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 *
39*0463c800SGordon Ross * Copyright 2019 Nexenta by DDN, 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 *);
7502d09e03SGordon Ross
7602d09e03SGordon Ross const char * const optlist[] = {
7702d09e03SGordon Ross
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,
83*0463c800SGordon Ross #define OPT_SUID 2
8402d09e03SGordon Ross MNTOPT_SUID,
85*0463c800SGordon 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,
9902d09e03SGordon Ross #define OPT_XATTR 10
10002d09e03SGordon Ross MNTOPT_XATTR,
10102d09e03SGordon Ross #define OPT_NOXATTR 11
10202d09e03SGordon Ross MNTOPT_NOXATTR,
10302d09e03SGordon Ross
10402d09e03SGordon Ross /* Sort of generic (from NFS) */
10502d09e03SGordon Ross #define OPT_NOAC 12
10602d09e03SGordon Ross MNTOPT_NOAC,
10702d09e03SGordon Ross #define OPT_ACTIMEO 13
10802d09e03SGordon Ross MNTOPT_ACTIMEO,
10902d09e03SGordon Ross #define OPT_ACREGMIN 14
11002d09e03SGordon Ross MNTOPT_ACREGMIN,
11102d09e03SGordon Ross #define OPT_ACREGMAX 15
11202d09e03SGordon Ross MNTOPT_ACREGMAX,
11302d09e03SGordon Ross #define OPT_ACDIRMIN 16
11402d09e03SGordon Ross MNTOPT_ACDIRMIN,
11502d09e03SGordon Ross #define OPT_ACDIRMAX 17
11602d09e03SGordon Ross MNTOPT_ACDIRMAX,
11702d09e03SGordon Ross
11802d09e03SGordon Ross /* smbfs-specifis options */
11902d09e03SGordon Ross #define OPT_DOMAIN 18
12002d09e03SGordon Ross "domain",
12102d09e03SGordon Ross #define OPT_USER 19
12202d09e03SGordon Ross "user",
12302d09e03SGordon Ross #define OPT_UID 20
12402d09e03SGordon Ross "uid",
12502d09e03SGordon Ross #define OPT_GID 21
12602d09e03SGordon Ross "gid",
12702d09e03SGordon Ross #define OPT_DIRPERMS 22
12802d09e03SGordon Ross "dirperms",
12902d09e03SGordon Ross #define OPT_FILEPERMS 23
13002d09e03SGordon Ross "fileperms",
13102d09e03SGordon Ross #define OPT_NOPROMPT 24
13202d09e03SGordon Ross "noprompt",
133bd7c6f51SGordon Ross #define OPT_ACL 25
134bd7c6f51SGordon Ross MNTOPT_ACL,
135bd7c6f51SGordon Ross #define OPT_NOACL 26
136bd7c6f51SGordon Ross MNTOPT_NOACL,
13702d09e03SGordon Ross
13802d09e03SGordon Ross NULL
1394bff34e3Sthurlow };
1404bff34e3Sthurlow
1414bff34e3Sthurlow static int Oflg = 0; /* Overlay mounts */
1424bff34e3Sthurlow static int qflg = 0; /* quiet - don't print warnings on bad options */
1434bff34e3Sthurlow static int noprompt = 0; /* don't prompt for password */
1444bff34e3Sthurlow
14502d09e03SGordon Ross /* Note: smbfs uses _both_ kinds of options. */
14602d09e03SGordon Ross static int mntflags = MS_DATA | MS_OPTIONSTR;
14702d09e03SGordon Ross
14802d09e03SGordon Ross #define EX_OK 0 /* normal */
14902d09e03SGordon Ross #define EX_OPT 1 /* bad options, usage, etc */
15002d09e03SGordon Ross #define EX_MNT 2 /* mount point problems, etc */
15102d09e03SGordon Ross #define RET_ERR 3 /* later errors */
15202d09e03SGordon Ross
1534bff34e3Sthurlow #define SERVICE "svc:/network/smb/client:default"
1544bff34e3Sthurlow
155613a2f6bSGordon Ross struct smbfs_args mdata;
156613a2f6bSGordon Ross struct mnttab mnt;
15702d09e03SGordon Ross
15802d09e03SGordon Ross /*
15902d09e03SGordon Ross * Initialize this with "rw" just to have something there,
16002d09e03SGordon Ross * so we don't have to decide whether to add a comma when
16102d09e03SGordon Ross * we strcat another option. Note the "rw" may be changed
16202d09e03SGordon Ross * to an "ro" by option processing.
16302d09e03SGordon Ross */
16402d09e03SGordon Ross char optbuf[MAX_MNTOPT_STR] = "rw";
16515c4b7fcSGordon Ross char special[MAXPATHLEN];
166613a2f6bSGordon Ross
1674bff34e3Sthurlow int
main(int argc,char * argv[])1684bff34e3Sthurlow main(int argc, char *argv[])
1694bff34e3Sthurlow {
170613a2f6bSGordon Ross struct smb_ctx *ctx = NULL;
1714bff34e3Sthurlow struct stat st;
17202d09e03SGordon Ross int opt, error, err2;
1734bff34e3Sthurlow static char *fstype = MNTTYPE_SMBFS;
1744d925e45SGordon Ross char *env;
1754bff34e3Sthurlow
1764bff34e3Sthurlow (void) setlocale(LC_ALL, "");
1774bff34e3Sthurlow #if !defined(TEXT_DOMAIN)
1784bff34e3Sthurlow #define TEXT_DOMAIN "SYS_TEST"
1794bff34e3Sthurlow #endif
1804bff34e3Sthurlow (void) textdomain(TEXT_DOMAIN);
18142d15982SGordon Ross
18242d15982SGordon Ross /*
18342d15982SGordon Ross * Normal users are allowed to run "mount -F smbfs ..."
18442d15982SGordon Ross * to mount on a directory they own. To allow that, this
185*0463c800SGordon Ross * program has an exec_attr that adds SYS_MOUNT priv.
186*0463c800SGordon Ross *
187*0463c800SGordon Ross * The __init_suid_priv call was designed for SUID programs,
188*0463c800SGordon Ross * but also works for privileges granted via exec_attr with
189*0463c800SGordon Ross * one difference: the added privileges are already effective
190*0463c800SGordon Ross * when the program starts, and remain effective after the call.
191*0463c800SGordon Ross * To make this work more like the SUID case we'll turn off the
192*0463c800SGordon Ross * additional privileges with a __priv_bracket() call here.
193*0463c800SGordon Ross * Later calls to __priv_bracket() make the extra privileges
194*0463c800SGordon Ross * effective only when we need them.
19542d15982SGordon Ross */
19642d15982SGordon Ross if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
19742d15982SGordon Ross (void) fprintf(stderr,
19842d15982SGordon Ross gettext("Insufficient privileges, "
199*0463c800SGordon Ross "%s should have sys_mount privilege via exec_attr\n"),
200*0463c800SGordon Ross argv[0]);
20142d15982SGordon Ross exit(RET_ERR);
20242d15982SGordon Ross }
203*0463c800SGordon Ross (void) __priv_bracket(PRIV_OFF);
20442d15982SGordon Ross
2054bff34e3Sthurlow if (argc == 2) {
2064bff34e3Sthurlow if (strcmp(argv[1], "-h") == 0) {
2074bff34e3Sthurlow usage();
2084bff34e3Sthurlow } else if (strcmp(argv[1], "-v") == 0) {
2094bff34e3Sthurlow errx(EX_OK, gettext("version %d.%d.%d"),
2104bff34e3Sthurlow SMBFS_VERSION / 100000,
2114bff34e3Sthurlow (SMBFS_VERSION % 10000) / 1000,
2124bff34e3Sthurlow (SMBFS_VERSION % 1000) / 100);
2134bff34e3Sthurlow }
2144bff34e3Sthurlow }
2154bff34e3Sthurlow if (argc < 3)
2164bff34e3Sthurlow usage();
2174bff34e3Sthurlow
2184bff34e3Sthurlow /* Debugging support. */
2194bff34e3Sthurlow if ((env = getenv("SMBFS_DEBUG")) != NULL) {
2204bff34e3Sthurlow smb_debug = atoi(env);
2214bff34e3Sthurlow if (smb_debug < 1)
2224bff34e3Sthurlow smb_debug = 1;
2234bff34e3Sthurlow }
2244bff34e3Sthurlow
2254bff34e3Sthurlow error = smb_lib_init();
2264bff34e3Sthurlow if (error)
227613a2f6bSGordon Ross exit(RET_ERR);
2284bff34e3Sthurlow
2294bff34e3Sthurlow mnt.mnt_mntopts = optbuf;
230613a2f6bSGordon Ross
2314bff34e3Sthurlow bzero(&mdata, sizeof (mdata));
232613a2f6bSGordon Ross mdata.version = SMBFS_VERSION; /* smbfs mount version */
2334bff34e3Sthurlow mdata.uid = (uid_t)-1;
2344bff34e3Sthurlow mdata.gid = (gid_t)-1;
2354bff34e3Sthurlow
236613a2f6bSGordon Ross error = smb_ctx_alloc(&ctx);
2374bff34e3Sthurlow if (error)
238613a2f6bSGordon Ross exit(RET_ERR);
239613a2f6bSGordon Ross
240613a2f6bSGordon Ross /*
241613a2f6bSGordon Ross * Parse the UNC path so we have the server (etc.)
242613a2f6bSGordon Ross * that we need during rcfile+sharectl parsing.
243613a2f6bSGordon Ross */
244613a2f6bSGordon Ross if (argc < 3)
245613a2f6bSGordon Ross usage();
246613a2f6bSGordon Ross error = smb_ctx_parseunc(ctx, argv[argc - 2],
247613a2f6bSGordon Ross SMBL_SHARE, SMBL_SHARE, USE_DISKDEV, NULL);
248613a2f6bSGordon Ross if (error)
24902d09e03SGordon Ross exit(EX_OPT);
250613a2f6bSGordon Ross
2514bff34e3Sthurlow error = smb_ctx_readrc(ctx);
2524bff34e3Sthurlow if (error)
25302d09e03SGordon Ross exit(EX_OPT);
2544bff34e3Sthurlow
2554bff34e3Sthurlow while ((opt = getopt(argc, argv, "ro:Oq")) != -1) {
2564bff34e3Sthurlow switch (opt) {
2574bff34e3Sthurlow case 'O':
2584bff34e3Sthurlow Oflg++;
2594bff34e3Sthurlow break;
2604bff34e3Sthurlow
2614bff34e3Sthurlow case 'q':
2624bff34e3Sthurlow qflg++;
2634bff34e3Sthurlow break;
2644bff34e3Sthurlow
2654bff34e3Sthurlow case 'r':
26602d09e03SGordon Ross mntflags |= MS_RDONLY;
2674bff34e3Sthurlow break;
2684bff34e3Sthurlow
2694bff34e3Sthurlow case 'o': {
27002d09e03SGordon Ross char *nextopt, *comma, *sopt;
27102d09e03SGordon Ross int ret;
27202d09e03SGordon Ross
2734bff34e3Sthurlow for (sopt = optarg; sopt != NULL; sopt = nextopt) {
2744bff34e3Sthurlow comma = strchr(sopt, ',');
2754bff34e3Sthurlow if (comma) {
2764bff34e3Sthurlow nextopt = comma + 1;
2774bff34e3Sthurlow *comma = '\0';
2784bff34e3Sthurlow } else
2794bff34e3Sthurlow nextopt = NULL;
28002d09e03SGordon Ross ret = setsubopt(ctx, &mdata, sopt);
2814bff34e3Sthurlow if (ret != 0)
28202d09e03SGordon Ross exit(EX_OPT);
28302d09e03SGordon Ross /* undo changes to optarg */
2844bff34e3Sthurlow if (comma)
2854bff34e3Sthurlow *comma = ',';
2864bff34e3Sthurlow }
2874bff34e3Sthurlow break;
2884bff34e3Sthurlow }
2894bff34e3Sthurlow
2904bff34e3Sthurlow case '?':
2914bff34e3Sthurlow default:
2924bff34e3Sthurlow usage();
2934bff34e3Sthurlow }
2944bff34e3Sthurlow }
2954bff34e3Sthurlow
2964bff34e3Sthurlow if (Oflg)
2974bff34e3Sthurlow mntflags |= MS_OVERLAY;
2984bff34e3Sthurlow
29902d09e03SGordon Ross if (mntflags & MS_RDONLY) {
3004bff34e3Sthurlow char *p;
3014bff34e3Sthurlow /* convert "rw"->"ro" */
30202d09e03SGordon Ross if (p = strstr(optbuf, "rw")) {
3034bff34e3Sthurlow if (*(p+2) == ',' || *(p+2) == '\0')
3044bff34e3Sthurlow *(p+1) = 'o';
3054bff34e3Sthurlow }
3064bff34e3Sthurlow }
3074bff34e3Sthurlow
308613a2f6bSGordon Ross if (optind + 2 != argc)
309613a2f6bSGordon Ross usage();
310613a2f6bSGordon Ross
31115c4b7fcSGordon Ross (void) snprintf(special, sizeof (special), "//%s/%s",
31215c4b7fcSGordon Ross ctx->ct_fullserver, ctx->ct_origshare);
31315c4b7fcSGordon Ross
31415c4b7fcSGordon Ross mnt.mnt_special = special;
3154bff34e3Sthurlow mnt.mnt_mountp = argv[optind+1];
3164bff34e3Sthurlow
3174d925e45SGordon Ross if ((realpath(argv[optind+1], mount_point) == NULL) ||
3184d925e45SGordon Ross (stat(mount_point, &st) == -1)) {
31902d09e03SGordon Ross err(EX_MNT, gettext("could not find mount point %s"),
3204d925e45SGordon Ross argv[optind+1]);
3214d925e45SGordon Ross }
3224bff34e3Sthurlow if (!S_ISDIR(st.st_mode)) {
3234bff34e3Sthurlow errno = ENOTDIR;
32402d09e03SGordon Ross err(EX_MNT, gettext("can't mount on %s"), mount_point);
3254bff34e3Sthurlow }
3264bff34e3Sthurlow
3274bff34e3Sthurlow /*
3282f5e3e91SGordon Ross * Fill in mdata defaults.
3294bff34e3Sthurlow */
3304bff34e3Sthurlow if (mdata.uid == (uid_t)-1)
3314bff34e3Sthurlow mdata.uid = getuid();
3324bff34e3Sthurlow if (mdata.gid == (gid_t)-1)
3334bff34e3Sthurlow mdata.gid = getgid();
3344bff34e3Sthurlow if (mdata.file_mode == 0)
3352f5e3e91SGordon Ross mdata.file_mode = S_IRWXU;
3364bff34e3Sthurlow if (mdata.dir_mode == 0) {
3374bff34e3Sthurlow mdata.dir_mode = mdata.file_mode;
3384bff34e3Sthurlow if (mdata.dir_mode & S_IRUSR)
3394bff34e3Sthurlow mdata.dir_mode |= S_IXUSR;
3404bff34e3Sthurlow if (mdata.dir_mode & S_IRGRP)
3414bff34e3Sthurlow mdata.dir_mode |= S_IXGRP;
3424bff34e3Sthurlow if (mdata.dir_mode & S_IROTH)
3434bff34e3Sthurlow mdata.dir_mode |= S_IXOTH;
3444bff34e3Sthurlow }
3454bff34e3Sthurlow
346613a2f6bSGordon Ross ctx->ct_ssn.ssn_owner = SMBM_ANY_OWNER;
3474bff34e3Sthurlow if (noprompt)
3484bff34e3Sthurlow ctx->ct_flags |= SMBCF_NOPWD;
3494bff34e3Sthurlow
3504bff34e3Sthurlow /*
351613a2f6bSGordon Ross * Resolve the server address,
352613a2f6bSGordon Ross * setup derived defaults.
3534bff34e3Sthurlow */
3544bff34e3Sthurlow error = smb_ctx_resolve(ctx);
3554bff34e3Sthurlow if (error)
356613a2f6bSGordon Ross exit(RET_ERR);
3574bff34e3Sthurlow
358613a2f6bSGordon Ross /*
359613a2f6bSGordon Ross * Have server, share, etc. from above:
360613a2f6bSGordon Ross * smb_ctx_scan_argv, option settings.
361613a2f6bSGordon Ross * Get the session and tree.
362613a2f6bSGordon Ross */
3634bff34e3Sthurlow again:
364613a2f6bSGordon Ross error = smb_ctx_get_ssn(ctx);
365613a2f6bSGordon Ross if (error == EAUTH && noprompt == 0) {
366613a2f6bSGordon Ross err2 = smb_get_authentication(ctx);
367613a2f6bSGordon Ross if (err2 == 0)
368613a2f6bSGordon Ross goto again;
3694bff34e3Sthurlow }
370613a2f6bSGordon Ross if (error) {
371613a2f6bSGordon Ross smb_error(gettext("//%s: login failed"),
372613a2f6bSGordon Ross error, ctx->ct_fullserver);
373613a2f6bSGordon Ross exit(RET_ERR);
374613a2f6bSGordon Ross }
375613a2f6bSGordon Ross
376613a2f6bSGordon Ross error = smb_ctx_get_tree(ctx);
377613a2f6bSGordon Ross if (error) {
378613a2f6bSGordon Ross smb_error(gettext("//%s/%s: tree connect failed"),
379613a2f6bSGordon Ross error, ctx->ct_fullserver, ctx->ct_origshare);
380613a2f6bSGordon Ross exit(RET_ERR);
3814bff34e3Sthurlow }
3824bff34e3Sthurlow
383613a2f6bSGordon Ross /*
384613a2f6bSGordon Ross * Have tree connection, now mount it.
385613a2f6bSGordon Ross */
386613a2f6bSGordon Ross mdata.devfd = ctx->ct_dev_fd;
3874bff34e3Sthurlow
38842d15982SGordon Ross /* Need sys_mount privilege for the mount call. */
38942d15982SGordon Ross (void) __priv_bracket(PRIV_ON);
39042d15982SGordon Ross err2 = mount(mnt.mnt_special, mnt.mnt_mountp,
3914bff34e3Sthurlow mntflags, fstype, &mdata, sizeof (mdata),
39242d15982SGordon Ross mnt.mnt_mntopts, MAX_MNTOPT_STR);
39342d15982SGordon Ross (void) __priv_bracket(PRIV_OFF);
39442d15982SGordon Ross
39542d15982SGordon Ross if (err2 < 0) {
3964bff34e3Sthurlow if (errno != ENOENT) {
39702d09e03SGordon Ross err(EX_MNT, gettext("mount_smbfs: %s"),
398613a2f6bSGordon Ross mnt.mnt_mountp);
3994bff34e3Sthurlow } else {
4004bff34e3Sthurlow struct stat sb;
401613a2f6bSGordon Ross if (stat(mnt.mnt_mountp, &sb) < 0 &&
4024bff34e3Sthurlow errno == ENOENT)
40302d09e03SGordon Ross err(EX_MNT, gettext("mount_smbfs: %s"),
404613a2f6bSGordon Ross mnt.mnt_mountp);
4054bff34e3Sthurlow else
40602d09e03SGordon Ross err(EX_MNT, gettext("mount_smbfs: %s"),
407613a2f6bSGordon Ross mnt.mnt_special);
4084bff34e3Sthurlow }
4094bff34e3Sthurlow }
4104bff34e3Sthurlow
411613a2f6bSGordon Ross smb_ctx_free(ctx);
4124bff34e3Sthurlow return (0);
4134bff34e3Sthurlow }
4144bff34e3Sthurlow
41502d09e03SGordon Ross #define bad(val) (val == NULL || !isdigit(*val))
41602d09e03SGordon Ross
4174bff34e3Sthurlow int
setsubopt(smb_ctx_t * ctx,struct smbfs_args * mdatap,char * subopt)41802d09e03SGordon Ross setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, char *subopt)
4194bff34e3Sthurlow {
42002d09e03SGordon Ross char *equals, *optarg;
4214bff34e3Sthurlow struct passwd *pwd;
4224bff34e3Sthurlow struct group *grp;
42302d09e03SGordon Ross long val;
42402d09e03SGordon Ross int rc = EX_OK;
42502d09e03SGordon Ross int index;
42602d09e03SGordon Ross char *p;
42702d09e03SGordon Ross
42802d09e03SGordon Ross equals = strchr(subopt, '=');
42902d09e03SGordon Ross if (equals) {
43002d09e03SGordon Ross *equals = '\0';
43102d09e03SGordon Ross optarg = equals + 1;
43202d09e03SGordon Ross } else
43302d09e03SGordon Ross optarg = NULL;
43402d09e03SGordon Ross
43502d09e03SGordon Ross for (index = 0; optlist[index] != NULL; index++) {
43602d09e03SGordon Ross if (strcmp(subopt, optlist[index]) == 0)
43702d09e03SGordon Ross break;
43802d09e03SGordon Ross }
43902d09e03SGordon Ross
44002d09e03SGordon Ross /*
44102d09e03SGordon Ross * Note: if the option was unknown, index will
44202d09e03SGordon Ross * point to the NULL at the end of optlist[],
44302d09e03SGordon Ross * and we'll take the switch default.
44402d09e03SGordon Ross */
4454bff34e3Sthurlow
4464bff34e3Sthurlow switch (index) {
44702d09e03SGordon Ross
448bd7c6f51SGordon Ross case OPT_ACL:
449bd7c6f51SGordon Ross case OPT_NOACL:
4504bff34e3Sthurlow case OPT_SUID:
4514bff34e3Sthurlow case OPT_NOSUID:
4524bff34e3Sthurlow case OPT_DEVICES:
4534bff34e3Sthurlow case OPT_NODEVICES:
4544bff34e3Sthurlow case OPT_SETUID:
4554bff34e3Sthurlow case OPT_NOSETUID:
4564bff34e3Sthurlow case OPT_EXEC:
4574bff34e3Sthurlow case OPT_NOEXEC:
45802d09e03SGordon Ross case OPT_XATTR:
45902d09e03SGordon Ross case OPT_NOXATTR:
46002d09e03SGordon Ross /*
46102d09e03SGordon Ross * These options are handled via the
46202d09e03SGordon Ross * generic option string mechanism.
46302d09e03SGordon Ross * None of these take an optarg.
46402d09e03SGordon Ross */
46502d09e03SGordon Ross if (optarg != NULL)
46602d09e03SGordon Ross goto badval;
46702d09e03SGordon Ross (void) strlcat(optbuf, ",", sizeof (optbuf));
46802d09e03SGordon Ross if (strlcat(optbuf, subopt, sizeof (optbuf)) >=
46902d09e03SGordon Ross sizeof (optbuf)) {
47002d09e03SGordon Ross if (!qflg)
47102d09e03SGordon Ross warnx(gettext("option string too long"));
47202d09e03SGordon Ross rc = EX_OPT;
47302d09e03SGordon Ross }
47402d09e03SGordon Ross break;
47502d09e03SGordon Ross
47602d09e03SGordon Ross /*
47702d09e03SGordon Ross * OPT_RO, OPT_RW, are actually generic too,
47802d09e03SGordon Ross * but we use the mntflags for these, and
47902d09e03SGordon Ross * then update the options string later.
48002d09e03SGordon Ross */
48102d09e03SGordon Ross case OPT_RO:
48202d09e03SGordon Ross mntflags |= MS_RDONLY;
48302d09e03SGordon Ross break;
48402d09e03SGordon Ross case OPT_RW:
48502d09e03SGordon Ross mntflags &= ~MS_RDONLY;
48602d09e03SGordon Ross break;
48702d09e03SGordon Ross
48802d09e03SGordon Ross /*
48902d09e03SGordon Ross * NFS-derived options for attribute cache
49002d09e03SGordon Ross * handling (disable, set min/max timeouts)
49102d09e03SGordon Ross */
49202d09e03SGordon Ross case OPT_NOAC:
49302d09e03SGordon Ross mdatap->flags |= SMBFS_MF_NOAC;
49402d09e03SGordon Ross break;
49502d09e03SGordon Ross
49602d09e03SGordon Ross case OPT_ACTIMEO:
49702d09e03SGordon Ross errno = 0;
49802d09e03SGordon Ross val = strtol(optarg, &p, 10);
49902d09e03SGordon Ross if (errno || *p != 0)
50002d09e03SGordon Ross goto badval;
50102d09e03SGordon Ross mdatap->acdirmin = mdatap->acregmin = val;
50202d09e03SGordon Ross mdatap->acdirmax = mdatap->acregmax = val;
50302d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACDIRMAX;
50402d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACREGMAX;
50502d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACDIRMIN;
50602d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACREGMIN;
50702d09e03SGordon Ross break;
50802d09e03SGordon Ross
50902d09e03SGordon Ross case OPT_ACREGMIN:
51002d09e03SGordon Ross errno = 0;
51102d09e03SGordon Ross val = strtol(optarg, &p, 10);
51202d09e03SGordon Ross if (errno || *p != 0)
51302d09e03SGordon Ross goto badval;
51402d09e03SGordon Ross mdatap->acregmin = val;
51502d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACREGMIN;
51602d09e03SGordon Ross break;
51702d09e03SGordon Ross
51802d09e03SGordon Ross case OPT_ACREGMAX:
51902d09e03SGordon Ross errno = 0;
52002d09e03SGordon Ross val = strtol(optarg, &p, 10);
52102d09e03SGordon Ross if (errno || *p != 0)
52202d09e03SGordon Ross goto badval;
52302d09e03SGordon Ross mdatap->acregmax = val;
52402d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACREGMAX;
52502d09e03SGordon Ross break;
52602d09e03SGordon Ross
52702d09e03SGordon Ross case OPT_ACDIRMIN:
52802d09e03SGordon Ross errno = 0;
52902d09e03SGordon Ross val = strtol(optarg, &p, 10);
53002d09e03SGordon Ross if (errno || *p != 0)
53102d09e03SGordon Ross goto badval;
53202d09e03SGordon Ross mdatap->acdirmin = val;
53302d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACDIRMIN;
53402d09e03SGordon Ross break;
53502d09e03SGordon Ross
53602d09e03SGordon Ross case OPT_ACDIRMAX:
53702d09e03SGordon Ross errno = 0;
53802d09e03SGordon Ross val = strtol(optarg, &p, 10);
53902d09e03SGordon Ross if (errno || *p != 0)
54002d09e03SGordon Ross goto badval;
54102d09e03SGordon Ross mdatap->acdirmax = val;
54202d09e03SGordon Ross mdatap->flags |= SMBFS_MF_ACDIRMAX;
54302d09e03SGordon Ross break;
544613a2f6bSGordon Ross
54502d09e03SGordon Ross /*
54602d09e03SGordon Ross * SMBFS-specific options. Some of these
54702d09e03SGordon Ross * don't go through the mount system call,
54802d09e03SGordon Ross * but just set libsmbfs options.
54902d09e03SGordon Ross */
550613a2f6bSGordon Ross case OPT_DOMAIN:
55102d09e03SGordon Ross if (smb_ctx_setdomain(ctx, optarg, B_TRUE) != 0)
55202d09e03SGordon Ross rc = EX_OPT;
553613a2f6bSGordon Ross break;
554613a2f6bSGordon Ross
555613a2f6bSGordon Ross case OPT_USER:
55602d09e03SGordon Ross if (smb_ctx_setuser(ctx, optarg, B_TRUE) != 0)
55702d09e03SGordon Ross rc = EX_OPT;
558613a2f6bSGordon Ross break;
559613a2f6bSGordon Ross
5604bff34e3Sthurlow case OPT_UID:
5614bff34e3Sthurlow pwd = isdigit(optarg[0]) ?
5624bff34e3Sthurlow getpwuid(atoi(optarg)) : getpwnam(optarg);
5634bff34e3Sthurlow if (pwd == NULL) {
5644bff34e3Sthurlow if (!qflg)
5654bff34e3Sthurlow warnx(gettext("unknown user '%s'"), optarg);
56602d09e03SGordon Ross rc = EX_OPT;
5674bff34e3Sthurlow } else {
5684bff34e3Sthurlow mdatap->uid = pwd->pw_uid;
5694bff34e3Sthurlow }
5704bff34e3Sthurlow break;
57102d09e03SGordon Ross
5724bff34e3Sthurlow case OPT_GID:
5734bff34e3Sthurlow grp = isdigit(optarg[0]) ?
5744bff34e3Sthurlow getgrgid(atoi(optarg)) : getgrnam(optarg);
5754bff34e3Sthurlow if (grp == NULL) {
5764bff34e3Sthurlow if (!qflg)
5774bff34e3Sthurlow warnx(gettext("unknown group '%s'"), optarg);
57802d09e03SGordon Ross rc = EX_OPT;
5794bff34e3Sthurlow } else {
5804bff34e3Sthurlow mdatap->gid = grp->gr_gid;
5814bff34e3Sthurlow }
5824bff34e3Sthurlow break;
58302d09e03SGordon Ross
5844bff34e3Sthurlow case OPT_DIRPERMS:
5854bff34e3Sthurlow errno = 0;
58602d09e03SGordon Ross val = strtol(optarg, &p, 8);
58702d09e03SGordon Ross if (errno || *p != 0)
58802d09e03SGordon Ross goto badval;
58902d09e03SGordon Ross mdatap->dir_mode = val;
5904bff34e3Sthurlow break;
59102d09e03SGordon Ross
5924bff34e3Sthurlow case OPT_FILEPERMS:
5934bff34e3Sthurlow errno = 0;
59402d09e03SGordon Ross val = strtol(optarg, &p, 8);
59502d09e03SGordon Ross if (errno || *p != 0)
59602d09e03SGordon Ross goto badval;
59702d09e03SGordon Ross mdatap->file_mode = val;
5984bff34e3Sthurlow break;
59902d09e03SGordon Ross
6004bff34e3Sthurlow case OPT_NOPROMPT:
6014bff34e3Sthurlow noprompt++;
60202d09e03SGordon Ross break;
60302d09e03SGordon Ross
60402d09e03SGordon Ross default:
605bd7c6f51SGordon Ross badopt:
60602d09e03SGordon Ross if (!qflg)
60702d09e03SGordon Ross warnx(gettext("unknown option %s"), subopt);
60802d09e03SGordon Ross rc = EX_OPT;
60902d09e03SGordon Ross break;
61002d09e03SGordon Ross
61102d09e03SGordon Ross badval:
61202d09e03SGordon Ross if (!qflg)
61302d09e03SGordon Ross warnx(gettext("invalid value for %s"), subopt);
61402d09e03SGordon Ross rc = EX_OPT;
61502d09e03SGordon Ross break;
6164bff34e3Sthurlow }
61702d09e03SGordon Ross
61802d09e03SGordon Ross /* Undo changes made to subopt */
61902d09e03SGordon Ross if (equals)
62002d09e03SGordon Ross *equals = '=';
62102d09e03SGordon Ross
62202d09e03SGordon Ross return (rc);
6234bff34e3Sthurlow }
6244bff34e3Sthurlow
6254bff34e3Sthurlow static void
usage(void)6264bff34e3Sthurlow usage(void)
6274bff34e3Sthurlow {
6284d925e45SGordon Ross (void) fprintf(stderr, "%s\n",
6294bff34e3Sthurlow gettext("usage: mount -F smbfs [-Orq] [-o option[,option]]"
6304bff34e3Sthurlow " //[workgroup;][user[:password]@]server[/share] path"));
6314bff34e3Sthurlow
63202d09e03SGordon Ross exit(EX_OPT);
6334bff34e3Sthurlow }
634