2 * Copyright (c) 1999, 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 * $FreeBSD: src/sbin/mount_nwfs/mount_nwfs.c,v 1.4.2.1 2000/04/17 08:34:18 bp Exp $
33 * $DragonFly: src/sbin/mount_nwfs/mount_nwfs.c,v 1.3 2003/08/08 04:18:40 dillon Exp $
35 #include <sys/param.h>
37 #include <sys/errno.h>
38 #include <sys/mount.h>
39 #include <sys/sysctl.h>
40 #include <machine/cpu.h>
53 #include <netncp/ncp_lib.h>
54 #include <netncp/ncp_rcfile.h>
55 #include <vfs/nwfs/nwfs_mount.h>
58 #define NWFS_VFSNAME "nwfs"
60 static char mount_point
[MAXPATHLEN
+ 1];
61 static void usage(void);
62 static int parsercfile(struct ncp_conn_loginfo
*li
, struct nwfs_args
*mdata
);
64 static struct mntopt mopts
[] = {
70 parsercfile(struct ncp_conn_loginfo
*li
, struct nwfs_args
*mdata
) {
75 main(int argc
, char *argv
[]) {
76 NWCONN_HANDLE connHandle
;
77 struct nwfs_args mdata
;
78 struct ncp_conn_loginfo li
;
81 struct nw_entry_info einfo
;
84 int opt
, error
, mntflags
, nlsopt
, wall_clock
, len
;
86 char *p
, *p1
, tmp
[1024];
92 if (strcmp(argv
[1], "-h") == 0) {
94 } else if (strcmp(argv
[1], "-v") == 0) {
95 errx(EX_OK
, "version %d.%d.%d", NWFS_VERSION
/ 100000,
96 (NWFS_VERSION
% 10000) / 1000,
97 (NWFS_VERSION
% 1000) / 100);
101 error
= getvfsbyname(NWFS_VFSNAME
, &vfc
);
102 if (error
&& vfsisloadable(NWFS_VFSNAME
)) {
103 if(vfsload(NWFS_VFSNAME
))
104 err(EX_OSERR
, "vfsload("NWFS_VFSNAME
")");
106 error
= getvfsbyname(NWFS_VFSNAME
, &vfc
);
109 errx(EX_OSERR
, "NetWare filesystem is not available");
111 if(ncp_initlib()) exit(1);
113 mntflags
= error
= 0;
114 bzero(&mdata
,sizeof(mdata
));
115 mdata
.uid
= mdata
.gid
= -1;
118 if (ncp_li_init(&li
, argc
, argv
)) return 1;
120 * A little bit weird, but I should figure out which server/user to use
121 * _before_ reading .rc file
123 if (argc
>= 3 && argv
[argc
-1][0] != '-' && argv
[argc
-2][0] != '-' &&
124 argv
[argc
-2][0] == '/') {
128 if (*p
++ != '/') break;
130 while (*p
!= ':' && *p
!= 0) *p1
++ = *p
++;
131 if (*p
++ == 0) break;
133 if (ncp_li_setserver(&li
, tmp
)) break;
135 while (*p
!= '/' && *p
!= 0) *p1
++ = *p
++;
136 if (*p
++ == 0) break;
138 if (ncp_li_setuser(&li
, tmp
)) break;
140 while (*p
!= '/' && *p
!= 0) *p1
++ = *p
++;
142 if (strlen(tmp
) > NCP_VOLNAME_LEN
) {
143 warnx("volume name too long: %s", tmp
);
146 ncp_str_upper(strcpy(mdata
.mounted_vol
,tmp
));
149 p1
= mdata
.root_path
+ 2;
150 pv
= mdata
.root_path
+ 1;
153 while (*p
!= '/' && *p
) {
158 ncp_nls_mem_u2n(pv
+ 1, pv
+ 1, *pv
);
160 mdata
.root_path
[0]++;
162 if (*p
++ == 0) break;
169 "an error occurred while parsing '%s'",
172 if (ncp_li_readrc(&li
)) return 1;
174 parsercfile(&li
,&mdata
);
177 while ((opt
= getopt(argc
, argv
, STDPARAM_OPT
"V:c:d:f:g:l:n:o:u:w:")) != -1) {
180 if (ncp_li_arg(&li
, opt
, optarg
)) {
185 if (strlen(optarg
) > NCP_VOLNAME_LEN
)
186 errx(EX_DATAERR
, "volume too long: %s", optarg
);
187 ncp_str_upper(strcpy(mdata
.mounted_vol
,optarg
));
192 pwd
= isdigit(optarg
[0]) ?
193 getpwuid(atoi(optarg
)) : getpwnam(optarg
);
195 errx(EX_NOUSER
, "unknown user '%s'", optarg
);
196 mdata
.uid
= pwd
->pw_uid
;
202 grp
= isdigit(optarg
[0]) ?
203 getgrgid(atoi(optarg
)) : getgrnam(optarg
);
205 errx(EX_NOUSER
, "unknown group '%s'", optarg
);
206 mdata
.gid
= grp
->gr_gid
;
211 mdata
.dir_mode
= strtol(optarg
, &p
, 8);
212 if (errno
|| *p
!= 0)
213 errx(EX_DATAERR
, "invalid value for directory mode");
217 mdata
.file_mode
= strtol(optarg
, &p
, 8);
218 if (errno
|| *p
!= 0)
219 errx(EX_DATAERR
, "invalid value for file mode");
228 while ((nsp
= strsep(&inp
, ",;:")) != NULL
) {
229 if (strcasecmp(nsp
, "OS2") == 0)
230 mdata
.flags
|= NWFS_MOUNT_NO_OS2
;
231 else if (strcasecmp(nsp
, "LONG") == 0)
232 mdata
.flags
|= NWFS_MOUNT_NO_LONG
;
233 else if (strcasecmp(nsp
, "NFS") == 0)
234 mdata
.flags
|= NWFS_MOUNT_NO_NFS
;
236 errx(EX_DATAERR
, "unknown namespace '%s'", nsp
);
241 if (ncp_nls_setlocale(optarg
) != 0) return 1;
242 mdata
.flags
|= NWFS_MOUNT_HAVE_NLS
;
245 getmntopts(optarg
, mopts
, &mntflags
, 0);
250 nlsopt
|= NWHP_LOWER
;
253 nlsopt
|= NWHP_UPPER
;
256 nlsopt
|= NWHP_LOWER
| NWHP_UPPER
;
259 nlsopt
|= NWHP_LOWER
| NWHP_NOSTRICT
;
262 nlsopt
|= NWHP_UPPER
| NWHP_NOSTRICT
;
265 errx(EX_DATAERR
, "invalid suboption '%c' for -c",
270 if (ncp_nls_setrecodebyname(optarg
) != 0)
272 mdata
.flags
|= NWFS_MOUNT_HAVE_NLS
;
279 if (optind
== argc
- 2) {
281 } else if (mdata
.mounted_vol
[0] == 0)
282 errx(EX_USAGE
, "volume name should be specified");
284 if (optind
!= argc
- 1)
286 realpath(argv
[optind
], mount_point
);
288 if (stat(mount_point
, &st
) == -1)
289 err(EX_OSERR
, "could not find mount point %s", mount_point
);
290 if (!S_ISDIR(st
.st_mode
)) {
292 err(EX_OSERR
, "can't mount on %s", mount_point
);
294 if (ncp_geteinfo(mount_point
, &einfo
) == 0)
295 errx(EX_OSERR
, "can't mount on %s twice", mount_point
);
297 if (mdata
.uid
== -1) {
298 mdata
.uid
= st
.st_uid
;
300 if (mdata
.gid
== -1) {
301 mdata
.gid
= st
.st_gid
;
303 if (mdata
.file_mode
== 0 ) {
304 mdata
.file_mode
= st
.st_mode
& (S_IRWXU
| S_IRWXG
| S_IRWXO
);
306 if (mdata
.dir_mode
== 0) {
307 mdata
.dir_mode
= mdata
.file_mode
;
308 if ((mdata
.dir_mode
& S_IRUSR
) != 0)
309 mdata
.dir_mode
|= S_IXUSR
;
310 if ((mdata
.dir_mode
& S_IRGRP
) != 0)
311 mdata
.dir_mode
|= S_IXGRP
;
312 if ((mdata
.dir_mode
& S_IROTH
) != 0)
313 mdata
.dir_mode
|= S_IXOTH
;
315 if (li
.access_mode
== 0) {
316 li
.access_mode
= mdata
.dir_mode
;
318 /* if (mdata.flags & NWFS_MOUNT_HAVE_NLS) {*/
321 mdata
.nls
.opt
= nlsopt
;
323 mib
[0] = CTL_MACHDEP
;
324 mib
[1] = CPU_WALLCLOCK
;
325 len
= sizeof(wall_clock
);
326 if (sysctl(mib
, 2, &wall_clock
, &len
, NULL
, 0) == -1)
327 err(EX_OSERR
, "get wall_clock");
328 if (wall_clock
== 0) {
330 tm
= localtime(<ime
);
331 mdata
.tz
= -(tm
->tm_gmtoff
/ 60);
334 error
= ncp_li_check(&li
);
337 li
.opt
|= NCP_OPT_WDOG
;
338 /* well, now we can try to login, or use already established connection */
339 error
= ncp_li_login(&li
, &connHandle
);
341 ncp_error("cannot login to server %s", error
, li
.server
);
344 error
= ncp_conn2ref(connHandle
, &mdata
.connRef
);
346 ncp_error("could not convert handle to reference", error
);
347 ncp_disconnect(connHandle
);
350 strcpy(mdata
.mount_point
,mount_point
);
351 mdata
.version
= NWFS_VERSION
;
352 error
= mount(NWFS_VFSNAME
, mdata
.mount_point
, mntflags
, (void*)&mdata
);
354 ncp_error("mount error: %s", error
, mdata
.mount_point
);
355 ncp_disconnect(connHandle
);
359 * I'm leave along my handle, but kernel should keep own ...
361 ncp_disconnect(connHandle
);
362 /* we are done ?, impossible ... */
369 fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n",
370 "usage: mount_nwfs [-Chv] -S server -U user [-connection options]",
371 " -V volume [-M mode] [-c case] [-d mode] [-f mode]",
372 " [-g gid] [-l locale] [-n os2] [-u uid] [-w scheme]",
374 " mount_nwfs [-options] /server:user/volume[/path] node");