16007Sthurlow /*
26007Sthurlow * Copyright (c) 2000-2001, Boris Popov
36007Sthurlow * All rights reserved.
46007Sthurlow *
56007Sthurlow * Redistribution and use in source and binary forms, with or without
66007Sthurlow * modification, are permitted provided that the following conditions
76007Sthurlow * are met:
86007Sthurlow * 1. Redistributions of source code must retain the above copyright
96007Sthurlow * notice, this list of conditions and the following disclaimer.
106007Sthurlow * 2. Redistributions in binary form must reproduce the above copyright
116007Sthurlow * notice, this list of conditions and the following disclaimer in the
126007Sthurlow * documentation and/or other materials provided with the distribution.
136007Sthurlow * 3. All advertising materials mentioning features or use of this software
146007Sthurlow * must display the following acknowledgement:
156007Sthurlow * This product includes software developed by Boris Popov.
166007Sthurlow * 4. Neither the name of the author nor the names of any co-contributors
176007Sthurlow * may be used to endorse or promote products derived from this software
186007Sthurlow * without specific prior written permission.
196007Sthurlow *
206007Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216007Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226007Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236007Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246007Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256007Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266007Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276007Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286007Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296007Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306007Sthurlow * SUCH DAMAGE.
316007Sthurlow *
326007Sthurlow * $Id: mount_smbfs.c,v 1.28.44.2 2005/06/02 00:55:41 lindak Exp $
336007Sthurlow */
346007Sthurlow
356007Sthurlow /*
3611564SGordon.Ross@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
376007Sthurlow * Use is subject to license terms.
386007Sthurlow */
396007Sthurlow
406007Sthurlow #include <stdio.h>
416007Sthurlow #include <string.h>
426007Sthurlow #include <strings.h>
436007Sthurlow #include <pwd.h>
446007Sthurlow #include <grp.h>
456007Sthurlow #include <unistd.h>
466007Sthurlow #include <ctype.h>
476007Sthurlow #include <stdlib.h>
486007Sthurlow #include <errno.h>
496007Sthurlow #include <err.h>
506007Sthurlow #include <libintl.h>
516007Sthurlow #include <locale.h>
526007Sthurlow #include <libscf.h>
53*12019SGordon.Ross@Sun.COM #include <priv_utils.h>
546007Sthurlow
5510023SGordon.Ross@Sun.COM #include <sys/types.h>
5610023SGordon.Ross@Sun.COM #include <sys/stat.h>
5710023SGordon.Ross@Sun.COM #include <sys/errno.h>
5810023SGordon.Ross@Sun.COM #include <sys/mount.h>
596007Sthurlow #include <sys/mntent.h>
606007Sthurlow #include <sys/mnttab.h>
616007Sthurlow
6211332SGordon.Ross@Sun.COM #include <sys/fs/smbfs_mount.h>
6311332SGordon.Ross@Sun.COM
6410023SGordon.Ross@Sun.COM /* This needs to know ctx->ct_dev_fd, etc. */
656007Sthurlow #include <netsmb/smb_lib.h>
666007Sthurlow
6710023SGordon.Ross@Sun.COM extern char *optarg;
6810023SGordon.Ross@Sun.COM extern int optind;
6911564SGordon.Ross@Sun.COM int enable_noacl_option = 0;
7010023SGordon.Ross@Sun.COM
716007Sthurlow static char mount_point[MAXPATHLEN + 1];
726007Sthurlow static void usage(void);
7311332SGordon.Ross@Sun.COM static int setsubopt(smb_ctx_t *, struct smbfs_args *, char *);
7411332SGordon.Ross@Sun.COM
7511332SGordon.Ross@Sun.COM const char * const optlist[] = {
766007Sthurlow
7711332SGordon.Ross@Sun.COM /* Generic VFS options. */
7811332SGordon.Ross@Sun.COM #define OPT_RO 0
7911332SGordon.Ross@Sun.COM MNTOPT_RO,
8011332SGordon.Ross@Sun.COM #define OPT_RW 1
8111332SGordon.Ross@Sun.COM MNTOPT_RW,
8211332SGordon.Ross@Sun.COM #define OPT_SUID 2
8311332SGordon.Ross@Sun.COM MNTOPT_SUID,
8411332SGordon.Ross@Sun.COM #define OPT_NOSUID 3
8511332SGordon.Ross@Sun.COM MNTOPT_NOSUID,
8611332SGordon.Ross@Sun.COM #define OPT_DEVICES 4
8711332SGordon.Ross@Sun.COM MNTOPT_DEVICES,
8811332SGordon.Ross@Sun.COM #define OPT_NODEVICES 5
8911332SGordon.Ross@Sun.COM MNTOPT_NODEVICES,
9011332SGordon.Ross@Sun.COM #define OPT_SETUID 6
9111332SGordon.Ross@Sun.COM MNTOPT_SETUID,
9211332SGordon.Ross@Sun.COM #define OPT_NOSETUID 7
9311332SGordon.Ross@Sun.COM MNTOPT_NOSETUID,
9411332SGordon.Ross@Sun.COM #define OPT_EXEC 8
9511332SGordon.Ross@Sun.COM MNTOPT_EXEC,
9611332SGordon.Ross@Sun.COM #define OPT_NOEXEC 9
9711332SGordon.Ross@Sun.COM MNTOPT_NOEXEC,
9811332SGordon.Ross@Sun.COM #define OPT_XATTR 10
9911332SGordon.Ross@Sun.COM MNTOPT_XATTR,
10011332SGordon.Ross@Sun.COM #define OPT_NOXATTR 11
10111332SGordon.Ross@Sun.COM MNTOPT_NOXATTR,
1026007Sthurlow
10311332SGordon.Ross@Sun.COM /* Sort of generic (from NFS) */
10411332SGordon.Ross@Sun.COM #define OPT_NOAC 12
10511332SGordon.Ross@Sun.COM MNTOPT_NOAC,
10611332SGordon.Ross@Sun.COM #define OPT_ACTIMEO 13
10711332SGordon.Ross@Sun.COM MNTOPT_ACTIMEO,
10811332SGordon.Ross@Sun.COM #define OPT_ACREGMIN 14
10911332SGordon.Ross@Sun.COM MNTOPT_ACREGMIN,
11011332SGordon.Ross@Sun.COM #define OPT_ACREGMAX 15
11111332SGordon.Ross@Sun.COM MNTOPT_ACREGMAX,
11211332SGordon.Ross@Sun.COM #define OPT_ACDIRMIN 16
11311332SGordon.Ross@Sun.COM MNTOPT_ACDIRMIN,
11411332SGordon.Ross@Sun.COM #define OPT_ACDIRMAX 17
11511332SGordon.Ross@Sun.COM MNTOPT_ACDIRMAX,
1166007Sthurlow
11711332SGordon.Ross@Sun.COM /* smbfs-specifis options */
11811332SGordon.Ross@Sun.COM #define OPT_DOMAIN 18
11911332SGordon.Ross@Sun.COM "domain",
12011332SGordon.Ross@Sun.COM #define OPT_USER 19
12111332SGordon.Ross@Sun.COM "user",
12211332SGordon.Ross@Sun.COM #define OPT_UID 20
12311332SGordon.Ross@Sun.COM "uid",
12411332SGordon.Ross@Sun.COM #define OPT_GID 21
12511332SGordon.Ross@Sun.COM "gid",
12611332SGordon.Ross@Sun.COM #define OPT_DIRPERMS 22
12711332SGordon.Ross@Sun.COM "dirperms",
12811332SGordon.Ross@Sun.COM #define OPT_FILEPERMS 23
12911332SGordon.Ross@Sun.COM "fileperms",
13011332SGordon.Ross@Sun.COM #define OPT_NOPROMPT 24
13111332SGordon.Ross@Sun.COM "noprompt",
13211564SGordon.Ross@Sun.COM #define OPT_ACL 25
13311564SGordon.Ross@Sun.COM MNTOPT_ACL,
13411564SGordon.Ross@Sun.COM #define OPT_NOACL 26
13511564SGordon.Ross@Sun.COM MNTOPT_NOACL,
13611332SGordon.Ross@Sun.COM
13711332SGordon.Ross@Sun.COM NULL
1386007Sthurlow };
1396007Sthurlow
1406007Sthurlow static int Oflg = 0; /* Overlay mounts */
1416007Sthurlow static int qflg = 0; /* quiet - don't print warnings on bad options */
1426007Sthurlow static int noprompt = 0; /* don't prompt for password */
1436007Sthurlow
14411332SGordon.Ross@Sun.COM /* Note: smbfs uses _both_ kinds of options. */
14511332SGordon.Ross@Sun.COM static int mntflags = MS_DATA | MS_OPTIONSTR;
14611332SGordon.Ross@Sun.COM
14711332SGordon.Ross@Sun.COM #define EX_OK 0 /* normal */
14811332SGordon.Ross@Sun.COM #define EX_OPT 1 /* bad options, usage, etc */
14911332SGordon.Ross@Sun.COM #define EX_MNT 2 /* mount point problems, etc */
15011332SGordon.Ross@Sun.COM #define RET_ERR 3 /* later errors */
15111332SGordon.Ross@Sun.COM
1526007Sthurlow #define SERVICE "svc:/network/smb/client:default"
1536007Sthurlow
15410023SGordon.Ross@Sun.COM struct smbfs_args mdata;
15510023SGordon.Ross@Sun.COM struct mnttab mnt;
15611332SGordon.Ross@Sun.COM
15711332SGordon.Ross@Sun.COM /*
15811332SGordon.Ross@Sun.COM * Initialize this with "rw" just to have something there,
15911332SGordon.Ross@Sun.COM * so we don't have to decide whether to add a comma when
16011332SGordon.Ross@Sun.COM * we strcat another option. Note the "rw" may be changed
16111332SGordon.Ross@Sun.COM * to an "ro" by option processing.
16211332SGordon.Ross@Sun.COM */
16311332SGordon.Ross@Sun.COM char optbuf[MAX_MNTOPT_STR] = "rw";
16410023SGordon.Ross@Sun.COM
1656007Sthurlow int
main(int argc,char * argv[])1666007Sthurlow main(int argc, char *argv[])
1676007Sthurlow {
16810023SGordon.Ross@Sun.COM struct smb_ctx *ctx = NULL;
1696007Sthurlow struct stat st;
17011332SGordon.Ross@Sun.COM int opt, error, err2;
1716007Sthurlow static char *fstype = MNTTYPE_SMBFS;
1726007Sthurlow char *env, *state;
1736007Sthurlow
1746007Sthurlow (void) setlocale(LC_ALL, "");
1756007Sthurlow #if !defined(TEXT_DOMAIN)
1766007Sthurlow #define TEXT_DOMAIN "SYS_TEST"
1776007Sthurlow #endif
1786007Sthurlow (void) textdomain(TEXT_DOMAIN);
179*12019SGordon.Ross@Sun.COM
180*12019SGordon.Ross@Sun.COM /*
181*12019SGordon.Ross@Sun.COM * Normal users are allowed to run "mount -F smbfs ..."
182*12019SGordon.Ross@Sun.COM * to mount on a directory they own. To allow that, this
183*12019SGordon.Ross@Sun.COM * program is installed setuid root, and it adds SYS_MOUNT
184*12019SGordon.Ross@Sun.COM * privilege here (if needed), and then restores the user's
185*12019SGordon.Ross@Sun.COM * normal privileges. When root runs this, it's a no-op.
186*12019SGordon.Ross@Sun.COM */
187*12019SGordon.Ross@Sun.COM if (__init_suid_priv(0, PRIV_SYS_MOUNT, (char *)NULL) < 0) {
188*12019SGordon.Ross@Sun.COM (void) fprintf(stderr,
189*12019SGordon.Ross@Sun.COM gettext("Insufficient privileges, "
190*12019SGordon.Ross@Sun.COM "%s must be set-uid root\n"), argv[0]);
191*12019SGordon.Ross@Sun.COM exit(RET_ERR);
192*12019SGordon.Ross@Sun.COM }
193*12019SGordon.Ross@Sun.COM
1946007Sthurlow if (argc == 2) {
1956007Sthurlow if (strcmp(argv[1], "-h") == 0) {
1966007Sthurlow usage();
1976007Sthurlow } else if (strcmp(argv[1], "-v") == 0) {
1986007Sthurlow errx(EX_OK, gettext("version %d.%d.%d"),
1996007Sthurlow SMBFS_VERSION / 100000,
2006007Sthurlow (SMBFS_VERSION % 10000) / 1000,
2016007Sthurlow (SMBFS_VERSION % 1000) / 100);
2026007Sthurlow }
2036007Sthurlow }
2046007Sthurlow if (argc < 3)
2056007Sthurlow usage();
2066007Sthurlow
2076007Sthurlow state = smf_get_state(SERVICE);
2086007Sthurlow if (state == NULL || strcmp(state, SCF_STATE_STRING_ONLINE) != 0) {
2096007Sthurlow fprintf(stderr,
2106007Sthurlow gettext("mount_smbfs: service \"%s\" not enabled.\n"),
2116007Sthurlow SERVICE);
21210023SGordon.Ross@Sun.COM exit(RET_ERR);
2136007Sthurlow }
21410023SGordon.Ross@Sun.COM free(state);
2156007Sthurlow
2166007Sthurlow /* Debugging support. */
2176007Sthurlow if ((env = getenv("SMBFS_DEBUG")) != NULL) {
2186007Sthurlow smb_debug = atoi(env);
2196007Sthurlow if (smb_debug < 1)
2206007Sthurlow smb_debug = 1;
2216007Sthurlow }
2226007Sthurlow
2236007Sthurlow error = smb_lib_init();
2246007Sthurlow if (error)
22510023SGordon.Ross@Sun.COM exit(RET_ERR);
2266007Sthurlow
2276007Sthurlow mnt.mnt_mntopts = optbuf;
22810023SGordon.Ross@Sun.COM
2296007Sthurlow bzero(&mdata, sizeof (mdata));
23010023SGordon.Ross@Sun.COM mdata.version = SMBFS_VERSION; /* smbfs mount version */
2316007Sthurlow mdata.uid = (uid_t)-1;
2326007Sthurlow mdata.gid = (gid_t)-1;
2336007Sthurlow
23410023SGordon.Ross@Sun.COM error = smb_ctx_alloc(&ctx);
2356007Sthurlow if (error)
23610023SGordon.Ross@Sun.COM exit(RET_ERR);
23710023SGordon.Ross@Sun.COM
23810023SGordon.Ross@Sun.COM /*
23910023SGordon.Ross@Sun.COM * Parse the UNC path so we have the server (etc.)
24010023SGordon.Ross@Sun.COM * that we need during rcfile+sharectl parsing.
24110023SGordon.Ross@Sun.COM */
24210023SGordon.Ross@Sun.COM if (argc < 3)
24310023SGordon.Ross@Sun.COM usage();
24410023SGordon.Ross@Sun.COM error = smb_ctx_parseunc(ctx, argv[argc - 2],
24510023SGordon.Ross@Sun.COM SMBL_SHARE, SMBL_SHARE, USE_DISKDEV, NULL);
24610023SGordon.Ross@Sun.COM if (error)
24711332SGordon.Ross@Sun.COM exit(EX_OPT);
24810023SGordon.Ross@Sun.COM
2496007Sthurlow error = smb_ctx_readrc(ctx);
2506007Sthurlow if (error)
25111332SGordon.Ross@Sun.COM exit(EX_OPT);
2526007Sthurlow
2536007Sthurlow while ((opt = getopt(argc, argv, "ro:Oq")) != -1) {
2546007Sthurlow switch (opt) {
2556007Sthurlow case 'O':
2566007Sthurlow Oflg++;
2576007Sthurlow break;
2586007Sthurlow
2596007Sthurlow case 'q':
2606007Sthurlow qflg++;
2616007Sthurlow break;
2626007Sthurlow
2636007Sthurlow case 'r':
26411332SGordon.Ross@Sun.COM mntflags |= MS_RDONLY;
2656007Sthurlow break;
2666007Sthurlow
2676007Sthurlow case 'o': {
26811332SGordon.Ross@Sun.COM char *nextopt, *comma, *sopt;
26911332SGordon.Ross@Sun.COM int ret;
2706007Sthurlow
2716007Sthurlow for (sopt = optarg; sopt != NULL; sopt = nextopt) {
2726007Sthurlow comma = strchr(sopt, ',');
2736007Sthurlow if (comma) {
2746007Sthurlow nextopt = comma + 1;
2756007Sthurlow *comma = '\0';
2766007Sthurlow } else
2776007Sthurlow nextopt = NULL;
27811332SGordon.Ross@Sun.COM ret = setsubopt(ctx, &mdata, sopt);
2796007Sthurlow if (ret != 0)
28011332SGordon.Ross@Sun.COM exit(EX_OPT);
28111332SGordon.Ross@Sun.COM /* undo changes to optarg */
2826007Sthurlow if (comma)
2836007Sthurlow *comma = ',';
2846007Sthurlow }
2856007Sthurlow break;
2866007Sthurlow }
2876007Sthurlow
2886007Sthurlow case '?':
2896007Sthurlow default:
2906007Sthurlow usage();
2916007Sthurlow }
2926007Sthurlow }
2936007Sthurlow
2946007Sthurlow if (Oflg)
2956007Sthurlow mntflags |= MS_OVERLAY;
2966007Sthurlow
29711332SGordon.Ross@Sun.COM if (mntflags & MS_RDONLY) {
2986007Sthurlow char *p;
2996007Sthurlow /* convert "rw"->"ro" */
30011332SGordon.Ross@Sun.COM if (p = strstr(optbuf, "rw")) {
3016007Sthurlow if (*(p+2) == ',' || *(p+2) == '\0')
3026007Sthurlow *(p+1) = 'o';
3036007Sthurlow }
3046007Sthurlow }
3056007Sthurlow
30610023SGordon.Ross@Sun.COM if (optind + 2 != argc)
30710023SGordon.Ross@Sun.COM usage();
30810023SGordon.Ross@Sun.COM
3096007Sthurlow mnt.mnt_special = argv[optind];
3106007Sthurlow mnt.mnt_mountp = argv[optind+1];
3116007Sthurlow
31210023SGordon.Ross@Sun.COM realpath(argv[optind+1], mount_point);
3136007Sthurlow if (stat(mount_point, &st) == -1)
31411332SGordon.Ross@Sun.COM err(EX_MNT, gettext("could not find mount point %s"),
3156007Sthurlow mount_point);
3166007Sthurlow if (!S_ISDIR(st.st_mode)) {
3176007Sthurlow errno = ENOTDIR;
31811332SGordon.Ross@Sun.COM err(EX_MNT, gettext("can't mount on %s"), mount_point);
3196007Sthurlow }
3206007Sthurlow
3216007Sthurlow /*
3229035SGordon.Ross@Sun.COM * Fill in mdata defaults.
3236007Sthurlow */
3246007Sthurlow if (mdata.uid == (uid_t)-1)
3256007Sthurlow mdata.uid = getuid();
3266007Sthurlow if (mdata.gid == (gid_t)-1)
3276007Sthurlow mdata.gid = getgid();
3286007Sthurlow if (mdata.file_mode == 0)
3299035SGordon.Ross@Sun.COM mdata.file_mode = S_IRWXU;
3306007Sthurlow if (mdata.dir_mode == 0) {
3316007Sthurlow mdata.dir_mode = mdata.file_mode;
3326007Sthurlow if (mdata.dir_mode & S_IRUSR)
3336007Sthurlow mdata.dir_mode |= S_IXUSR;
3346007Sthurlow if (mdata.dir_mode & S_IRGRP)
3356007Sthurlow mdata.dir_mode |= S_IXGRP;
3366007Sthurlow if (mdata.dir_mode & S_IROTH)
3376007Sthurlow mdata.dir_mode |= S_IXOTH;
3386007Sthurlow }
3396007Sthurlow
34010023SGordon.Ross@Sun.COM ctx->ct_ssn.ssn_owner = SMBM_ANY_OWNER;
3416007Sthurlow if (noprompt)
3426007Sthurlow ctx->ct_flags |= SMBCF_NOPWD;
3436007Sthurlow
3446007Sthurlow /*
34510023SGordon.Ross@Sun.COM * Resolve the server address,
34610023SGordon.Ross@Sun.COM * setup derived defaults.
3476007Sthurlow */
3486007Sthurlow error = smb_ctx_resolve(ctx);
3496007Sthurlow if (error)
35010023SGordon.Ross@Sun.COM exit(RET_ERR);
3516007Sthurlow
35210023SGordon.Ross@Sun.COM /*
35310023SGordon.Ross@Sun.COM * Have server, share, etc. from above:
35410023SGordon.Ross@Sun.COM * smb_ctx_scan_argv, option settings.
35510023SGordon.Ross@Sun.COM * Get the session and tree.
35610023SGordon.Ross@Sun.COM */
3576007Sthurlow again:
35810023SGordon.Ross@Sun.COM error = smb_ctx_get_ssn(ctx);
35910023SGordon.Ross@Sun.COM if (error == EAUTH && noprompt == 0) {
36010023SGordon.Ross@Sun.COM err2 = smb_get_authentication(ctx);
36110023SGordon.Ross@Sun.COM if (err2 == 0)
36210023SGordon.Ross@Sun.COM goto again;
3636007Sthurlow }
36410023SGordon.Ross@Sun.COM if (error) {
36510023SGordon.Ross@Sun.COM smb_error(gettext("//%s: login failed"),
36610023SGordon.Ross@Sun.COM error, ctx->ct_fullserver);
36710023SGordon.Ross@Sun.COM exit(RET_ERR);
3686007Sthurlow }
36910023SGordon.Ross@Sun.COM
37010023SGordon.Ross@Sun.COM error = smb_ctx_get_tree(ctx);
37110023SGordon.Ross@Sun.COM if (error) {
37210023SGordon.Ross@Sun.COM smb_error(gettext("//%s/%s: tree connect failed"),
37310023SGordon.Ross@Sun.COM error, ctx->ct_fullserver, ctx->ct_origshare);
37410023SGordon.Ross@Sun.COM exit(RET_ERR);
37510023SGordon.Ross@Sun.COM }
3766007Sthurlow
37710023SGordon.Ross@Sun.COM /*
37810023SGordon.Ross@Sun.COM * Have tree connection, now mount it.
37910023SGordon.Ross@Sun.COM */
38010023SGordon.Ross@Sun.COM mdata.devfd = ctx->ct_dev_fd;
3816007Sthurlow
382*12019SGordon.Ross@Sun.COM /* Need sys_mount privilege for the mount call. */
383*12019SGordon.Ross@Sun.COM (void) __priv_bracket(PRIV_ON);
384*12019SGordon.Ross@Sun.COM err2 = mount(mnt.mnt_special, mnt.mnt_mountp,
3856007Sthurlow mntflags, fstype, &mdata, sizeof (mdata),
386*12019SGordon.Ross@Sun.COM mnt.mnt_mntopts, MAX_MNTOPT_STR);
387*12019SGordon.Ross@Sun.COM (void) __priv_bracket(PRIV_OFF);
388*12019SGordon.Ross@Sun.COM
389*12019SGordon.Ross@Sun.COM if (err2 < 0) {
3906007Sthurlow if (errno != ENOENT) {
39111332SGordon.Ross@Sun.COM err(EX_MNT, gettext("mount_smbfs: %s"),
39210023SGordon.Ross@Sun.COM mnt.mnt_mountp);
3936007Sthurlow } else {
3946007Sthurlow struct stat sb;
39510023SGordon.Ross@Sun.COM if (stat(mnt.mnt_mountp, &sb) < 0 &&
3966007Sthurlow errno == ENOENT)
39711332SGordon.Ross@Sun.COM err(EX_MNT, gettext("mount_smbfs: %s"),
39810023SGordon.Ross@Sun.COM mnt.mnt_mountp);
3996007Sthurlow else
40011332SGordon.Ross@Sun.COM err(EX_MNT, gettext("mount_smbfs: %s"),
40110023SGordon.Ross@Sun.COM mnt.mnt_special);
4026007Sthurlow }
4036007Sthurlow }
4046007Sthurlow
40510023SGordon.Ross@Sun.COM smb_ctx_free(ctx);
4066007Sthurlow return (0);
4076007Sthurlow }
4086007Sthurlow
40911332SGordon.Ross@Sun.COM #define bad(val) (val == NULL || !isdigit(*val))
41011332SGordon.Ross@Sun.COM
4116007Sthurlow int
setsubopt(smb_ctx_t * ctx,struct smbfs_args * mdatap,char * subopt)41211332SGordon.Ross@Sun.COM setsubopt(smb_ctx_t *ctx, struct smbfs_args *mdatap, char *subopt)
4136007Sthurlow {
41411332SGordon.Ross@Sun.COM char *equals, *optarg;
4156007Sthurlow struct passwd *pwd;
4166007Sthurlow struct group *grp;
41711332SGordon.Ross@Sun.COM long val;
41811332SGordon.Ross@Sun.COM int rc = EX_OK;
41911332SGordon.Ross@Sun.COM int index;
42011332SGordon.Ross@Sun.COM char *p;
42111332SGordon.Ross@Sun.COM
42211332SGordon.Ross@Sun.COM equals = strchr(subopt, '=');
42311332SGordon.Ross@Sun.COM if (equals) {
42411332SGordon.Ross@Sun.COM *equals = '\0';
42511332SGordon.Ross@Sun.COM optarg = equals + 1;
42611332SGordon.Ross@Sun.COM } else
42711332SGordon.Ross@Sun.COM optarg = NULL;
42811332SGordon.Ross@Sun.COM
42911332SGordon.Ross@Sun.COM for (index = 0; optlist[index] != NULL; index++) {
43011332SGordon.Ross@Sun.COM if (strcmp(subopt, optlist[index]) == 0)
43111332SGordon.Ross@Sun.COM break;
43211332SGordon.Ross@Sun.COM }
43311332SGordon.Ross@Sun.COM
43411332SGordon.Ross@Sun.COM /*
43511332SGordon.Ross@Sun.COM * Note: if the option was unknown, index will
43611332SGordon.Ross@Sun.COM * point to the NULL at the end of optlist[],
43711332SGordon.Ross@Sun.COM * and we'll take the switch default.
43811332SGordon.Ross@Sun.COM */
4396007Sthurlow
4406007Sthurlow switch (index) {
44111332SGordon.Ross@Sun.COM
44211564SGordon.Ross@Sun.COM case OPT_ACL:
44311564SGordon.Ross@Sun.COM case OPT_NOACL:
44411564SGordon.Ross@Sun.COM /* Some of our tests use this. */
44511564SGordon.Ross@Sun.COM if (enable_noacl_option == 0)
44611564SGordon.Ross@Sun.COM goto badopt;
44711564SGordon.Ross@Sun.COM /* fallthrough */
4486007Sthurlow case OPT_SUID:
4496007Sthurlow case OPT_NOSUID:
4506007Sthurlow case OPT_DEVICES:
4516007Sthurlow case OPT_NODEVICES:
4526007Sthurlow case OPT_SETUID:
4536007Sthurlow case OPT_NOSETUID:
4546007Sthurlow case OPT_EXEC:
4556007Sthurlow case OPT_NOEXEC:
45611332SGordon.Ross@Sun.COM case OPT_XATTR:
45711332SGordon.Ross@Sun.COM case OPT_NOXATTR:
45811332SGordon.Ross@Sun.COM /*
45911332SGordon.Ross@Sun.COM * These options are handled via the
46011332SGordon.Ross@Sun.COM * generic option string mechanism.
46111332SGordon.Ross@Sun.COM * None of these take an optarg.
46211332SGordon.Ross@Sun.COM */
46311332SGordon.Ross@Sun.COM if (optarg != NULL)
46411332SGordon.Ross@Sun.COM goto badval;
46511332SGordon.Ross@Sun.COM (void) strlcat(optbuf, ",", sizeof (optbuf));
46611332SGordon.Ross@Sun.COM if (strlcat(optbuf, subopt, sizeof (optbuf)) >=
46711332SGordon.Ross@Sun.COM sizeof (optbuf)) {
46811332SGordon.Ross@Sun.COM if (!qflg)
46911332SGordon.Ross@Sun.COM warnx(gettext("option string too long"));
47011332SGordon.Ross@Sun.COM rc = EX_OPT;
47111332SGordon.Ross@Sun.COM }
47211332SGordon.Ross@Sun.COM break;
47311332SGordon.Ross@Sun.COM
47411332SGordon.Ross@Sun.COM /*
47511332SGordon.Ross@Sun.COM * OPT_RO, OPT_RW, are actually generic too,
47611332SGordon.Ross@Sun.COM * but we use the mntflags for these, and
47711332SGordon.Ross@Sun.COM * then update the options string later.
47811332SGordon.Ross@Sun.COM */
47911332SGordon.Ross@Sun.COM case OPT_RO:
48011332SGordon.Ross@Sun.COM mntflags |= MS_RDONLY;
48111332SGordon.Ross@Sun.COM break;
48211332SGordon.Ross@Sun.COM case OPT_RW:
48311332SGordon.Ross@Sun.COM mntflags &= ~MS_RDONLY;
48411332SGordon.Ross@Sun.COM break;
48511332SGordon.Ross@Sun.COM
48611332SGordon.Ross@Sun.COM /*
48711332SGordon.Ross@Sun.COM * NFS-derived options for attribute cache
48811332SGordon.Ross@Sun.COM * handling (disable, set min/max timeouts)
48911332SGordon.Ross@Sun.COM */
49011332SGordon.Ross@Sun.COM case OPT_NOAC:
49111332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_NOAC;
49211332SGordon.Ross@Sun.COM break;
49310023SGordon.Ross@Sun.COM
49411332SGordon.Ross@Sun.COM case OPT_ACTIMEO:
49511332SGordon.Ross@Sun.COM errno = 0;
49611332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 10);
49711332SGordon.Ross@Sun.COM if (errno || *p != 0)
49811332SGordon.Ross@Sun.COM goto badval;
49911332SGordon.Ross@Sun.COM mdatap->acdirmin = mdatap->acregmin = val;
50011332SGordon.Ross@Sun.COM mdatap->acdirmax = mdatap->acregmax = val;
50111332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACDIRMAX;
50211332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACREGMAX;
50311332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACDIRMIN;
50411332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACREGMIN;
50511332SGordon.Ross@Sun.COM break;
50611332SGordon.Ross@Sun.COM
50711332SGordon.Ross@Sun.COM case OPT_ACREGMIN:
50811332SGordon.Ross@Sun.COM errno = 0;
50911332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 10);
51011332SGordon.Ross@Sun.COM if (errno || *p != 0)
51111332SGordon.Ross@Sun.COM goto badval;
51211332SGordon.Ross@Sun.COM mdatap->acregmin = val;
51311332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACREGMIN;
51411332SGordon.Ross@Sun.COM break;
51511332SGordon.Ross@Sun.COM
51611332SGordon.Ross@Sun.COM case OPT_ACREGMAX:
51711332SGordon.Ross@Sun.COM errno = 0;
51811332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 10);
51911332SGordon.Ross@Sun.COM if (errno || *p != 0)
52011332SGordon.Ross@Sun.COM goto badval;
52111332SGordon.Ross@Sun.COM mdatap->acregmax = val;
52211332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACREGMAX;
52311332SGordon.Ross@Sun.COM break;
52411332SGordon.Ross@Sun.COM
52511332SGordon.Ross@Sun.COM case OPT_ACDIRMIN:
52611332SGordon.Ross@Sun.COM errno = 0;
52711332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 10);
52811332SGordon.Ross@Sun.COM if (errno || *p != 0)
52911332SGordon.Ross@Sun.COM goto badval;
53011332SGordon.Ross@Sun.COM mdatap->acdirmin = val;
53111332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACDIRMIN;
53211332SGordon.Ross@Sun.COM break;
53311332SGordon.Ross@Sun.COM
53411332SGordon.Ross@Sun.COM case OPT_ACDIRMAX:
53511332SGordon.Ross@Sun.COM errno = 0;
53611332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 10);
53711332SGordon.Ross@Sun.COM if (errno || *p != 0)
53811332SGordon.Ross@Sun.COM goto badval;
53911332SGordon.Ross@Sun.COM mdatap->acdirmax = val;
54011332SGordon.Ross@Sun.COM mdatap->flags |= SMBFS_MF_ACDIRMAX;
54111332SGordon.Ross@Sun.COM break;
54211332SGordon.Ross@Sun.COM
54311332SGordon.Ross@Sun.COM /*
54411332SGordon.Ross@Sun.COM * SMBFS-specific options. Some of these
54511332SGordon.Ross@Sun.COM * don't go through the mount system call,
54611332SGordon.Ross@Sun.COM * but just set libsmbfs options.
54711332SGordon.Ross@Sun.COM */
54810023SGordon.Ross@Sun.COM case OPT_DOMAIN:
54911332SGordon.Ross@Sun.COM if (smb_ctx_setdomain(ctx, optarg, B_TRUE) != 0)
55011332SGordon.Ross@Sun.COM rc = EX_OPT;
55110023SGordon.Ross@Sun.COM break;
55210023SGordon.Ross@Sun.COM
55310023SGordon.Ross@Sun.COM case OPT_USER:
55411332SGordon.Ross@Sun.COM if (smb_ctx_setuser(ctx, optarg, B_TRUE) != 0)
55511332SGordon.Ross@Sun.COM rc = EX_OPT;
55610023SGordon.Ross@Sun.COM break;
55710023SGordon.Ross@Sun.COM
5586007Sthurlow case OPT_UID:
5596007Sthurlow pwd = isdigit(optarg[0]) ?
5606007Sthurlow getpwuid(atoi(optarg)) : getpwnam(optarg);
5616007Sthurlow if (pwd == NULL) {
5626007Sthurlow if (!qflg)
5636007Sthurlow warnx(gettext("unknown user '%s'"), optarg);
56411332SGordon.Ross@Sun.COM rc = EX_OPT;
5656007Sthurlow } else {
5666007Sthurlow mdatap->uid = pwd->pw_uid;
5676007Sthurlow }
5686007Sthurlow break;
56911332SGordon.Ross@Sun.COM
5706007Sthurlow case OPT_GID:
5716007Sthurlow grp = isdigit(optarg[0]) ?
5726007Sthurlow getgrgid(atoi(optarg)) : getgrnam(optarg);
5736007Sthurlow if (grp == NULL) {
5746007Sthurlow if (!qflg)
5756007Sthurlow warnx(gettext("unknown group '%s'"), optarg);
57611332SGordon.Ross@Sun.COM rc = EX_OPT;
5776007Sthurlow } else {
5786007Sthurlow mdatap->gid = grp->gr_gid;
5796007Sthurlow }
5806007Sthurlow break;
58111332SGordon.Ross@Sun.COM
5826007Sthurlow case OPT_DIRPERMS:
5836007Sthurlow errno = 0;
58411332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 8);
58511332SGordon.Ross@Sun.COM if (errno || *p != 0)
58611332SGordon.Ross@Sun.COM goto badval;
58711332SGordon.Ross@Sun.COM mdatap->dir_mode = val;
5886007Sthurlow break;
58911332SGordon.Ross@Sun.COM
5906007Sthurlow case OPT_FILEPERMS:
5916007Sthurlow errno = 0;
59211332SGordon.Ross@Sun.COM val = strtol(optarg, &p, 8);
59311332SGordon.Ross@Sun.COM if (errno || *p != 0)
59411332SGordon.Ross@Sun.COM goto badval;
59511332SGordon.Ross@Sun.COM mdatap->file_mode = val;
5966007Sthurlow break;
59711332SGordon.Ross@Sun.COM
5986007Sthurlow case OPT_NOPROMPT:
5996007Sthurlow noprompt++;
60011332SGordon.Ross@Sun.COM break;
60111332SGordon.Ross@Sun.COM
60211332SGordon.Ross@Sun.COM default:
60311564SGordon.Ross@Sun.COM badopt:
60411332SGordon.Ross@Sun.COM if (!qflg)
60511332SGordon.Ross@Sun.COM warnx(gettext("unknown option %s"), subopt);
60611332SGordon.Ross@Sun.COM rc = EX_OPT;
60711332SGordon.Ross@Sun.COM break;
60811332SGordon.Ross@Sun.COM
60911332SGordon.Ross@Sun.COM badval:
61011332SGordon.Ross@Sun.COM if (!qflg)
61111332SGordon.Ross@Sun.COM warnx(gettext("invalid value for %s"), subopt);
61211332SGordon.Ross@Sun.COM rc = EX_OPT;
61311332SGordon.Ross@Sun.COM break;
6146007Sthurlow }
61511332SGordon.Ross@Sun.COM
61611332SGordon.Ross@Sun.COM /* Undo changes made to subopt */
61711332SGordon.Ross@Sun.COM if (equals)
61811332SGordon.Ross@Sun.COM *equals = '=';
61911332SGordon.Ross@Sun.COM
62011332SGordon.Ross@Sun.COM return (rc);
6216007Sthurlow }
6226007Sthurlow
6236007Sthurlow static void
usage(void)6246007Sthurlow usage(void)
6256007Sthurlow {
6266007Sthurlow fprintf(stderr, "%s\n",
6276007Sthurlow gettext("usage: mount -F smbfs [-Orq] [-o option[,option]]"
6286007Sthurlow " //[workgroup;][user[:password]@]server[/share] path"));
6296007Sthurlow
63011332SGordon.Ross@Sun.COM exit(EX_OPT);
6316007Sthurlow }
632