summaryrefslogtreecommitdiffstats
path: root/sbin/mount_nwfs
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/mount_nwfs')
-rw-r--r--sbin/mount_nwfs/Makefile15
-rw-r--r--sbin/mount_nwfs/mount_nwfs.8191
-rw-r--r--sbin/mount_nwfs/mount_nwfs.c372
3 files changed, 578 insertions, 0 deletions
diff --git a/sbin/mount_nwfs/Makefile b/sbin/mount_nwfs/Makefile
new file mode 100644
index 0000000..5340596
--- /dev/null
+++ b/sbin/mount_nwfs/Makefile
@@ -0,0 +1,15 @@
+# $FreeBSD$
+
+PROG= mount_nwfs
+SRCS= mount_nwfs.c getmntopts.c
+MAN8= mount_nwfs.8
+
+MOUNT= ${.CURDIR}/../mount
+CFLAGS+= -DNWFS -I${MOUNT}
+
+.PATH: ${MOUNT}
+
+LDADD+= -lncp -lipx
+DPADD+= ${LIBIPX} ${LIBNCP}
+
+.include <bsd.prog.mk>
diff --git a/sbin/mount_nwfs/mount_nwfs.8 b/sbin/mount_nwfs/mount_nwfs.8
new file mode 100644
index 0000000..83a880f
--- /dev/null
+++ b/sbin/mount_nwfs/mount_nwfs.8
@@ -0,0 +1,191 @@
+.\" $FreeBSD$
+.Dd Oct 14, 1999
+.Dt MOUNT_NWFS 8
+.Os FreeBSD 4.0
+.Sh NAME
+.Nm mount_nwfs
+.Nd mount NetWare volume from a NetWare file server
+.Sh SYNOPSIS
+.Nm mount_nwfs
+.Op Fl Chv
+.Ar -S Ar server
+.Ar -U Ar user
+.Ar "[connection options]"
+.Ar -V Ar volume
+.Op Fl M Ar mode
+.Op Fl c Ar case
+.Op Fl d Ar mode
+.Op Fl f Ar mode
+.Op Fl g Ar gid
+.Op Fl l Ar locale
+.Op Fl n Ar os2
+.Op Fl u Ar uid
+.Op Fl w Ar scheme
+.Ar node
+.Nm mount_nwfs
+.Op Fl options
+.Ar /server:user/volume/path
+.Ar node
+.Sh DESCRIPTION
+The
+.Nm
+command allow to mount volume from a NetWare server. It may use either
+existing connection or create new: if no usable connection was found
+it will try to establish a new one. Connection has count of references to it,
+so when last mount will be dismounted connection will be closed. It is
+possible to create connection without any mounts (but use it for them) with
+.Xr ncplogin 1 .
+.Pp
+Note two forms of command line. In the first form, server and user specified
+via
+.Fl S
+and
+.Fl U
+options respectively. In the second form server and user specified in
+.Ar special
+part of
+.Xr mount 8
+command line arguments (the
+.Fl S ,
+.Fl U
+and
+.Fl V
+options aren't used in this case). This allows use of fstab file (see EXAMPLES below).
+.Pp
+The options are:
+.Bl -tag -width indent
+.It Fl S Ar server
+name of NetWare server to connect. For native IP you will need also
+.Fl A
+option.
+.It Fl U Ar user
+name of user used in login sequence.
+.It Fl "[connection options]"
+See
+.Xr ncplogin 1
+for details.
+.It Fl V Ar volume
+Volume name to mount. Volume name can also be specified after all options and
+before
+.Ar mount-point .
+.It Ar node
+Path to mount volume.
+.It Fl c Ar case
+Selects a
+.Ar case
+option which affects on name representation.
+.Ar Case
+can be one of the following:
+.Bd -literal -offset indent
+Value Meaning
+l All existing file names converted to lower case.
+ Newly created file gets a lower case under OS2 name
+ space. This is default when mounting volumes with DOS
+ name space.
+L Same as 'l' but file system tries to be case
+ insensitive. May not work well.
+n No case conversion is performed.
+ Warning! Warning!: use this option with DOS name
+ space only as a last resort, because creating a lower
+ case name in the DOS name space can lead to an
+ unpredictable results. This is default when mounting
+ volume with OS2 name space.
+u All existing file names converted to upper case. Newly
+ created file gets an upper case under OS2 name space.
+U Same as 'u' but file system tries to be case insensitive.
+ May not work well.
+.Ed
+.It Fl f Ar mode, Fl d Ar mode
+specifies permissions that should be assigned to files and directories.
+The values must be specified as octal numbers. Default value for the file mode
+taken from mount point, default value for the dir mode adds execute permission
+where the file mode gives read permission.
+
+Note that these permissions can differ from the rights granted by NetWare
+server.
+.It Fl n Ar namespace
+don't use
+.Ar namespace .
+Currently only
+.Ar OS2
+can be here.
+.It Fl v
+prints version number.
+.It Fl u Ar uid, Fl g Ar gid
+User id and group id assigned to files. The default is owner and group id from
+directory where volume is mounted.
+.It Fl l Ar locale
+Sets the locale for case conversion. By default
+.Nm
+tries to use an environment variable
+.Ar LC_* .
+.It Fl w Ar scheme
+Selects a
+.Ar scheme
+used to convert file names between NetWare and FreeBSD. Currently only
+.Ar koi2cp866
+and
+.Ar asis
+can be here. Please note, that scheme should be enabled at compile
+time in config.mk file.
+.It Fl M Ar mode
+See
+.Xr ncplogin 1
+for details. If this option is ommited, connection permissions
+assumed the same as directory mode (
+.Ar -d )
+option.
+.El
+.Sh FILES
+.Bl -tag -width /var/log/wtmp -compact
+.It Pa ~/.nwfsrc
+keeps description for each connection. See
+.Xr nwfsrc 8
+for details.
+
+.Sh NOTES
+Before any NCP connection can be established kernel must be configured
+for IPX support, IPXrouted and KLD nwfs.ko should be loaded.
+.Sh EXAMPLES
+Next examples illustrates how to connect to NetWare server
+.Ar nwserv
+as user
+.Ar GUEST
+and mount volumes
+.Ar SYS
+and
+.Ar VOL1 :
+.Bd -literal -offset indent
+mount_nwfs -S nwserv -U guest -V sys /nw/s1/sys
+mount_nwfs /nwserv:guest/sys /nw/s1/sys
+mount -t nwfs /nwserv:guest/vol1 /nw/s1/vol1
+mount -t nwfs /nwserv:boris/sys/home/boris /home/boris/nw/home
+.Ed
+.Pp
+The last example mounts only subdirectory on a volume and equivalent
+to NetWare 'map root' command.
+.Pp
+It is possible to use fstab for nwfs mounts:
+.Bd -literal -offset indent
+/nwserv:guest/sys /nw/s1/sys nwfs rw,noauto 0 0
+/nwserv:guest/vol1 /nw/s1/vol2 nwfs rw,noauto 0 0
+.Ed
+
+.Sh BUGS
+to number a few
+
+.Sh CREDITS
+In development of NetWare client for FreeBSD next sources was used:
+.Pp
+Documentation from NetWare NDK.
+.Pp
+ncpfs for Linux - written by Volker Lendecke (lendecke@math.uni-goettingen.de).
+He grants me permission to publish parts of his code under BSD-style license,
+.Pp
+"Interrupt List" from Ralf Brown,
+.Pp
+Many files from /sys directory.
+
+.Sh AUTHOR
+.An Boris Popov Aq bp@butya.kz ,
+.Aq rbp@chat.ru
diff --git a/sbin/mount_nwfs/mount_nwfs.c b/sbin/mount_nwfs/mount_nwfs.c
new file mode 100644
index 0000000..363b8cc
--- /dev/null
+++ b/sbin/mount_nwfs/mount_nwfs.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1999, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/mount.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <err.h>
+#include <sysexits.h>
+
+#include <netncp/ncp_lib.h>
+#include <netncp/ncp_rcfile.h>
+#include <nwfs/nwfs.h>
+#include <nwfs/nwfs_mount.h>
+#include "mntopts.h"
+
+#define NWFS_VFSNAME "nwfs"
+
+extern char *__progname;
+static char mount_point[MAXPATHLEN + 1];
+static void usage(void);
+static int parsercfile(struct ncp_conn_loginfo *li, struct nwfs_args *mdata);
+
+static struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ { NULL }
+};
+
+static int
+parsercfile(struct ncp_conn_loginfo *li, struct nwfs_args *mdata) {
+ return 0;
+}
+
+int
+main(int argc, char *argv[]) {
+ int opt, error, mntflags, nlsopt;
+ char *p, *p1, tmp[1024];
+ u_char *pv;
+ NWCONN_HANDLE connHandle;
+ struct nwfs_args mdata;
+ struct ncp_conn_loginfo li;
+ struct stat st;
+ struct vfsconf vfc;
+ struct nw_entry_info einfo;
+
+ if (argc < 2) {
+ usage();
+ exit(1);
+ }
+ if (argc == 2) {
+ if (strcmp(argv[1], "-h") == 0) {
+ usage();
+ exit(0);
+ } else if (strcmp(argv[1], "-v") == 0) {
+ errx(EX_OK, "version %d.%d.%d", NWFS_VERSION / 100000,
+ (NWFS_VERSION % 10000) / 1000,
+ (NWFS_VERSION % 1000) / 100);
+ }
+ }
+
+ error = getvfsbyname(NWFS_VFSNAME, &vfc);
+ if (error && vfsisloadable(NWFS_VFSNAME)) {
+ if(vfsload(NWFS_VFSNAME))
+ err(EX_OSERR, "vfsload("NWFS_VFSNAME")");
+ endvfsent();
+ error = getvfsbyname(NWFS_VFSNAME, &vfc);
+ }
+ if (error)
+ errx(EX_OSERR, "NetWare filesystem is not available");
+
+ if(ncp_initlib()) exit(1);
+
+ mntflags = error = 0;
+ bzero(&mdata,sizeof(mdata));
+ mdata.uid = mdata.gid = -1;
+ nlsopt = 0;
+
+ if (ncp_li_init(&li, argc, argv)) return 1;
+ /*
+ * A little bit weird, but I should figure out which server/user to use
+ * _before_ reading .rc file
+ */
+ if (argc >= 3 && argv[argc-1][0] != '-' && argv[argc-2][0] != '-' &&
+ argv[argc-2][0] == '/') {
+ p = argv[argc-2];
+ error = 1;
+ do {
+ if (*p++ != '/') break;
+ p1 = tmp;
+ while (*p != ':' && *p != 0) *p1++ = *p++;
+ if (*p++ == 0) break;
+ *p1 = 0;
+ if (ncp_li_setserver(&li, tmp)) break;
+ p1 = tmp;
+ while (*p != '/' && *p != 0) *p1++ = *p++;
+ if (*p++ == 0) break;
+ *p1 = 0;
+ if (ncp_li_setuser(&li, tmp)) break;
+ p1 = tmp;
+ while (*p != '/' && *p != 0) *p1++ = *p++;
+ *p1 = 0;
+ if (strlen(tmp) > NCP_VOLNAME_LEN) {
+ fprintf(stderr, "Volume name too long: %s\n", tmp);
+ break;
+ }
+ ncp_str_upper(strcpy(mdata.mounted_vol,tmp));
+ if (*p == '/')
+ p++;
+ p1 = mdata.root_path + 2;
+ pv = mdata.root_path + 1;
+ for(;*p;) {
+ *pv = 0;
+ while (*p != '/' && *p) {
+ *p1++ = *p++;
+ (*pv)++;
+ }
+ if (*pv) {
+ ncp_nls_mem_u2n(pv + 1, pv + 1, *pv);
+ pv += (*pv) + 1;
+ mdata.root_path[0]++;
+ }
+ if (*p++ == 0) break;
+ p1++;
+ }
+ error = 0;
+ } while(0);
+ if (error)
+ errx(EX_DATAERR,
+ "An error occured while parsing '%s'",
+ argv[argc - 2]);
+ }
+ if (ncp_li_readrc(&li)) return 1;
+ if (ncp_rc) {
+ parsercfile(&li,&mdata);
+ rc_close(ncp_rc);
+ }
+ while ((opt = getopt(argc, argv, STDPARAM_OPT"V:c:d:f:g:l:n:o:u:w:")) != EOF) {
+ switch (opt) {
+ case STDPARAM_ARGS:
+ if (ncp_li_arg(&li, opt, optarg)) {
+ return 1;
+ }
+ break;
+ case 'V':
+ if (strlen(optarg) > NCP_VOLNAME_LEN)
+ errx(EX_DATAERR, "Volume too long: %s\n", optarg);
+ ncp_str_upper(strcpy(mdata.mounted_vol,optarg));
+ break;
+ case 'u': {
+ struct passwd *pwd;
+
+ pwd = isdigit(optarg[0]) ?
+ getpwuid(atoi(optarg)) : getpwnam(optarg);
+ if (pwd == NULL)
+ errx(EX_NOUSER, "unknown user '%s'", optarg);
+ mdata.uid = pwd->pw_uid;
+ break;
+ }
+ case 'g': {
+ struct group *grp;
+
+ grp = isdigit(optarg[0]) ?
+ getgrgid(atoi(optarg)) : getgrnam(optarg);
+ if (grp == NULL)
+ errx(EX_NOUSER, "unknown group '%s'", optarg);
+ mdata.gid = grp->gr_gid;
+ break;
+ }
+ case 'd':
+ errno = 0;
+ mdata.dir_mode = strtol(optarg, &p, 8);
+ if (errno || *p != 0)
+ errx(EX_DATAERR, "invalid value for directory mode");
+ break;
+ case 'f':
+ errno = 0;
+ mdata.file_mode = strtol(optarg, &p, 8);
+ if (errno || *p != 0)
+ errx(EX_DATAERR, "invalid value for file mode");
+ break;
+ case '?':
+ usage();
+ exit(1); /*NOTREACHED*/
+ case 'n': {
+ char *inp, *nsp;
+
+ nsp = inp = optarg;
+ while ((nsp = strsep(&inp, ",;:")) != NULL) {
+ if (strcasecmp(nsp, "OS2") == 0)
+ mdata.flags |= NWFS_MOUNT_NO_OS2;
+ else if (strcasecmp(nsp, "LONG") == 0)
+ mdata.flags |= NWFS_MOUNT_NO_LONG;
+ else if (strcasecmp(nsp, "NFS") == 0)
+ mdata.flags |= NWFS_MOUNT_NO_NFS;
+ else
+ errx(EX_DATAERR, "Unknown namespace '%s'", nsp);
+ }
+ break;
+ };
+ case 'l':
+ if (ncp_nls_setlocale(optarg) != 0) return 1;
+ mdata.flags |= NWFS_MOUNT_HAVE_NLS;
+ break;
+ case 'o':
+ getmntopts(optarg, mopts, &mntflags, 0);
+ break;
+ case 'c':
+ switch (optarg[0]) {
+ case 'l':
+ nlsopt |= NWHP_LOWER;
+ break;
+ case 'u':
+ nlsopt |= NWHP_UPPER;
+ break;
+ case 'n':
+ nlsopt |= NWHP_LOWER | NWHP_UPPER;
+ break;
+ case 'L':
+ nlsopt |= NWHP_LOWER | NWHP_NOSTRICT;
+ break;
+ case 'U':
+ nlsopt |= NWHP_UPPER | NWHP_NOSTRICT;
+ break;
+ default:
+ errx(EX_DATAERR, "invalid suboption '%c' for -c",
+ optarg[0]);
+ }
+ break;
+ case 'w':
+ if (ncp_nls_setrecodebyname(optarg) != 0)
+ return 1;
+ mdata.flags |= NWFS_MOUNT_HAVE_NLS;
+ break;
+ default:
+ usage();
+ return 1;
+ }
+ }
+
+ if (optind == argc - 2) {
+ optind++;
+ } else if (mdata.mounted_vol[0] == 0)
+ errx(EX_USAGE, "Volume name should be specified");
+
+ if (optind != argc - 1) {
+ usage();
+ return 1;
+ }
+ realpath(argv[optind], mount_point);
+
+ if (stat(mount_point, &st) == -1)
+ err(EX_OSERR, "could not find mount point %s", mount_point);
+ if (!S_ISDIR(st.st_mode)) {
+ errno = ENOTDIR;
+ err(EX_OSERR, "can't mount on %s", mount_point);
+ }
+ if (ncp_geteinfo(mount_point, &einfo) == 0)
+ errx(EX_OSERR, "can't mount on %s twice", mount_point);
+
+ if (mdata.uid == -1) {
+ mdata.uid = st.st_uid;
+ }
+ if (mdata.gid == -1) {
+ mdata.gid = st.st_gid;
+ }
+ if (mdata.file_mode == 0 ) {
+ mdata.file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ if (mdata.dir_mode == 0) {
+ mdata.dir_mode = mdata.file_mode;
+ if ((mdata.dir_mode & S_IRUSR) != 0)
+ mdata.dir_mode |= S_IXUSR;
+ if ((mdata.dir_mode & S_IRGRP) != 0)
+ mdata.dir_mode |= S_IXGRP;
+ if ((mdata.dir_mode & S_IROTH) != 0)
+ mdata.dir_mode |= S_IXOTH;
+ }
+ if (li.access_mode == 0) {
+ li.access_mode = mdata.dir_mode;
+ }
+/* if (mdata.flags & NWFS_MOUNT_HAVE_NLS) {*/
+ mdata.nls = ncp_nls;
+/* }*/
+ mdata.nls.opt = nlsopt;
+ error = ncp_li_check(&li);
+ if (error)
+ return 1;
+ li.opt |= NCP_OPT_WDOG;
+ /* well, now we can try to login, or use already established connection */
+ error = ncp_li_login(&li,&connHandle);
+ if( error ){
+ fprintf(stderr,"Cannot login to server %s,%s\n",li.server,strerror(errno));
+ ncp_disconnect(connHandle);
+ return(1);
+ }
+ error = ncp_conn2ref(connHandle, &mdata.connRef);
+ if (error) {
+ fprintf(stderr,"Cannot convert handle to refernce. Consider this as a big bug.\n");
+ ncp_disconnect(connHandle);
+ return(1);
+ }
+ strcpy(mdata.mount_point,mount_point);
+ mdata.version = NWFS_VERSION;
+ error = mount(NWFS_VFSNAME, mdata.mount_point, mntflags, (void*)&mdata);
+ if (error) {
+ fprintf(stderr,"mount error: %s\n", strerror(errno));
+ ncp_disconnect(connHandle);
+ exit(1);
+ }
+ /*
+ * I'm leave along my handle, but kernel should keep own ...
+ */
+ ncp_disconnect(connHandle);
+ /* we are done ?, impossible ... */
+ return 0;
+}
+
+static void
+usage(void) {
+ printf("usage: %s [connection options] [options] \n"
+ " server:user/volume[/path] mount-point\n\n", __progname);
+ printf(
+ "see ncplogin(1) for details on connection options\n"
+ " -A host Netware/IP host address\n"
+ " -u uid uid the mounted files get\n"
+ " -g gid gid the mounted files get\n"
+ " -f mode permission the files get\n"
+ " -d mode permission the dirs get\n"
+ " -h print this help text\n"
+ " -v print nwfs version number\n"
+ "\n"
+ );
+}
OpenPOWER on IntegriCloud