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 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 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 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