Sync usage with man page.
[netbsd-mini2440.git] / dist / smbfs / mount_smbfs / mount_smbfs.c
blob10bd6e5d34877f578f0ddbfe186868966ea02c1d
1 /* $NetBSD: mount_smbfs.c,v 1.10 2009/09/04 18:22:37 pooka Exp $ */
3 /*
4 * Copyright (c) 2000-2002, Boris Popov
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Boris Popov.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
34 * from: Id: mount_smbfs.c,v 1.17 2002/04/10 04:17:51 bp Exp
37 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: mount_smbfs.c,v 1.10 2009/09/04 18:22:37 pooka Exp $");
40 #include <sys/param.h>
41 #include <sys/stat.h>
42 #include <sys/errno.h>
43 #include <sys/mount.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <pwd.h>
48 #include <grp.h>
49 #include <unistd.h>
50 #include <ctype.h>
51 #include <stdlib.h>
52 #include <err.h>
53 #include <sysexits.h>
54 #include <errno.h>
56 #include <cflib.h>
58 #include <netsmb/smb.h>
59 #include <netsmb/smb_conn.h>
60 #include <netsmb/smb_lib.h>
62 #include <fs/smbfs/smbfs.h>
64 #include "mount_smbfs.h"
66 #include "mntopts.h"
68 static void usage(void);
70 static const struct mntopt mopts[] = {
71 MOPT_STDOPTS,
72 { NULL, 0, 0, 0 }
75 #ifndef MOUNT_NOMAIN
76 int
77 main(int argc, char *argv[])
80 setprogname(argv[0]);
81 return mount_smbfs(argc, argv);
83 #endif
85 struct smb_ctx sctx;
86 void
87 mount_smbfs_parseargs(int argc, char *argv[], struct smbfs_args *mdatap,
88 int *mntflagsp, char *canon_dev, char *mount_point)
90 struct smb_ctx *ctx = &sctx;
91 struct stat st;
92 char *next;
93 int opt, error, caseopt;
95 if (argc == 2) {
96 if (strcmp(argv[1], "-h") == 0) {
97 usage();
98 } else if (strcmp(argv[1], "-v") == 0) {
99 errx(EX_OK, "version %d.%d.%d", SMBFS_VERSION / 100000,
100 (SMBFS_VERSION % 10000) / 1000,
101 (SMBFS_VERSION % 1000) / 100);
104 if (argc < 3)
105 usage();
107 if (smb_lib_init() != 0)
108 exit(1);
110 *mntflagsp = error = 0;
111 memset(mdatap, 0, sizeof(*mdatap));
112 mdatap->uid = mdatap->gid = -1;
113 caseopt = SMB_CS_NONE;
115 if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0)
116 exit(1);
117 if (smb_ctx_readrc(ctx) != 0)
118 exit(1);
119 if (smb_rc)
120 rc_close(smb_rc);
122 while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) {
123 switch (opt) {
124 case STDPARAM_ARGS:
125 error = smb_ctx_opt(ctx, opt, optarg);
126 if (error)
127 exit(1);
128 break;
129 case 'u': {
130 struct passwd *pwd;
132 pwd = isdigit((unsigned char)optarg[0]) ?
133 getpwuid(atoi(optarg)) : getpwnam(optarg);
134 if (pwd == NULL)
135 errx(EX_NOUSER, "unknown user '%s'", optarg);
136 mdatap->uid = pwd->pw_uid;
137 break;
139 case 'g': {
140 struct group *grp;
142 grp = isdigit((unsigned char)optarg[0]) ?
143 getgrgid(atoi(optarg)) : getgrnam(optarg);
144 if (grp == NULL)
145 errx(EX_NOUSER, "unknown group '%s'", optarg);
146 mdatap->gid = grp->gr_gid;
147 break;
149 case 'd':
150 errno = 0;
151 mdatap->dir_mode = strtol(optarg, &next, 8);
152 if (errno || *next != 0)
153 errx(EX_DATAERR, "invalid value for directory mode");
154 break;
155 case 'f':
156 errno = 0;
157 mdatap->file_mode = strtol(optarg, &next, 8);
158 if (errno || *next != 0)
159 errx(EX_DATAERR, "invalid value for file mode");
160 break;
161 case '?':
162 usage();
163 /*NOTREACHED*/
164 case 'n': {
165 char *inp, *nsp;
167 nsp = inp = optarg;
168 while ((nsp = strsep(&inp, ",;:")) != NULL) {
169 if (strcasecmp(nsp, "LONG") == 0)
170 mdatap->flags |= SMBFS_MOUNT_NO_LONG;
171 else
172 errx(EX_DATAERR, "unknown suboption '%s'", nsp);
174 break;
176 case 'o':
177 getmntopts(optarg, mopts, mntflagsp, 0);
178 break;
179 case 'c':
180 switch (optarg[0]) {
181 case 'l':
182 caseopt |= SMB_CS_LOWER;
183 break;
184 case 'u':
185 caseopt |= SMB_CS_UPPER;
186 break;
187 default:
188 errx(EX_DATAERR, "invalid suboption '%c' for -c",
189 optarg[0]);
191 break;
192 default:
193 usage();
197 if (optind == argc - 2)
198 optind++;
200 if (optind != argc - 1)
201 usage();
202 realpath(argv[optind], mount_point);
204 if (stat(mount_point, &st) == -1)
205 err(EX_OSERR, "could not find mount point %s", mount_point);
206 if (!S_ISDIR(st.st_mode)) {
207 errno = ENOTDIR;
208 err(EX_OSERR, "can't mount on %s", mount_point);
211 if (smb_getextattr(mount_point, &einfo) == 0)
212 errx(EX_OSERR, "can't mount on %s twice", mount_point);
214 if (mdatap->uid == (uid_t)-1)
215 mdatap->uid = st.st_uid;
216 if (mdatap->gid == (gid_t)-1)
217 mdatap->gid = st.st_gid;
218 if (mdatap->file_mode == 0 )
219 mdatap->file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
220 if (mdatap->dir_mode == 0) {
221 mdatap->dir_mode = mdatap->file_mode;
222 if (mdatap->dir_mode & S_IRUSR)
223 mdatap->dir_mode |= S_IXUSR;
224 if (mdatap->dir_mode & S_IRGRP)
225 mdatap->dir_mode |= S_IXGRP;
226 if (mdatap->dir_mode & S_IROTH)
227 mdatap->dir_mode |= S_IXOTH;
230 * For now, let connection be private for this mount
232 ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE;
233 if (getuid() == 0)
234 ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */
235 else
236 ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = mdatap->uid;
237 ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = mdatap->gid;
238 opt = 0;
239 if (mdatap->dir_mode & S_IXGRP)
240 opt |= SMBM_EXECGRP;
241 if (mdatap->dir_mode & S_IXOTH)
242 opt |= SMBM_EXECOTH;
243 ctx->ct_ssn.ioc_rights |= opt;
244 ctx->ct_sh.ioc_rights |= opt;
245 error = smb_ctx_resolve(ctx);
246 if (error)
247 err(1, "resolve %d", error);
248 error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
249 if (error) {
250 err(1, "lookup %d", error);
252 mdatap->version = SMBFS_VERSION;
253 mdatap->dev_fd = ctx->ct_fd;
254 mdatap->caseopt = caseopt;
256 snprintf(canon_dev, MAXPATHLEN, "//%s@%s/%s",
257 ctx->ct_ssn.ioc_user[0] ? ctx->ct_ssn.ioc_user : "guest",
258 ctx->ct_ssn.ioc_srvname, ctx->ct_sh.ioc_share);
262 mount_smbfs(int argc, char *argv[])
264 char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN];
265 struct smbfs_args mdata;
266 int mntflags, error;
268 mount_smbfs_parseargs(argc, argv, &mdata, &mntflags,
269 canon_dev, canon_dir);
271 error = mount(SMBFS_VFSNAME, canon_dir, mntflags,
272 &mdata, sizeof mdata);
273 smb_ctx_done(&sctx); /* XXX */
275 if (error) {
276 smb_error("mount error for %s: %s", error, canon_dir,
277 strerror(errno));
278 exit(1);
280 return 0;
283 static void
284 usage(void)
286 fprintf(stderr, "%s\n%s\n%s\n%s\n",
287 "usage: mount_smbfs [-E cs1:cs2] [-I host] [-L locale] [-M crights:srights]",
288 " [-N] [-O cowner:cgroup/sowner:sgroup] [-R retrycount]",
289 " [-T timeout] [-W workgroup] [-c case] [-d mode] [-f mode]",
290 " [-g gid] [-n opt] [-u uid] //user@server/share node");
292 exit (1);