Add mount_nwfs program. Now -current can mount NetWare volumes.

This commit is contained in:
Boris Popov 1999-10-15 09:59:48 +00:00
parent ce0b1244e8
commit a51e71fc64
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=52252
7 changed files with 1157 additions and 1 deletions

View File

@ -63,7 +63,7 @@ SUBDIR= adjkerntz \
vinum
.if ${MACHINE_ARCH} == i386
SUBDIR+= kget
SUBDIR+= kget mount_nwfs
.endif
.if exists(${.CURDIR}/${MACHINE_ARCH})

15
sbin/mount_nwfs/Makefile Normal file
View File

@ -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>

View File

@ -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

View File

@ -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"
);
}

View File

@ -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>

View File

@ -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

View File

@ -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"
);
}