2 * Copyright (c) 2000-2002, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $Id: mount_smbfs.c,v 1.17 2002/04/10 04:17:51 bp Exp $
34 #include <sys/param.h>
36 #include <sys/errno.h>
37 #include <sys/mount.h>
51 #include <netsmb/smb.h>
52 #include <netsmb/smb_conn.h>
53 #include <netsmb/smb_lib.h>
55 #include <fs/smbfs/smbfs.h>
59 static char mount_point
[MAXPATHLEN
+ 1];
60 static void usage(void);
62 static struct mntopt mopts
[] = {
69 main(int argc
, char *argv
[])
71 struct smb_ctx sctx
, *ctx
= &sctx
;
72 struct smbfs_args mdata
;
75 extern void dropsuid();
76 extern int loadsmbvfs();
81 int opt
, error
, mntflags
, caseopt
;
88 if (strcmp(argv
[1], "-h") == 0) {
90 } else if (strcmp(argv
[1], "-v") == 0) {
91 errx(EX_OK
, "version %d.%d.%d", SMBFS_VERSION
/ 100000,
92 (SMBFS_VERSION
% 10000) / 1000,
93 (SMBFS_VERSION
% 1000) / 100);
100 error
= loadsmbvfs();
102 error
= getvfsbyname(SMBFS_VFSNAME
, &vfc
);
103 if (error
&& vfsisloadable(SMBFS_VFSNAME
)) {
104 if(vfsload(SMBFS_VFSNAME
))
105 err(EX_OSERR
, "vfsload("SMBFS_VFSNAME
")");
107 error
= getvfsbyname(SMBFS_VFSNAME
, &vfc
);
111 errx(EX_OSERR
, "SMB filesystem is not available");
113 if (smb_lib_init() != 0)
116 mntflags
= error
= 0;
117 bzero(&mdata
, sizeof(mdata
));
118 mdata
.uid
= mdata
.gid
= -1;
119 caseopt
= SMB_CS_NONE
;
121 if (smb_ctx_init(ctx
, argc
, argv
, SMBL_SHARE
, SMBL_SHARE
, SMB_ST_DISK
) != 0)
123 if (smb_ctx_readrc(ctx
) != 0)
128 while ((opt
= getopt(argc
, argv
, STDPARAM_OPT
"c:d:f:g:l:n:o:u:w:")) != -1) {
131 error
= smb_ctx_opt(ctx
, opt
, optarg
);
138 pwd
= isdigit(optarg
[0]) ?
139 getpwuid(atoi(optarg
)) : getpwnam(optarg
);
141 errx(EX_NOUSER
, "unknown user '%s'", optarg
);
142 mdata
.uid
= pwd
->pw_uid
;
148 grp
= isdigit(optarg
[0]) ?
149 getgrgid(atoi(optarg
)) : getgrnam(optarg
);
151 errx(EX_NOUSER
, "unknown group '%s'", optarg
);
152 mdata
.gid
= grp
->gr_gid
;
157 mdata
.dir_mode
= strtol(optarg
, &next
, 8);
158 if (errno
|| *next
!= 0)
159 errx(EX_DATAERR
, "invalid value for directory mode");
163 mdata
.file_mode
= strtol(optarg
, &next
, 8);
164 if (errno
|| *next
!= 0)
165 errx(EX_DATAERR
, "invalid value for file mode");
174 while ((nsp
= strsep(&inp
, ",;:")) != NULL
) {
175 if (strcasecmp(nsp
, "LONG") == 0)
176 mdata
.flags
|= SMBFS_MOUNT_NO_LONG
;
178 errx(EX_DATAERR
, "unknown suboption '%s'", nsp
);
183 getmntopts(optarg
, mopts
, &mntflags
, 0);
188 caseopt
|= SMB_CS_LOWER
;
191 caseopt
|= SMB_CS_UPPER
;
194 errx(EX_DATAERR
, "invalid suboption '%c' for -c",
203 if (optind
== argc
- 2)
206 if (optind
!= argc
- 1)
208 realpath(argv
[optind
], mount_point
);
210 if (stat(mount_point
, &st
) == -1)
211 err(EX_OSERR
, "could not find mount point %s", mount_point
);
212 if (!S_ISDIR(st
.st_mode
)) {
214 err(EX_OSERR
, "can't mount on %s", mount_point
);
217 if (smb_getextattr(mount_point, &einfo) == 0)
218 errx(EX_OSERR, "can't mount on %s twice", mount_point);
220 if (mdata
.uid
== (uid_t
)-1)
221 mdata
.uid
= st
.st_uid
;
222 if (mdata
.gid
== (gid_t
)-1)
223 mdata
.gid
= st
.st_gid
;
224 if (mdata
.file_mode
== 0 )
225 mdata
.file_mode
= st
.st_mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
);
226 if (mdata
.dir_mode
== 0) {
227 mdata
.dir_mode
= mdata
.file_mode
;
228 if (mdata
.dir_mode
& S_IRUSR
)
229 mdata
.dir_mode
|= S_IXUSR
;
230 if (mdata
.dir_mode
& S_IRGRP
)
231 mdata
.dir_mode
|= S_IXGRP
;
232 if (mdata
.dir_mode
& S_IROTH
)
233 mdata
.dir_mode
|= S_IXOTH
;
236 * For now, let connection be private for this mount
238 ctx
->ct_ssn
.ioc_opt
|= SMBVOPT_PRIVATE
;
239 ctx
->ct_ssn
.ioc_owner
= ctx
->ct_sh
.ioc_owner
= 0; /* root */
240 ctx
->ct_ssn
.ioc_group
= ctx
->ct_sh
.ioc_group
= mdata
.gid
;
242 if (mdata
.dir_mode
& S_IXGRP
)
244 if (mdata
.dir_mode
& S_IXOTH
)
246 ctx
->ct_ssn
.ioc_rights
|= opt
;
247 ctx
->ct_sh
.ioc_rights
|= opt
;
248 error
= smb_ctx_resolve(ctx
);
251 error
= smb_ctx_lookup(ctx
, SMBL_SHARE
, SMBLK_CREATE
);
255 strcpy(mdata
.mount_point
,mount_point
);
256 mdata
.version
= SMBFS_VERSION
;
257 mdata
.dev
= ctx
->ct_fd
;
258 mdata
.caseopt
= caseopt
;
259 error
= mount(SMBFS_VFSNAME
, mdata
.mount_point
, mntflags
, (void*)&mdata
);
262 smb_error("mount error: %s", error
, mdata
.mount_point
);
271 fprintf(stderr
, "%s\n%s\n%s\n%s\n",
272 "usage: mount_smbfs [-E cs1:cs2] [-I host] [-L locale] [-M crights:srights]",
273 " [-N] [-O cowner:cgroup/sowner:sgroup] [-R retrycount]",
274 " [-T timeout] [-W workgroup] [-c case] [-d mode] [-f mode]",
275 " [-g gid] [-n opt] [-u uid] //user@server/share node");