xref: /titanic_50/usr/src/cmd/fs.d/smbclnt/mount/mount.c (revision 1a4cea1bca45d5775aeb88646a63db027947246f)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2000-2001, Boris Popov
34bff34e3Sthurlow  * All rights reserved.
44bff34e3Sthurlow  *
54bff34e3Sthurlow  * Redistribution and use in source and binary forms, with or without
64bff34e3Sthurlow  * modification, are permitted provided that the following conditions
74bff34e3Sthurlow  * are met:
84bff34e3Sthurlow  * 1. Redistributions of source code must retain the above copyright
94bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer.
104bff34e3Sthurlow  * 2. Redistributions in binary form must reproduce the above copyright
114bff34e3Sthurlow  *    notice, this list of conditions and the following disclaimer in the
124bff34e3Sthurlow  *    documentation and/or other materials provided with the distribution.
134bff34e3Sthurlow  * 3. All advertising materials mentioning features or use of this software
144bff34e3Sthurlow  *    must display the following acknowledgement:
154bff34e3Sthurlow  *    This product includes software developed by Boris Popov.
164bff34e3Sthurlow  * 4. Neither the name of the author nor the names of any co-contributors
174bff34e3Sthurlow  *    may be used to endorse or promote products derived from this software
184bff34e3Sthurlow  *    without specific prior written permission.
194bff34e3Sthurlow  *
204bff34e3Sthurlow  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
214bff34e3Sthurlow  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
224bff34e3Sthurlow  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
234bff34e3Sthurlow  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
244bff34e3Sthurlow  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
254bff34e3Sthurlow  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
264bff34e3Sthurlow  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
274bff34e3Sthurlow  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
284bff34e3Sthurlow  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
294bff34e3Sthurlow  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
304bff34e3Sthurlow  * SUCH DAMAGE.
314bff34e3Sthurlow  *
324bff34e3Sthurlow  * $Id: mount_smbfs.c,v 1.28.44.2 2005/06/02 00:55:41 lindak Exp $
334bff34e3Sthurlow  */
344bff34e3Sthurlow 
354bff34e3Sthurlow /*
36bd7c6f51SGordon Ross  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
374bff34e3Sthurlow  * Use is subject to license terms.
384d925e45SGordon Ross  *
3915c4b7fcSGordon Ross  * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
404bff34e3Sthurlow  */
414bff34e3Sthurlow 
424bff34e3Sthurlow #include <stdio.h>
434bff34e3Sthurlow #include <string.h>
444bff34e3Sthurlow #include <strings.h>
454bff34e3Sthurlow #include <pwd.h>
464bff34e3Sthurlow #include <grp.h>
474bff34e3Sthurlow #include <unistd.h>
484bff34e3Sthurlow #include <ctype.h>
494bff34e3Sthurlow #include <stdlib.h>
504bff34e3Sthurlow #include <errno.h>
514bff34e3Sthurlow #include <err.h>
524bff34e3Sthurlow #include <libintl.h>
534bff34e3Sthurlow #include <locale.h>
544bff34e3Sthurlow #include <libscf.h>
5542d15982SGordon Ross #include <priv_utils.h>
564bff34e3Sthurlow 
57613a2f6bSGordon Ross #include <sys/types.h>
58613a2f6bSGordon Ross #include <sys/stat.h>
59613a2f6bSGordon Ross #include <sys/errno.h>
60613a2f6bSGordon Ross #include <sys/mount.h>
614bff34e3Sthurlow #include <sys/mntent.h>
624bff34e3Sthurlow #include <sys/mnttab.h>
634bff34e3Sthurlow 
644bff34e3Sthurlow #include <sys/fs/smbfs_mount.h>
654bff34e3Sthurlow 
6602d09e03SGordon Ross /* This needs to know ctx->ct_dev_fd, etc. */
6702d09e03SGordon Ross #include <netsmb/smb_lib.h>
684bff34e3Sthurlow 
69613a2f6bSGordon Ross extern char *optarg;
70613a2f6bSGordon Ross extern int optind;
71613a2f6bSGordon Ross 
724bff34e3Sthurlow static char mount_point[MAXPATHLEN + 1];
734bff34e3Sthurlow static void usage(void);
7402d09e03SGordon Ross static int setsubopt(smb_ctx_t *, struct smbfs_args *, char *);
754bff34e3Sthurlow 
7602d09e03SGordon Ross const char * const optlist[] = {
774bff34e3Sthurlow 
7802d09e03SGordon Ross 	/* Generic VFS options. */
7902d09e03SGordon Ross #define	OPT_RO		0
8002d09e03SGordon Ross 	MNTOPT_RO,
8102d09e03SGordon Ross #define	OPT_RW		1
8202d09e03SGordon Ross 	MNTOPT_RW,
8302d09e03SGordon Ross #define	OPT_SUID 	2
8402d09e03SGordon Ross 	MNTOPT_SUID,
8502d09e03SGordon Ross #define	OPT_NOSUID 	3
8602d09e03SGordon Ross 	MNTOPT_NOSUID,
8702d09e03SGordon Ross #define	OPT_DEVICES	4
8802d09e03SGordon Ross 	MNTOPT_DEVICES,
8902d09e03SGordon Ross #define	OPT_NODEVICES	5
9002d09e03SGordon Ross 	MNTOPT_NODEVICES,
9102d09e03SGordon Ross #define	OPT_SETUID	6
9202d09e03SGordon Ross 	MNTOPT_SETUID,
9302d09e03SGordon Ross #define	OPT_NOSETUID	7
9402d09e03SGordon Ross 	MNTOPT_NOSETUID,
9502d09e03SGordon Ross #define	OPT_EXEC	8
9602d09e03SGordon Ross 	MNTOPT_EXEC,
9702d09e03SGordon Ross #define	OPT_NOEXEC	9
9802d09e03SGordon Ross 	MNTOPT_NOEXEC,
99*1a4cea1bSArne Jansen #define	OPT_FOLLOW	10
100*1a4cea1bSArne Jansen 	MNTOPT_FOLLOW,
101*1a4cea1bSArne Jansen #define	OPT_NOFOLLOW	11
102*1a4cea1bSArne Jansen 	MNTOPT_NOFOLLOW,
103*1a4cea1bSArne Jansen #define	OPT_XATTR	12
10402d09e03SGordon Ross 	MNTOPT_XATTR,
105*1a4cea1bSArne Jansen #define	OPT_NOXATTR	13
10602d09e03SGordon Ross 	MNTOPT_NOXATTR,
1074bff34e3Sthurlow 
10802d09e03SGordon Ross 	/* Sort of generic (from NFS) */
109*1a4cea1bSArne Jansen #define	OPT_NOAC	14
11002d09e03SGordon Ross 	MNTOPT_NOAC,
111*1a4cea1bSArne Jansen #define	OPT_ACTIMEO	15
11202d09e03SGordon Ross 	MNTOPT_ACTIMEO,
113*1a4cea1bSArne Jansen #define	OPT_ACREGMIN	16
11402d09e03SGordon Ross 	MNTOPT_ACREGMIN,
115*1a4cea1bSArne Jansen #define	OPT_ACREGMAX	17
11602d09e03SGordon Ross 	MNTOPT_ACREGMAX,
117*1a4cea1bSArne Jansen #define	OPT_ACDIRMIN	18
11802d09e03SGordon Ross 	MNTOPT_ACDIRMIN,
119*1a4cea1bSArne Jansen #define	OPT_ACDIRMAX	19
12002d09e03SGordon Ross 	MNTOPT_ACDIRMAX,
1214bff34e3Sthurlow 
12202d09e03SGordon Ross 	/* smbfs-specifis options */
123*1a4cea1bSArne Jansen #define	OPT_DOMAIN	20
12402d09e03SGordon Ross 	"domain",
125*1a4cea1bSArne Jansen #define	OPT_USER	21
12602d09e03SGordon Ross 	"user",
127*1a4cea1bSArne Jansen #define	OPT_UID		22
12802d09e03SGordon Ross 	"uid",
129*1a4cea1bSArne Jansen #define	OPT_GID		23
13002d09e03SGordon Ross 	"gid",
131*1a4cea1bSArne Jansen #define	OPT_DIRPERMS	24
13202d09e03SGordon Ross 	"dirperms",
133*1a4cea1bSArne Jansen #define	OPT_FILEPERMS	25
13402d09e03SGordon Ross 	"fileperms",
135*1a4cea1bSArne Jansen #define	OPT_NOPROMPT	26
13602d09e03SGordon Ross 	"noprompt",
137*1a4cea1bSArne Jansen #define	OPT_ACL		27
138bd7c6f51SGordon Ross 	MNTOPT_ACL,
139*1a4cea1bSArne Jansen #define	OPT_NOACL	28
140bd7c6f51SGordon Ross 	MNTOPT_NOACL,
1414bff34e3Sthurlow 
14202d09e03SGordon Ross 	NULL
1434bff34e3Sthurlow };
1444bff34e3Sthurlow 
1454bff34e3Sthurlow static int Oflg = 0;    /* Overlay mounts */
1464bff34e3Sthurlow static int qflg = 0;    /* quiet - don't print warnings on bad options */
1474bff34e3Sthurlow static int noprompt = 0;	/* don't prompt for password */
1484bff34e3Sthurlow 
14902d09e03SGordon Ross /* Note: smbfs uses _both_ kinds of options. */
15002d09e03SGordon Ross static int mntflags = MS_DATA | MS_OPTIONSTR;
15102d09e03SGordon Ross 
15202d09e03SGordon Ross #define	EX_OK	0	/* normal */
15302d09e03SGordon Ross #define	EX_OPT	1	/* bad options, usage, etc */
15402d09e03SGordon Ross #define	EX_MNT	2	/* mount point problems, etc */
15502d09e03SGordon Ross #define	RET_ERR	3	/* later errors */
15602d09e03SGordon Ross 
1574bff34e3Sthurlow #define	SERVICE "svc:/network/smb/client:default"
1584bff34e3Sthurlow 
159613a2f6bSGordon Ross struct smbfs_args mdata;
160613a2f6bSGordon Ross struct mnttab mnt;
16102d09e03SGordon Ross 
16202d09e03SGordon Ross /*
16302d09e03SGordon Ross  * Initialize this with "rw" just to have something there,
16402d09e03SGordon Ross  * so we don't have to decide whether to add a comma when
16502d09e03SGordon Ross  * we strcat another option.  Note the "rw" may be changed
16602d09e03SGordon Ross  * to an "ro" by option processing.
16702d09e03SGordon Ross  */
16802d09e03SGordon Ross char optbuf[MAX_MNTOPT_STR] = "rw";
16915c4b7fcSGordon Ross char special[MAXPATHLEN];
170613a2f6bSGordon Ross 
1714bff34e3Sthurlow int
main(int argc,char * argv[])1724bff34e3Sthurlow main(int argc, char *argv[])
1734bff34e3Sthurlow {
174613a2f6bSGordon Ross 	struct smb_ctx *ctx = NULL;
1754bff34e3Sthurlow 	struct stat st;
17602d09e03SGordon Ross 	int opt, error, err2;
1774bff34e3Sthurlow 	static char *fstype = MNTTYPE_SMBFS;
1784d925e45SGordon Ross 	char *env;
1794bff34e3Sthurlow 
1804bff34e3Sthurlow 	(void) setlocale(LC_ALL, "");
1814bff34e3Sthurlow #if !defined(TEXT_DOMAIN)
1824bff34e3Sthurlow #define	TEXT_DOMAIN	"SYS_TEST"
1834bff34e3Sthurlow #endif
1844bff34e3Sthurlow 	(void) textdomain(TEXT_DOMAIN);
18542d15982SGordon Ross 
18642d15982SGordon Ross 	/*
18742d15982SGordon Ross 	 * Normal users are allowed to run "mount -F smbfs ..."
18842d15982SGordon Ross 	 * to mount on a directory they own.  To allow that, this
18942d15982SGordon Ross 	 * program is installed setuid root, and it adds SYS_MOUNT
19042d15982SGordon Ross 	 * privilege here (if needed), and then restores the user's
19142d15982SGordon Ross 	 * normal privileges.  When root runs this, it's a no-op.
19242d15982SGordon Ross 	 */
19342d15982SGordon Ross 	if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
19442d15982SGordon Ross 		(void) fprintf(stderr,
19542d15982SGordon Ross 		    gettext("Insufficient privileges, "
19642d15982SGordon Ross 		    "%s must be set-uid root\n"), argv[0]);
19742d15982SGordon Ross 		exit(RET_ERR);
19842d15982SGordon Ross 	}
19942d15982SGordon Ross 
2004bff34e3Sthurlow 	if (argc == 2) {
2014bff34e3Sthurlow 		if (strcmp(argv[1], "-h") == 0) {
2024bff34e3Sthurlow 			usage();
2034bff34e3Sthurlow 		} else if (strcmp(argv[1], "-v") == 0) {
2044bff34e3Sthurlow 			errx(EX_OK, gettext("version %d.%d.%d"),
2054bff34e3Sthurlow 			    SMBFS_VERSION / 100000,
2064bff34e3Sthurlow 			    (SMBFS_VERSION % 10000) / 1000,
2074bff34e3Sthurlow 			    (SMBFS_VERSION % 1000) / 100);
2084bff34e3Sthurlow 		}
2094bff34e3Sthurlow 	}
2104bff34e3Sthurlow 	if (argc < 3)
2114bff34e3Sthurlow 		usage();
2124bff34e3Sthurlow 
2134bff34e3Sthurlow 	/* Debugging support. */
2144bff34e3Sthurlow 	if ((env = getenv("SMBFS_DEBUG")) != NULL) {
2154bff34e3Sthurlow 		smb_debug = atoi(env);
2164bff34e3Sthurlow 		if (smb_debug < 1)
2174bff34e3Sthurlow 			smb_debug = 1;
2184bff34e3Sthurlow 	}
2194bff34e3Sthurlow 
2204bff34e3Sthurlow 	error = smb_lib_init();
2214bff34e3Sthurlow 	if (error)
222613a2f6bSGordon Ross 		exit(RET_ERR);
2234bff34e3Sthurlow 
2244bff34e3Sthurlow 	mnt.mnt_mntopts = optbuf;
225613a2f6bSGordon Ross 
2264bff34e3Sthurlow 	bzero(&mdata, sizeof (mdata));
227613a2f6bSGordon Ross 	mdata.version = SMBFS_VERSION;		/* smbfs mount version */
2284bff34e3Sthurlow 	mdata.uid = (uid_t)-1;
2294bff34e3Sthurlow 	mdata.gid = (gid_t)-1;
2304bff34e3Sthurlow 
231613a2f6bSGordon Ross 	error = smb_ctx_alloc(&ctx);
2324bff34e3Sthurlow 	if (error)
233613a2f6bSGordon Ross 		exit(RET_ERR);
234613a2f6bSGordon Ross 
235613a2f6bSGordon Ross 	/*
236613a2f6bSGordon Ross 	 * Parse the UNC path so we have the server (etc.)
237613a2f6bSGordon Ross 	 * that we need during rcfile+sharectl parsing.
238613a2f6bSGordon Ross 	 */
239613a2f6bSGordon Ross 	if (argc < 3)
240613a2f6bSGordon Ross 		usage();
241613a2f6bSGordon Ross 	error = smb_ctx_parseunc(ctx, argv[argc - 2],
242613a2f6bSGordon Ross 	    SMBL_SHARE, SMBL_SHARE, USE_DISKDEV, NULL);
243613a2f6bSGordon Ross 	if (error)
24402d09e03SGordon Ross 		exit(EX_OPT);
245613a2f6bSGordon Ross 
2464bff34e3Sthurlow 	error = smb_ctx_readrc(ctx);
2474bff34e3Sthurlow 	if (error)
24802d09e03SGordon Ross 		exit(EX_OPT);
2494bff34e3Sthurlow 
2504bff34e3Sthurlow 	while ((opt = getopt(argc, argv, "ro:Oq")) != -1) {
2514bff34e3Sthurlow 		switch (opt) {
2524bff34e3Sthurlow 		case 'O':
2534bff34e3Sthurlow 			Oflg++;
2544bff34e3Sthurlow 			break;
2554bff34e3Sthurlow 
2564bff34e3Sthurlow 		case 'q':
2574bff34e3Sthurlow 			qflg++;
2584bff34e3Sthurlow 			break;
2594bff34e3Sthurlow 
2604bff34e3Sthurlow 		case 'r':
26102d09e03SGordon Ross 			mntflags |= MS_RDONLY;
2624bff34e3Sthurlow 			break;
2634bff34e3Sthurlow 
2644bff34e3Sthurlow 		case 'o': {
26502d09e03SGordon Ross 			char *nextopt, *comma, *sopt;
26602d09e03SGordon Ross 			int ret;
2674bff34e3Sthurlow 
2684bff34e3Sthurlow 			for (sopt = optarg; sopt != NULL; sopt = nextopt) {
2694bff34e3Sthurlow 				comma = strchr(sopt, ',');
2704bff34e3Sthurlow 				if (comma) {
2714bff34e3Sthurlow 					nextopt = comma + 1;
2724bff34e3Sthurlow 					*comma = '\0';
2734bff34e3Sthurlow 				} else
2744bff34e3Sthurlow 					nextopt = NULL;
27502d09e03SGordon Ross 				ret = setsubopt(ctx, &mdata, sopt);
2764bff34e3Sthurlow 				if (ret != 0)
27702d09e03SGordon Ross 					exit(EX_OPT);
27802d09e03SGordon Ross 				/* undo changes to optarg */
2794bff34e3Sthurlow 				if (comma)
2804bff34e3Sthurlow 					*comma = ',';
2814bff34e3Sthurlow 			}
2824bff34e3Sthurlow 			break;
2834bff34e3Sthurlow 		}
2844bff34e3Sthurlow 
2854bff34e3Sthurlow 		case '?':
2864bff34e3Sthurlow 		default:
2874bff34e3Sthurlow 			usage();
2884bff34e3Sthurlow 		}
2894bff34e3Sthurlow 	}
2904bff34e3Sthurlow 
2914bff34e3Sthurlow 	if (Oflg)
2924bff34e3Sthurlow 		mntflags |= MS_OVERLAY;
2934bff34e3Sthurlow 
29402d09e03SGordon Ross 	if (mntflags & MS_RDONLY) {
2954bff34e3Sthurlow 		char *p;
2964bff34e3Sthurlow 		/* convert "rw"->"ro" */
29702d09e03SGordon Ross 		if (p = strstr(optbuf, "rw")) {
2984bff34e3Sthurlow 			if (*(p+2) == ',' || *(p+2) == '\0')
2994bff34e3Sthurlow 				*(p+1) = 'o';
3004bff34e3Sthurlow 		}
3014bff34e3Sthurlow 	}
3024bff34e3Sthurlow 
303613a2f6bSGordon Ross 	if (optind + 2 != argc)
304613a2f6bSGordon Ross 		usage();
305613a2f6bSGordon Ross 
30615c4b7fcSGordon Ross 	(void) snprintf(special, sizeof (special), "//%s/%s",
30715c4b7fcSGordon Ross 	    ctx->ct_fullserver, ctx->ct_origshare);
30815c4b7fcSGordon Ross 
30915c4b7fcSGordon Ross 	mnt.mnt_special = special;
3104bff34e3Sthurlow 	mnt.mnt_mountp = argv[optind+1];
3114bff34e3Sthurlow 
3124d925e45SGordon Ross 	if ((realpath(argv[optind+1], mount_point) == NULL) ||
3134d925e45SGordon Ross 	    (stat(mount_point, &st) == -1)) {
31402d09e03SGordon Ross 		err(EX_MNT, gettext("could not find mount point %s"),
3154d925e45SGordon Ross 		    argv[optind+1]);
3164d925e45SGordon Ross 	}
3174bff34e3Sthurlow 	if (!S_ISDIR(st.st_mode)) {
3184bff34e3Sthurlow 		errno = ENOTDIR;
31902d09e03SGordon Ross 		err(EX_MNT, gettext("can't mount on %s"), mount_point);
3204bff34e3Sthurlow 	}
3214bff34e3Sthurlow 
3224bff34e3Sthurlow 	/*
3232f5e3e91SGordon Ross 	 * Fill in mdata defaults.
3244bff34e3Sthurlow 	 */
3254bff34e3Sthurlow 	if (mdata.uid == (uid_t)-1)
3264bff34e3Sthurlow 		mdata.uid = getuid();
3274bff34e3Sthurlow 	if (mdata.gid == (gid_t)-1)
3284bff34e3Sthurlow 		mdata.gid = getgid();
3294bff34e3Sthurlow 	if (mdata.file_mode == 0)
3302f5e3e91SGordon Ross 		mdata.file_mode = S_IRWXU;
3314bff34e3Sthurlow 	if (mdata.dir_mode == 0) {
3324bff34e3Sthurlow 		mdata.dir_mode = mdata.file_mode;
3334bff34e3Sthurlow 		if (mdata.dir_mode & S_IRUSR)
3344bff34e3Sthurlow 			mdata.dir_mode |= S_IXUSR;
3354bff34e3Sthurlow 		if (mdata.dir_mode & S_IRGRP)
3364bff34e3Sthurlow 			mdata.dir_mode |= S_IXGRP;
3374bff34e3Sthurlow 		if (mdata.dir_mode & S_IROTH)
3384bff34e3Sthurlow 			mdata.dir_mode |= S_IXOTH;
3394bff34e3Sthurlow 	}
3404bff34e3Sthurlow 
341613a2f6bSGordon Ross 	ctx->ct_ssn.ssn_owner = SMBM_ANY_OWNER;
3424bff34e3Sthurlow 	if (noprompt)
3434bff34e3Sthurlow 		ctx->ct_flags |= SMBCF_NOPWD;
3444bff34e3Sthurlow 
3454bff34e3Sthurlow 	/*
346613a2f6bSGordon Ross 	 * Resolve the server address,
347613a2f6bSGordon Ross 	 * setup derived defaults.
3484bff34e3Sthurlow 	 */
3494bff34e3Sthurlow 	error = smb_ctx_resolve(ctx);
3504bff34e3Sthurlow 	if (error)
351613a2f6bSGordon Ross 		exit(RET_ERR);
3524bff34e3Sthurlow 
353613a2f6bSGordon Ross 	/*
354613a2f6bSGordon Ross 	 * Have server, share, etc. from above:
355613a2f6bSGordon Ross 	 * smb_ctx_scan_argv, option settings.
356613a2f6bSGordon Ross 	 * Get the session and tree.
357613a2f6bSGordon Ross 	 */
3584bff34e3Sthurlow again:
359613a2f6bSGordon Ross 	error = smb_ctx_get_ssn(ctx);
360613a2f6bSGordon Ross 	if (error == EAUTH && noprompt == 0) {
361613a2f6bSGordon Ross 		err2 = smb_get_authentication(ctx);
362613a2f6bSGordon Ross 		if (err2 == 0)
363613a2f6bSGordon Ross 			goto again;
3644bff34e3Sthurlow 	}
365613a2f6bSGordon Ross 	if (error) {
366613a2f6bSGordon Ross 		smb_error(gettext("//%s: login failed"),
367613a2f6bSGordon Ross 		    error, ctx->ct_fullserver);
368613a2f6bSGordon Ross 		exit(RET_ERR);
3694bff34e3Sthurlow 	}
3704bff34e3Sthurlow 
371613a2f6bSGordon Ross 	error = smb_ctx_get_tree(ctx);
372613a2f6bSGordon Ross 	if (error) {
373613a2f6bSGordon Ross 		smb_error(gettext("//%s/%s: tree connect failed"),
374613a2f6bSGordon Ross 		    error, ctx->ct_fullserver, ctx->ct_origshare);
375613a2f6bSGordon Ross 		exit(RET_ERR);
376613a2f6bSGordon Ross 	}
3774bff34e3Sthurlow 
378613a2f6bSGordon Ross 	/*
379613a2f6bSGordon Ross 	 * Have tree connection, now mount it.
380613a2f6bSGordon Ross 	 */
381613a2f6bSGordon Ross 	mdata.devfd = ctx->ct_dev_fd;
382613a2f6bSGordon Ross 
38342d15982SGordon Ross 	/* Need sys_mount privilege for the mount call. */
38442d15982SGordon Ross 	(void) __priv_bracket(PRIV_ON);
38542d15982SGordon Ross 	err2 = mount(mnt.mnt_special, mnt.mnt_mountp,
3864bff34e3Sthurlow 	    mntflags, fstype, &mdata, sizeof (mdata),
38742d15982SGordon Ross 	    mnt.mnt_mntopts, MAX_MNTOPT_STR);
38842d15982SGordon Ross 	(void) __priv_bracket(PRIV_OFF);
38942d15982SGordon Ross 
39042d15982SGordon Ross 	if (err2 < 0) {
3914bff34e3Sthurlow 		if (errno != ENOENT) {
39202d09e03SGordon Ross 			err(EX_MNT, gettext("mount_smbfs: %s"),
393613a2f6bSGordon Ross 			    mnt.mnt_mountp);
3944bff34e3Sthurlow 		} else {
3954bff34e3Sthurlow 			struct stat sb;
396613a2f6bSGordon Ross 			if (stat(mnt.mnt_mountp, &sb) < 0 &&
3974bff34e3Sthurlow 			    errno == ENOENT)
39802d09e03SGordon Ross 				err(EX_MNT, gettext("mount_smbfs: %s"),
399613a2f6bSGordon Ross 				    mnt.mnt_mountp);
4004bff34e3Sthurlow 			else
40102d09e03SGordon Ross 				err(EX_MNT, gettext("mount_smbfs: %s"),
402613a2f6bSGordon Ross 				    mnt.mnt_special);
4034bff34e3Sthurlow 		}
4044bff34e3Sthurlow 	}
4054bff34e3Sthurlow 
406613a2f6bSGordon Ross 	smb_ctx_free(ctx);
4074bff34e3Sthurlow 	return (0);
4084bff34e3Sthurlow }
4094bff34e3Sthurlow 
41002d09e03SGordon Ross #define	bad(val) (val == NULL || !isdigit(*val))
41102d09e03SGordon Ross 
4124bff34e3Sthurlow int
setsubopt(smb_ctx_t * ctx,struct smbfs_args * mdatap,char * subopt)41302d09e03SGordon Ross setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, char *subopt)
4144bff34e3Sthurlow {
41502d09e03SGordon Ross 	char *equals, *optarg;
4164bff34e3Sthurlow 	struct passwd *pwd;
4174bff34e3Sthurlow 	struct group *grp;
41802d09e03SGordon Ross 	long val;
41902d09e03SGordon Ross 	int rc = EX_OK;
42002d09e03SGordon Ross 	int index;
42102d09e03SGordon Ross 	char *p;
42202d09e03SGordon Ross 
42302d09e03SGordon Ross 	equals = strchr(subopt, '=');
42402d09e03SGordon Ross 	if (equals) {
42502d09e03SGordon Ross 		*equals = '\0';
42602d09e03SGordon Ross 		optarg = equals + 1;
42702d09e03SGordon Ross 	} else
42802d09e03SGordon Ross 		optarg = NULL;
42902d09e03SGordon Ross 
43002d09e03SGordon Ross 	for (index = 0; optlist[index] != NULL; index++) {
43102d09e03SGordon Ross 		if (strcmp(subopt, optlist[index]) == 0)
43202d09e03SGordon Ross 			break;
43302d09e03SGordon Ross 	}
43402d09e03SGordon Ross 
43502d09e03SGordon Ross 	/*
43602d09e03SGordon Ross 	 * Note: if the option was unknown, index will
43702d09e03SGordon Ross 	 * point to the NULL at the end of optlist[],
43802d09e03SGordon Ross 	 * and we'll take the switch default.
43902d09e03SGordon Ross 	 */
4404bff34e3Sthurlow 
4414bff34e3Sthurlow 	switch (index) {
44202d09e03SGordon Ross 
443bd7c6f51SGordon Ross 	case OPT_ACL:
444bd7c6f51SGordon Ross 	case OPT_NOACL:
4454bff34e3Sthurlow 	case OPT_SUID:
4464bff34e3Sthurlow 	case OPT_NOSUID:
4474bff34e3Sthurlow 	case OPT_DEVICES:
4484bff34e3Sthurlow 	case OPT_NODEVICES:
4494bff34e3Sthurlow 	case OPT_SETUID:
4504bff34e3Sthurlow 	case OPT_NOSETUID:
4514bff34e3Sthurlow 	case OPT_EXEC:
4524bff34e3Sthurlow 	case OPT_NOEXEC:
453*1a4cea1bSArne Jansen 	case OPT_FOLLOW:
454*1a4cea1bSArne Jansen 	case OPT_NOFOLLOW:
45502d09e03SGordon Ross 	case OPT_XATTR:
45602d09e03SGordon Ross 	case OPT_NOXATTR:
45702d09e03SGordon Ross 		/*
45802d09e03SGordon Ross 		 * These options are handled via the
45902d09e03SGordon Ross 		 * generic option string mechanism.
46002d09e03SGordon Ross 		 * None of these take an optarg.
46102d09e03SGordon Ross 		 */
46202d09e03SGordon Ross 		if (optarg != NULL)
46302d09e03SGordon Ross 			goto badval;
46402d09e03SGordon Ross 		(void) strlcat(optbuf, ",", sizeof (optbuf));
46502d09e03SGordon Ross 		if (strlcat(optbuf, subopt, sizeof (optbuf)) >=
46602d09e03SGordon Ross 		    sizeof (optbuf)) {
46702d09e03SGordon Ross 			if (!qflg)
46802d09e03SGordon Ross 				warnx(gettext("option string too long"));
46902d09e03SGordon Ross 			rc = EX_OPT;
47002d09e03SGordon Ross 		}
47102d09e03SGordon Ross 		break;
472613a2f6bSGordon Ross 
47302d09e03SGordon Ross 	/*
47402d09e03SGordon Ross 	 * OPT_RO, OPT_RW, are actually generic too,
47502d09e03SGordon Ross 	 * but we use the mntflags for these, and
47602d09e03SGordon Ross 	 * then update the options string later.
47702d09e03SGordon Ross 	 */
47802d09e03SGordon Ross 	case OPT_RO:
47902d09e03SGordon Ross 		mntflags |= MS_RDONLY;
48002d09e03SGordon Ross 		break;
48102d09e03SGordon Ross 	case OPT_RW:
48202d09e03SGordon Ross 		mntflags &= ~MS_RDONLY;
48302d09e03SGordon Ross 		break;
48402d09e03SGordon Ross 
48502d09e03SGordon Ross 	/*
48602d09e03SGordon Ross 	 * NFS-derived options for attribute cache
48702d09e03SGordon Ross 	 * handling (disable, set min/max timeouts)
48802d09e03SGordon Ross 	 */
48902d09e03SGordon Ross 	case OPT_NOAC:
49002d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_NOAC;
49102d09e03SGordon Ross 		break;
49202d09e03SGordon Ross 
49302d09e03SGordon Ross 	case OPT_ACTIMEO:
49402d09e03SGordon Ross 		errno = 0;
49502d09e03SGordon Ross 		val = strtol(optarg, &p, 10);
49602d09e03SGordon Ross 		if (errno || *p != 0)
49702d09e03SGordon Ross 			goto badval;
49802d09e03SGordon Ross 		mdatap->acdirmin = mdatap->acregmin = val;
49902d09e03SGordon Ross 		mdatap->acdirmax = mdatap->acregmax = val;
50002d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACDIRMAX;
50102d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACREGMAX;
50202d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACDIRMIN;
50302d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACREGMIN;
50402d09e03SGordon Ross 		break;
50502d09e03SGordon Ross 
50602d09e03SGordon Ross 	case OPT_ACREGMIN:
50702d09e03SGordon Ross 		errno = 0;
50802d09e03SGordon Ross 		val = strtol(optarg, &p, 10);
50902d09e03SGordon Ross 		if (errno || *p != 0)
51002d09e03SGordon Ross 			goto badval;
51102d09e03SGordon Ross 		mdatap->acregmin = val;
51202d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACREGMIN;
51302d09e03SGordon Ross 		break;
51402d09e03SGordon Ross 
51502d09e03SGordon Ross 	case OPT_ACREGMAX:
51602d09e03SGordon Ross 		errno = 0;
51702d09e03SGordon Ross 		val = strtol(optarg, &p, 10);
51802d09e03SGordon Ross 		if (errno || *p != 0)
51902d09e03SGordon Ross 			goto badval;
52002d09e03SGordon Ross 		mdatap->acregmax = val;
52102d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACREGMAX;
52202d09e03SGordon Ross 		break;
52302d09e03SGordon Ross 
52402d09e03SGordon Ross 	case OPT_ACDIRMIN:
52502d09e03SGordon Ross 		errno = 0;
52602d09e03SGordon Ross 		val = strtol(optarg, &p, 10);
52702d09e03SGordon Ross 		if (errno || *p != 0)
52802d09e03SGordon Ross 			goto badval;
52902d09e03SGordon Ross 		mdatap->acdirmin = val;
53002d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACDIRMIN;
53102d09e03SGordon Ross 		break;
53202d09e03SGordon Ross 
53302d09e03SGordon Ross 	case OPT_ACDIRMAX:
53402d09e03SGordon Ross 		errno = 0;
53502d09e03SGordon Ross 		val = strtol(optarg, &p, 10);
53602d09e03SGordon Ross 		if (errno || *p != 0)
53702d09e03SGordon Ross 			goto badval;
53802d09e03SGordon Ross 		mdatap->acdirmax = val;
53902d09e03SGordon Ross 		mdatap->flags |= SMBFS_MF_ACDIRMAX;
54002d09e03SGordon Ross 		break;
54102d09e03SGordon Ross 
54202d09e03SGordon Ross 	/*
54302d09e03SGordon Ross 	 * SMBFS-specific options.  Some of these
54402d09e03SGordon Ross 	 * don't go through the mount system call,
54502d09e03SGordon Ross 	 * but just set libsmbfs options.
54602d09e03SGordon Ross 	 */
547613a2f6bSGordon Ross 	case OPT_DOMAIN:
54802d09e03SGordon Ross 		if (smb_ctx_setdomain(ctx, optarg, B_TRUE) != 0)
54902d09e03SGordon Ross 			rc = EX_OPT;
550613a2f6bSGordon Ross 		break;
551613a2f6bSGordon Ross 
552613a2f6bSGordon Ross 	case OPT_USER:
55302d09e03SGordon Ross 		if (smb_ctx_setuser(ctx, optarg, B_TRUE) != 0)
55402d09e03SGordon Ross 			rc = EX_OPT;
555613a2f6bSGordon Ross 		break;
556613a2f6bSGordon Ross 
5574bff34e3Sthurlow 	case OPT_UID:
5584bff34e3Sthurlow 		pwd = isdigit(optarg[0]) ?
5594bff34e3Sthurlow 		    getpwuid(atoi(optarg)) : getpwnam(optarg);
5604bff34e3Sthurlow 		if (pwd == NULL) {
5614bff34e3Sthurlow 			if (!qflg)
5624bff34e3Sthurlow 				warnx(gettext("unknown user '%s'"), optarg);
56302d09e03SGordon Ross 			rc = EX_OPT;
5644bff34e3Sthurlow 		} else {
5654bff34e3Sthurlow 			mdatap->uid = pwd->pw_uid;
5664bff34e3Sthurlow 		}
5674bff34e3Sthurlow 		break;
56802d09e03SGordon Ross 
5694bff34e3Sthurlow 	case OPT_GID:
5704bff34e3Sthurlow 		grp = isdigit(optarg[0]) ?
5714bff34e3Sthurlow 		    getgrgid(atoi(optarg)) : getgrnam(optarg);
5724bff34e3Sthurlow 		if (grp == NULL) {
5734bff34e3Sthurlow 			if (!qflg)
5744bff34e3Sthurlow 				warnx(gettext("unknown group '%s'"), optarg);
57502d09e03SGordon Ross 			rc = EX_OPT;
5764bff34e3Sthurlow 		} else {
5774bff34e3Sthurlow 			mdatap->gid = grp->gr_gid;
5784bff34e3Sthurlow 		}
5794bff34e3Sthurlow 		break;
58002d09e03SGordon Ross 
5814bff34e3Sthurlow 	case OPT_DIRPERMS:
5824bff34e3Sthurlow 		errno = 0;
58302d09e03SGordon Ross 		val = strtol(optarg, &p, 8);
58402d09e03SGordon Ross 		if (errno || *p != 0)
58502d09e03SGordon Ross 			goto badval;
58602d09e03SGordon Ross 		mdatap->dir_mode = val;
5874bff34e3Sthurlow 		break;
58802d09e03SGordon Ross 
5894bff34e3Sthurlow 	case OPT_FILEPERMS:
5904bff34e3Sthurlow 		errno = 0;
59102d09e03SGordon Ross 		val = strtol(optarg, &p, 8);
59202d09e03SGordon Ross 		if (errno || *p != 0)
59302d09e03SGordon Ross 			goto badval;
59402d09e03SGordon Ross 		mdatap->file_mode = val;
5954bff34e3Sthurlow 		break;
59602d09e03SGordon Ross 
5974bff34e3Sthurlow 	case OPT_NOPROMPT:
5984bff34e3Sthurlow 		noprompt++;
59902d09e03SGordon Ross 		break;
60002d09e03SGordon Ross 
60102d09e03SGordon Ross 	default:
602bd7c6f51SGordon Ross 	badopt:
60302d09e03SGordon Ross 		if (!qflg)
60402d09e03SGordon Ross 			warnx(gettext("unknown option %s"), subopt);
60502d09e03SGordon Ross 		rc = EX_OPT;
60602d09e03SGordon Ross 		break;
60702d09e03SGordon Ross 
60802d09e03SGordon Ross 	badval:
60902d09e03SGordon Ross 		if (!qflg)
61002d09e03SGordon Ross 			warnx(gettext("invalid value for %s"), subopt);
61102d09e03SGordon Ross 		rc = EX_OPT;
61202d09e03SGordon Ross 		break;
6134bff34e3Sthurlow 	}
61402d09e03SGordon Ross 
61502d09e03SGordon Ross 	/* Undo changes made to subopt */
61602d09e03SGordon Ross 	if (equals)
61702d09e03SGordon Ross 		*equals = '=';
61802d09e03SGordon Ross 
61902d09e03SGordon Ross 	return (rc);
6204bff34e3Sthurlow }
6214bff34e3Sthurlow 
6224bff34e3Sthurlow static void
usage(void)6234bff34e3Sthurlow usage(void)
6244bff34e3Sthurlow {
6254d925e45SGordon Ross 	(void) fprintf(stderr, "%s\n",
6264bff34e3Sthurlow 	gettext("usage: mount -F smbfs [-Orq] [-o option[,option]]"
6274bff34e3Sthurlow 	"	//[workgroup;][user[:password]@]server[/share] path"));
6284bff34e3Sthurlow 
62902d09e03SGordon Ross 	exit(EX_OPT);
6304bff34e3Sthurlow }
631