Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fa4442004 | ||
|
|
aaa3c6e7cc | ||
|
|
f6e0a67e78 |
BIN
.downloads/ncpfs-0.2.tgz
Normal file
BIN
.downloads/ncpfs-0.2.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.3.tgz
Normal file
BIN
.downloads/ncpfs-0.3.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.4.tgz
Normal file
BIN
.downloads/ncpfs-0.4.tgz
Normal file
Binary file not shown.
17
BUGS
Normal file
17
BUGS
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Maybe you want to look at LIMITATIONS in README. Some might consider
|
||||||
|
them to be bugs.
|
||||||
|
|
||||||
|
But there are really problems that might be fixed in the future.
|
||||||
|
|
||||||
|
Invalid directory timestamps:
|
||||||
|
I did not yet find out how to get valid timestamps for directories
|
||||||
|
from a NetWare server. So I simply return 0, which means 01.01.70. If
|
||||||
|
anybody knows how to get these values, please mail
|
||||||
|
lendecke@namu01.gwdg.de.
|
||||||
|
|
||||||
|
'df' returns 0:
|
||||||
|
Free disk space is distributed among the volumes in NetWare. df is
|
||||||
|
only able to report one number per mounted filesystem. As connections
|
||||||
|
are quite expensive for NetWare (with lwared that might change ...), I
|
||||||
|
rejected the alternative to mount only a single volume for a unix
|
||||||
|
mount point. So I simply return 0.
|
||||||
19
Changes
Normal file
19
Changes
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
ncpfs-0.3 -> ncpfs-0.4
|
||||||
|
|
||||||
|
- removed bug causing kernel to crash on filenames too long
|
||||||
|
This was a typical C bug! Thanks to Uwe Bonnes,
|
||||||
|
bon@elektron.ikp.physik.th-darmstadt.de for his patience with this one.
|
||||||
|
|
||||||
|
ncpfs-0.2 -> ncpfs-0.3
|
||||||
|
|
||||||
|
- removed bug in get_pname_static
|
||||||
|
- removed bug in 'ncpmount -n'
|
||||||
|
- fake '.' and '..'
|
||||||
|
- return 0 for df and directory timestamps. See file BUGS
|
||||||
|
|
||||||
|
ncpfs-0.1 -> ncpfs-0.2
|
||||||
|
|
||||||
|
- should be compileable with gcc other than 2.7.0
|
||||||
|
- first attempt at read/write access
|
||||||
|
- more complete ncpmount.c
|
||||||
|
- included file ipx.tar
|
||||||
22
Makefile
22
Makefile
@@ -6,7 +6,7 @@ INCLUDES = -I/usr/src/linux/include
|
|||||||
|
|
||||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||||
$(INCLUDES) \
|
$(INCLUDES) \
|
||||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP=2 -DDEBUG_NCP_MALLOC
|
||||||
# -DDEBUG_NCP_MALLOC
|
# -DDEBUG_NCP_MALLOC
|
||||||
|
|
||||||
CC = gcc -D__KERNEL__ -I.
|
CC = gcc -D__KERNEL__ -I.
|
||||||
@@ -22,26 +22,32 @@ ARCH = i386
|
|||||||
|
|
||||||
OBJS= inode.o dir.o file.o sock.o ioctl.o ncplib.o nwcrypt.o
|
OBJS= inode.o dir.o file.o sock.o ioctl.o ncplib.o nwcrypt.o
|
||||||
|
|
||||||
all: ncpfs.o ncpmount
|
all: ncpfs.o ncpmount ncptest
|
||||||
|
|
||||||
ncpfs.o: $(OBJS)
|
ncpfs.o: $(OBJS)
|
||||||
$(LD) -r -o ncpfs.o $(OBJS)
|
$(LD) -r -o ncpfs.o $(OBJS)
|
||||||
|
|
||||||
ncpmount: ncpmount.o
|
ncplib.o: ncplib.c ncplib.h
|
||||||
|
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||||
|
|
||||||
|
ncpmount: ncpmount.o
|
||||||
gcc -o ncpmount ncpmount.o
|
gcc -o ncpmount ncpmount.o
|
||||||
|
|
||||||
ncpmount.o: ncpmount.c
|
ncpmount.o: ncpmount.c
|
||||||
gcc -c ncpmount.c -Wall -I. -g
|
gcc -c ncpmount.c -Wall -I. -g
|
||||||
|
|
||||||
|
ncptest: ncptest.o ncplib_user.o nwcrypt.o
|
||||||
|
gcc -o ncptest ncptest.o ncplib_user.o nwcrypt.o
|
||||||
|
|
||||||
|
ncptest.o: ncptest.c
|
||||||
|
gcc -c ncptest.c -Wall -I. -g
|
||||||
|
|
||||||
ncplib_user.o: ncplib.o
|
ncplib_user.o: ncplib.o
|
||||||
gcc -c ncplib.c -Wall -I. -g -o ncplib_user.o
|
gcc -c ncplib.c -O3 -Wall -I. -g -o ncplib_user.o
|
||||||
|
|
||||||
nwcrypt.o: nwcrypt.c
|
nwcrypt.o: nwcrypt.c
|
||||||
gcc -c -O2 -Wall nwcrypt.c
|
gcc -c -O2 -Wall nwcrypt.c
|
||||||
|
|
||||||
ncpumount: ncpumount.o
|
|
||||||
gcc -o ncpumount ncpumount.o
|
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
@@ -49,7 +55,7 @@ clean:
|
|||||||
rm -f *.o *~
|
rm -f *.o *~
|
||||||
|
|
||||||
realclean: clean
|
realclean: clean
|
||||||
rm -fr ncpmount ncpumount .depend $(DISTFILE) mnt
|
rm -fr ncpmount ncptest .depend $(DISTFILE) mnt *.out
|
||||||
|
|
||||||
modules: ncpfs.o
|
modules: ncpfs.o
|
||||||
|
|
||||||
|
|||||||
133
README
133
README
@@ -1,90 +1,55 @@
|
|||||||
This is version 0.1 of ncpfs, a free NetWare client for Linux. For me
|
This is version 0.2 of ncpfs, a free NetWare client for Linux. For me
|
||||||
it works with 1.3.32 and 1.3.35.
|
it works with 1.3.32
|
||||||
|
|
||||||
I know that this piece of software is VERY incomplete, as it only
|
I know that this piece of software is VERY incomplete, I have to
|
||||||
gives you read-only access. I have to apologize for that. But I
|
apologize for that. But I thought I should make it publically
|
||||||
thought I should make it publically available, because I have tried to
|
available, because I have tried to ask several people about the legal
|
||||||
ask several people about the legal status of the code. I did not get
|
status of the code. I did not get very satisfying answers. So I publish
|
||||||
very satisfying answers. So I publish ncpfs to open it for
|
ncpfs to open it for criticism. If nobody complains, I will go on
|
||||||
criticism. If nobody complains, I will go on working.
|
working.
|
||||||
|
|
||||||
To install ncpfs, just type 'make', 'insmod ncpfs.o' and
|
To install ncpfs, just type 'make', 'insmod ncpfs.o' and then
|
||||||
'ncpmount server mount-point user password'. Please note that your IPX
|
'ncpmount server mount-point'. Please note that your IPX system has to
|
||||||
system has to be configured correctly. There has to be a route to the
|
be configured correctly. There has to be a route to the internal
|
||||||
internal network of your server. I use tools from the dosemu-0.60.3
|
network of your server. Please see the file start_ipx for an example.
|
||||||
distribution to do this. Once again I have to apologize for this
|
|
||||||
cryptic description, but before I'm sure that I'm allowed to do all
|
I use tools written by Greg Page, Caldera. I hope I did not do too
|
||||||
this I will not do more.
|
much harm to their business. For your convenience I included the file
|
||||||
|
ipx.tar made available by Caldera.
|
||||||
|
|
||||||
I read that Novell is not very open when it comes to technical details
|
My main source of information is a book written in german by Manfred
|
||||||
of the Netware Core Protocol. This might be especially true for the
|
Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH,
|
||||||
encryption stuff. I took the necessary code from Dr. Dobb's Journal
|
1995, ISBN 3-88322-491-X. It contains quite a lot of typographical and
|
||||||
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
|
other errors, but I find it very valuable as an introduction to NCP
|
||||||
the legal status of this piece of code:
|
programming. If you know about the concepts and possibilities of NCP,
|
||||||
|
Ralph Brown's interrupt list becomes much more readable. It's much
|
||||||
|
easier to find undocumented information if you know what to look for!
|
||||||
---
|
|
||||||
Date: Thu, 12 Oct 1995 13:44:18 +0100
|
For the curious: the file ncplib.c is usable from user space as well.
|
||||||
From: Volker Lendecke <lendecke>
|
Look at the file ncptest.c for a possible use. I use ncptest to check
|
||||||
To: jon@ddj.com
|
my assumptions about the widely undocumented NetWare Core Protocol.
|
||||||
Subject: legal status of your source code?
|
Maybe this is the beginning of a free NetWare API for Linux! I would
|
||||||
|
be happy to receive your comments on this.
|
||||||
|
|
||||||
Hello!
|
|
||||||
|
|
||||||
I hope that you're the right one to write to, you are the first on your WWW
|
|
||||||
server. If you are not, could you please forward this message to the right
|
|
||||||
person? Thanks.
|
|
||||||
|
|
||||||
I'm currently exploring the possibility to write a free (in the GNU GPL
|
|
||||||
sense) NCP filesystem, which would allow me to access a novell server
|
|
||||||
transparently. For that I would like to use the encryption functions you
|
|
||||||
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
|
|
||||||
changes, such as other indentations, minor code changes and so on. But I do
|
|
||||||
not know if that allows me to publish this code under GPL. One alternative
|
|
||||||
would be to publish a diff against your listing, but that would probably
|
|
||||||
contain much of your code as well, and it would be very inconvenient for
|
|
||||||
the average user.
|
|
||||||
|
|
||||||
I think that you have some kind of standard procedure for such a
|
|
||||||
case. Please tell me what I should do.
|
|
||||||
|
|
||||||
Many thanks in advance,
|
|
||||||
|
|
||||||
Volker
|
|
||||||
|
|
||||||
+=================================================================+
|
|
||||||
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
|
|
||||||
! D-37081 Goettingen, Germany !
|
|
||||||
+=================================================================+
|
|
||||||
|
|
||||||
--
|
|
||||||
|
|
||||||
|
|
||||||
I got the following answer:
|
|
||||||
|
|
||||||
---
|
|
||||||
From: Jon Erickson <jon@ddj.com>
|
|
||||||
X-Mailer: SCO System V Mail (version 3.2)
|
|
||||||
To: lendecke@namu01.gwdg.de
|
|
||||||
Subject: Re: legal status of your source code?
|
|
||||||
Date: Thu, 12 Oct 95 5:42:56 PDT
|
|
||||||
|
|
||||||
Volker,
|
|
||||||
Code from Dr. Dobb's Journal related articles is provided for
|
|
||||||
anyone to use. Clearly, the author of the article should be
|
|
||||||
given credit.
|
|
||||||
Jon Erickson
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
With this answer in mind, I took the code and made it a bit more
|
|
||||||
C-like. The original seemed to be translated by a mechanical pascal->c
|
|
||||||
translator. Jon's answer encouraged me to publish nwcrypt.c under the
|
|
||||||
GPL. If anybody who knows more about copyright and sees any problems
|
|
||||||
with this, please tell me.
|
|
||||||
|
|
||||||
|
|
||||||
|
LIMITATIONS (compare these with smbfs :-)
|
||||||
|
|
||||||
|
The limitations ncpfs has are the natural limitations of the NCP
|
||||||
|
protocol, which was designed with MS-DOS based PCs in mind. The first
|
||||||
|
limitation is the lack of uid, gid and permission information per
|
||||||
|
file. You have to assign those values once for a complete mounted
|
||||||
|
directory.
|
||||||
|
|
||||||
|
The second limitation is just as annoying as the first: You cannot
|
||||||
|
re-export a ncp-mounted directory by nfs. It is not possible because
|
||||||
|
the NFS protocol defines access to files through unique file handles,
|
||||||
|
which can be mapped to the device and inode numbers in unix NFS
|
||||||
|
servers. NCP does not have unique numbers per file, you only have the
|
||||||
|
path name. I implemented a caching scheme for inode numbers, which
|
||||||
|
gives unique inode numbers for every open file in the system. This is
|
||||||
|
just sufficient for local use of the files, because you can tell when
|
||||||
|
an inode number can be discarded. With NFS the situation is
|
||||||
|
different. You can never know when the client will access the file-id
|
||||||
|
you offered, so you would have to cache the inode numbers
|
||||||
|
indefinitely long. I think this should not be done in kernel mode, as
|
||||||
|
it would require an unlimited amount of RAM.
|
||||||
|
|||||||
361
dir.c
361
dir.c
@@ -1,4 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* dir.c
|
* dir.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 1995 by Volker Lendecke
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
@@ -60,6 +60,23 @@ static int
|
|||||||
ncp_lookup(struct inode *dir, const char *__name,
|
ncp_lookup(struct inode *dir, const char *__name,
|
||||||
int len, struct inode **result);
|
int len, struct inode **result);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||||
|
struct inode **result);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_mkdir(struct inode *dir, const char *name, int len, int mode);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_rmdir(struct inode *dir, const char *name, int len);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_unlink(struct inode *dir, const char *name, int len);
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||||
|
struct inode *new_dir, const char *new_name, int new_len);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
date_dos2unix(unsigned short time,unsigned short date);
|
date_dos2unix(unsigned short time,unsigned short date);
|
||||||
|
|
||||||
@@ -103,15 +120,15 @@ static struct file_operations ncp_dir_operations = {
|
|||||||
|
|
||||||
struct inode_operations ncp_dir_inode_operations = {
|
struct inode_operations ncp_dir_inode_operations = {
|
||||||
&ncp_dir_operations, /* default directory file ops */
|
&ncp_dir_operations, /* default directory file ops */
|
||||||
NULL, /* create */
|
ncp_create, /* create */
|
||||||
ncp_lookup, /* lookup */
|
ncp_lookup, /* lookup */
|
||||||
NULL, /* link */
|
NULL, /* link */
|
||||||
NULL, /* unlink */
|
ncp_unlink, /* unlink */
|
||||||
NULL, /* symlink */
|
NULL, /* symlink */
|
||||||
NULL, /* mkdir */
|
ncp_mkdir, /* mkdir */
|
||||||
NULL, /* rmdir */
|
ncp_rmdir, /* rmdir */
|
||||||
NULL, /* mknod */
|
NULL, /* mknod */
|
||||||
NULL, /* rename */
|
ncp_rename, /* rename */
|
||||||
NULL, /* readlink */
|
NULL, /* readlink */
|
||||||
NULL, /* follow_link */
|
NULL, /* follow_link */
|
||||||
NULL, /* bmap */
|
NULL, /* bmap */
|
||||||
@@ -286,13 +303,34 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_read_volume_list(struct ncp_server *server, int start_with, int cache_size)
|
ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
||||||
{
|
{
|
||||||
struct ncp_dirent *entry = c_entry;
|
struct ncp_dirent *entry = c_entry;
|
||||||
|
|
||||||
int total_count = 0;
|
int total_count = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
void fill_one(char *name)
|
||||||
|
{
|
||||||
|
if (total_count < fpos) {
|
||||||
|
DPRINTK("ncp_do_readdir: skipped file: %s\n", name);
|
||||||
|
} else if (total_count >= fpos + cache_size) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
DPRINTK("ncp_do_readdir: found file: %s\n", name);
|
||||||
|
|
||||||
|
entry->attr = aDIR;
|
||||||
|
entry->mtime = 0;
|
||||||
|
entry->ctime = 0;
|
||||||
|
entry->atime = 0;
|
||||||
|
entry->size = 1024;
|
||||||
|
entry->f_pos = total_count;
|
||||||
|
strcpy(entry->path, name);
|
||||||
|
entry += 1;
|
||||||
|
}
|
||||||
|
total_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++) {
|
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++) {
|
||||||
|
|
||||||
struct ncp_volume_info info;
|
struct ncp_volume_info info;
|
||||||
@@ -302,29 +340,12 @@ ncp_read_volume_list(struct ncp_server *server, int start_with, int cache_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(info.volume_name) > 0) {
|
if (strlen(info.volume_name) > 0) {
|
||||||
|
fill_one(info.volume_name);
|
||||||
if (total_count < start_with) {
|
|
||||||
DPRINTK("ncp_read_volumes: skipped vol: %s\n",
|
|
||||||
info.volume_name);
|
|
||||||
} else if (total_count >= start_with + cache_size) {
|
|
||||||
return (total_count - start_with);
|
|
||||||
} else {
|
|
||||||
DPRINTK("ncp_read_volumes: found vol %s\n",
|
|
||||||
info.volume_name);
|
|
||||||
entry->attr = aDIR;
|
|
||||||
entry->mtime = 0;
|
|
||||||
entry->ctime = 0;
|
|
||||||
entry->atime = 0;
|
|
||||||
entry->size = 1024;
|
|
||||||
entry->f_pos = total_count;
|
|
||||||
strcpy(entry->path, info.volume_name);
|
|
||||||
entry += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_count += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (total_count - start_with);
|
fill_one(".");
|
||||||
|
fill_one("..");
|
||||||
|
return (total_count - fpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -336,6 +357,41 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
|||||||
|
|
||||||
int total_count = 0;
|
int total_count = 0;
|
||||||
|
|
||||||
|
void fill_one(int attr, char *name,
|
||||||
|
int upd_time, int upd_date,
|
||||||
|
int cr_date, int ac_date, int length)
|
||||||
|
{
|
||||||
|
if (total_count < fpos) {
|
||||||
|
DPRINTK("ncp_do_readdir: skipped file: %s\n", name);
|
||||||
|
} else if (total_count >= fpos + cache_size) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
DPRINTK("ncp_do_readdir: found file: %s\n", name);
|
||||||
|
|
||||||
|
entry->attr = attr;
|
||||||
|
if ((attr & aDIR) == 0) {
|
||||||
|
entry->mtime = date_dos2unix(upd_time,
|
||||||
|
upd_date);
|
||||||
|
entry->ctime = date_dos2unix(0, cr_date);
|
||||||
|
entry->atime = date_dos2unix(0, ac_date);
|
||||||
|
entry->size = length;
|
||||||
|
} else {
|
||||||
|
/* Sorry, I do not know how to get the
|
||||||
|
* values for directories :-(. Mail
|
||||||
|
* lendecke@namu01.gwdg.de if you
|
||||||
|
* know more. */
|
||||||
|
entry->mtime = 0;
|
||||||
|
entry->ctime = 0;
|
||||||
|
entry->atime = 0;
|
||||||
|
entry->size = 1024;
|
||||||
|
}
|
||||||
|
entry->f_pos = total_count;
|
||||||
|
strcpy(entry->path, name);
|
||||||
|
entry += 1;
|
||||||
|
}
|
||||||
|
total_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
void doit(int attr) {
|
void doit(int attr) {
|
||||||
|
|
||||||
if (ncp_file_search_init(server, 0, NCP_FINFO(dir)->path,
|
if (ncp_file_search_init(server, 0, NCP_FINFO(dir)->path,
|
||||||
@@ -346,36 +402,20 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
|||||||
|
|
||||||
while (ncp_file_search_continue(server, &fsinfo, attr, "*",
|
while (ncp_file_search_continue(server, &fsinfo, attr, "*",
|
||||||
&finfo) == 0) {
|
&finfo) == 0) {
|
||||||
|
|
||||||
|
fill_one(attr, finfo.file_name,
|
||||||
|
finfo.update_time, finfo.update_date,
|
||||||
|
finfo.creation_date, finfo.access_date,
|
||||||
|
finfo.file_length);
|
||||||
|
|
||||||
if (total_count < fpos) {
|
|
||||||
DPRINTK("ncp_do_readdir: skipped file: %s\n",
|
|
||||||
finfo.file_name);
|
|
||||||
} else if (total_count >= fpos + cache_size) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
DPRINTK("ncp_do_readdir: found file: %s\n",
|
|
||||||
finfo.file_name);
|
|
||||||
|
|
||||||
entry->attr = attr;
|
|
||||||
entry->mtime =
|
|
||||||
date_dos2unix(finfo.update_time,
|
|
||||||
finfo.update_date);
|
|
||||||
entry->ctime =
|
|
||||||
date_dos2unix(0, finfo.creation_date);
|
|
||||||
entry->atime =
|
|
||||||
date_dos2unix(0, finfo.access_date);
|
|
||||||
;
|
|
||||||
entry->size = (attr & aDIR) != 0 ?
|
|
||||||
1024 : finfo.file_length;
|
|
||||||
entry->f_pos = total_count;
|
|
||||||
strcpy(entry->path, finfo.file_name);
|
|
||||||
entry += 1;
|
|
||||||
}
|
|
||||||
total_count += 1;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fill_one(aDIR, ".", 0, 0, 0, 0, 0);
|
||||||
|
fill_one(aDIR, "..", 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
doit(0);
|
doit(0);
|
||||||
doit(aDIR);
|
doit(aDIR);
|
||||||
|
|
||||||
@@ -437,8 +477,10 @@ get_pname_static(struct inode *dir, const char *name, int len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
DPRINTK("get_pname_static: parentname = %s, len = %d\n",
|
DDPRINTK("get_pname_static: parentname = %s, parlen = %d\n",
|
||||||
parentname, parentlen);
|
parentname, parentlen);
|
||||||
|
DDPRINTK("get_pname_static: name = %s, len = %d\n",
|
||||||
|
name, len);
|
||||||
|
|
||||||
if (len > NCP_MAXNAMELEN) {
|
if (len > NCP_MAXNAMELEN) {
|
||||||
return -ENAMETOOLONG;
|
return -ENAMETOOLONG;
|
||||||
@@ -458,16 +500,16 @@ get_pname_static(struct inode *dir, const char *name, int len,
|
|||||||
char *pos = strrchr(parentname, '\\');
|
char *pos = strrchr(parentname, '\\');
|
||||||
|
|
||||||
if ( (pos == NULL)
|
if ( (pos == NULL)
|
||||||
&& (parentlen == 0)) {
|
&& ( (parentname[parentlen-1] == ':')
|
||||||
|
|| (parentlen == 0))) {
|
||||||
|
|
||||||
/* We're at the top */
|
/* We're at the top */
|
||||||
|
|
||||||
path[0] = '\\';
|
path[0] = '\0';
|
||||||
path[1] = '\0';
|
*res_len = 0;
|
||||||
*res_len = 2;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (pos == NULL) {
|
if (pos == NULL) {
|
||||||
printk("ncp_make_name: Bad parent NCP-name: %s",
|
printk("ncp_make_name: Bad parent NCP-name: %s",
|
||||||
@@ -481,7 +523,6 @@ get_pname_static(struct inode *dir, const char *name, int len,
|
|||||||
path[len] = '\0';
|
path[len] = '\0';
|
||||||
}
|
}
|
||||||
else if (parentlen == 0) {
|
else if (parentlen == 0) {
|
||||||
|
|
||||||
memcpy(path, name, len);
|
memcpy(path, name, len);
|
||||||
path[len] = ':';
|
path[len] = ':';
|
||||||
path[len+1] = '\0';
|
path[len+1] = '\0';
|
||||||
@@ -501,7 +542,7 @@ get_pname_static(struct inode *dir, const char *name, int len,
|
|||||||
|
|
||||||
*res_len = len;
|
*res_len = len;
|
||||||
|
|
||||||
DPRINTK("get_pname: path = %s, *pathlen = %d\n",
|
DDPRINTK("get_pname: path = %s, *pathlen = %d\n",
|
||||||
path, *res_len);
|
path, *res_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -514,7 +555,7 @@ get_pname(struct inode *dir, const char *name, int len,
|
|||||||
int result_len;
|
int result_len;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if ((res = get_pname_static(dir,name,len,result,&result_len) != 0)) {
|
if ((res = get_pname_static(dir,name,len,result,&result_len)) != 0) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +755,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTK("ncp_lookup: %s\n", __name);
|
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
||||||
|
|
||||||
server = NCP_SERVER(dir);
|
server = NCP_SERVER(dir);
|
||||||
|
|
||||||
@@ -730,6 +771,9 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DDPRINTK("ncp_lookup: get_pname for %s returned %d\n",
|
||||||
|
__name, error);
|
||||||
|
|
||||||
result_info = ncp_find_inode(NCP_SERVER(dir), name);
|
result_info = ncp_find_inode(NCP_SERVER(dir), name);
|
||||||
|
|
||||||
if (result_info != 0) {
|
if (result_info != 0) {
|
||||||
@@ -771,10 +815,10 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
i, c_entry[i].path);
|
i, c_entry[i].path);
|
||||||
if (strcmp(c_entry[i].path, __name) == 0) {
|
if (strcmp(c_entry[i].path, __name) == 0) {
|
||||||
DPRINTK("ncp_lookup: found in cache!\n");
|
DPRINTK("ncp_lookup: found in cache!\n");
|
||||||
finfo = c_entry[i];
|
finfo = c_entry[i];
|
||||||
finfo.path = NULL; /* It's not ours! */
|
finfo.path = NULL; /* It's not ours! */
|
||||||
found_in_cache = 1;
|
found_in_cache = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = (i + 1) % c_size;
|
i = (i + 1) % c_size;
|
||||||
DDPRINTK("ncp_lookup: index %d, name %s failed\n",
|
DDPRINTK("ncp_lookup: index %d, name %s failed\n",
|
||||||
@@ -845,10 +889,191 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||||
|
struct inode **result)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
char *path = NULL;
|
||||||
|
struct ncp_dirent entry;
|
||||||
|
struct ncp_file_info finfo;
|
||||||
|
struct ncp_dirent *ino_finfo;
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
|
|
||||||
|
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||||
|
printk("ncp_create: inode is NULL or not a directory\n");
|
||||||
|
iput(dir);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* The following are taken directly from msdos-fs */
|
/* Now we will have to build up an NCP filename. */
|
||||||
|
if ((error = get_pname(dir, name, len, &path, &len)) < 0) {
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_create_newfile(NCP_SERVER(dir), 0, path, 0, &finfo) != 0) {
|
||||||
|
put_pname(path);
|
||||||
|
iput(dir);
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.attr = finfo.file_attributes;
|
||||||
|
entry.mtime = date_dos2unix(finfo.update_time,
|
||||||
|
finfo.update_date);
|
||||||
|
entry.ctime = date_dos2unix(0, finfo.creation_date);
|
||||||
|
entry.atime = date_dos2unix(0, finfo.access_date);
|
||||||
|
entry.size = 0;
|
||||||
|
|
||||||
|
ncp_invalid_dir_cache(dir->i_ino);
|
||||||
|
|
||||||
|
if (!(*result = ncp_iget(dir, path, &entry)) < 0) {
|
||||||
|
ncp_close_file(NCP_SERVER(dir), finfo.file_id);
|
||||||
|
put_pname(path);
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ino_finfo = &(NCP_INOP(*result)->finfo);
|
||||||
|
ino_finfo->opened = 1;
|
||||||
|
ino_finfo->access = O_RDWR;
|
||||||
|
memcpy(&(ino_finfo->file_id), finfo.file_id, NCP_FILE_ID_LEN);
|
||||||
|
|
||||||
|
iput(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
char path[NCP_MAXPATHLEN];
|
||||||
|
|
||||||
|
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||||
|
printk("ncp_mkdir: inode is NULL or not a directory\n");
|
||||||
|
iput(dir);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we will have to build up an NCP filename. */
|
||||||
|
if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = ncp_create_directory(NCP_SERVER(dir), 0, path,
|
||||||
|
0xff)) == 0) {
|
||||||
|
ncp_invalid_dir_cache(dir->i_ino);
|
||||||
|
}
|
||||||
|
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_rmdir(struct inode *dir, const char *name, int len)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
char path[NCP_MAXPATHLEN];
|
||||||
|
|
||||||
|
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||||
|
printk("ncp_rmdir: inode is NULL or not a directory\n");
|
||||||
|
iput(dir);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) {
|
||||||
|
error = -EBUSY;
|
||||||
|
} else {
|
||||||
|
if ((error = ncp_delete_directory(NCP_SERVER(dir),
|
||||||
|
0, path)) == 0) {
|
||||||
|
ncp_invalid_dir_cache(dir->i_ino);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_unlink(struct inode *dir, const char *name, int len)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
char path[NCP_MAXPATHLEN];
|
||||||
|
|
||||||
|
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||||
|
printk("ncp_unlink: inode is NULL or not a directory\n");
|
||||||
|
iput(dir);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
if ((error = get_pname_static(dir, name, len, path, &len)) < 0) {
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) {
|
||||||
|
error = -EBUSY;
|
||||||
|
} else {
|
||||||
|
if ((error = ncp_erase_file(NCP_SERVER(dir), 0, path,
|
||||||
|
0)) == 0)
|
||||||
|
ncp_invalid_dir_cache(dir->i_ino);
|
||||||
|
}
|
||||||
|
|
||||||
|
iput(dir);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||||
|
struct inode *new_dir, const char *new_name, int new_len)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
char old_path[NCP_MAXPATHLEN], new_path[NCP_MAXPATHLEN];
|
||||||
|
|
||||||
|
if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
|
||||||
|
printk("ncp_rename: old inode is NULL or not a directory\n");
|
||||||
|
res = -ENOENT;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
|
||||||
|
printk("ncp_rename: new inode is NULL or not a directory\n");
|
||||||
|
res = -ENOENT;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len);
|
||||||
|
if (res < 0) {
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len);
|
||||||
|
if (res < 0) {
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (ncp_find_inode(NCP_SERVER(old_dir), old_path) != NULL)
|
||||||
|
|| (ncp_find_inode(NCP_SERVER(new_dir), new_path) != NULL)) {
|
||||||
|
res = -EBUSY;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = ncp_rename_file(NCP_SERVER(old_dir), 0, old_path, 0,0, new_path);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
ncp_invalid_dir_cache(old_dir->i_ino);
|
||||||
|
ncp_invalid_dir_cache(new_dir->i_ino);
|
||||||
|
}
|
||||||
|
|
||||||
|
finished:
|
||||||
|
iput(old_dir);
|
||||||
|
iput(new_dir);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following routines are taken directly from msdos-fs */
|
||||||
|
|
||||||
/* Linear day numbers of the respective 1sts in non-leap years. */
|
/* Linear day numbers of the respective 1sts in non-leap years. */
|
||||||
|
|
||||||
|
|||||||
83
file.c
83
file.c
@@ -93,9 +93,6 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
|
||||||
return errno;
|
|
||||||
|
|
||||||
pos = file->f_pos;
|
pos = file->f_pos;
|
||||||
|
|
||||||
if (pos + count > inode->i_size)
|
if (pos + count > inode->i_size)
|
||||||
@@ -104,6 +101,9 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||||
|
|
||||||
already_read = 0;
|
already_read = 0;
|
||||||
@@ -145,10 +145,85 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
|||||||
return already_read;
|
return already_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
||||||
|
int count)
|
||||||
|
{
|
||||||
|
int bufsize, to_write, already_written;
|
||||||
|
off_t pos;
|
||||||
|
int errno;
|
||||||
|
|
||||||
|
if (!inode) {
|
||||||
|
DPRINTK("ncp_file_write: inode = NULL\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(inode->i_mode)) {
|
||||||
|
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
|
||||||
|
inode->i_mode);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTK("ncp_file_write: enter %s\n", NCP_FINFO(inode)->path);
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
pos = file->f_pos;
|
||||||
|
|
||||||
|
if (file->f_flags & O_APPEND)
|
||||||
|
pos = inode->i_size;
|
||||||
|
|
||||||
|
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||||
|
|
||||||
|
already_written = 0;
|
||||||
|
|
||||||
|
while (already_written < count) {
|
||||||
|
|
||||||
|
int written_this_time;
|
||||||
|
|
||||||
|
if ((pos % bufsize) != 0) {
|
||||||
|
to_write = bufsize - (pos % bufsize);
|
||||||
|
} else {
|
||||||
|
to_write = bufsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
to_write = min(to_write, count - already_written);
|
||||||
|
if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_id,
|
||||||
|
pos, to_write, buf, &written_this_time) != 0) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += written_this_time;
|
||||||
|
buf += written_this_time;
|
||||||
|
already_written += written_this_time;
|
||||||
|
|
||||||
|
if (written_this_time < to_write) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inode->i_mtime = inode->i_ctime = CURRENT_TIME;
|
||||||
|
inode->i_dirt = 1;
|
||||||
|
|
||||||
|
file->f_pos = pos;
|
||||||
|
|
||||||
|
if (pos > inode->i_size) {
|
||||||
|
inode->i_size = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINTK("ncp_file_write: exit %s\n", NCP_FINFO(inode)->path);
|
||||||
|
|
||||||
|
return already_written;
|
||||||
|
}
|
||||||
|
|
||||||
static struct file_operations ncp_file_operations = {
|
static struct file_operations ncp_file_operations = {
|
||||||
NULL, /* lseek - default */
|
NULL, /* lseek - default */
|
||||||
ncp_file_read, /* read */
|
ncp_file_read, /* read */
|
||||||
NULL, /* write */
|
ncp_file_write, /* write */
|
||||||
NULL, /* readdir - bad */
|
NULL, /* readdir - bad */
|
||||||
NULL, /* select - default */
|
NULL, /* select - default */
|
||||||
ncp_ioctl, /* ioctl */
|
ncp_ioctl, /* ioctl */
|
||||||
|
|||||||
79
inode.c
79
inode.c
@@ -34,15 +34,17 @@ extern int close_fp(struct file *filp);
|
|||||||
static void ncp_put_inode(struct inode *);
|
static void ncp_put_inode(struct inode *);
|
||||||
static void ncp_read_inode(struct inode *);
|
static void ncp_read_inode(struct inode *);
|
||||||
static void ncp_put_super(struct super_block *);
|
static void ncp_put_super(struct super_block *);
|
||||||
|
static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
|
||||||
|
static int ncp_notify_change(struct inode *inode, struct iattr *attr);
|
||||||
|
|
||||||
static struct super_operations ncp_sops = {
|
static struct super_operations ncp_sops = {
|
||||||
ncp_read_inode, /* read inode */
|
ncp_read_inode, /* read inode */
|
||||||
NULL, /* notify change */
|
ncp_notify_change, /* notify change */
|
||||||
NULL, /* write inode */
|
NULL, /* write inode */
|
||||||
ncp_put_inode, /* put inode */
|
ncp_put_inode, /* put inode */
|
||||||
ncp_put_super, /* put superblock */
|
ncp_put_super, /* put superblock */
|
||||||
NULL, /* write superblock */
|
NULL, /* write superblock */
|
||||||
NULL, /* stat filesystem */
|
ncp_statfs, /* stat filesystem */
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -328,6 +330,79 @@ ncp_put_super(struct super_block *sb)
|
|||||||
MOD_DEC_USE_COUNT;
|
MOD_DEC_USE_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
||||||
|
{
|
||||||
|
struct statfs tmp;
|
||||||
|
|
||||||
|
/* We cannot say how much disk space is left on a mounted
|
||||||
|
NetWare Server, because free space is distributed over
|
||||||
|
volumes, and the current user might have disk quotas. So
|
||||||
|
free space is not that simple to determine. Our decision
|
||||||
|
here is to err conservatively. */
|
||||||
|
|
||||||
|
tmp.f_type = NCP_SUPER_MAGIC;
|
||||||
|
tmp.f_bsize = 512;
|
||||||
|
tmp.f_blocks = 0;
|
||||||
|
tmp.f_bfree = 0;
|
||||||
|
tmp.f_bavail = 0;
|
||||||
|
tmp.f_files = -1;
|
||||||
|
tmp.f_ffree = -1;
|
||||||
|
tmp.f_namelen = 12;
|
||||||
|
memcpy_tofs(buf, &tmp, bufsiz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DO MORE */
|
||||||
|
static int
|
||||||
|
ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if ((error = inode_change_ok(inode, attr)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (((attr->ia_valid & ATTR_UID) &&
|
||||||
|
(attr->ia_uid != NCP_SERVER(inode)->m.uid)))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (((attr->ia_valid & ATTR_GID) &&
|
||||||
|
(attr->ia_uid != NCP_SERVER(inode)->m.gid)))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (((attr->ia_valid & ATTR_MODE) &&
|
||||||
|
(attr->ia_mode &
|
||||||
|
~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
||||||
|
|
||||||
|
struct ncp_file_info finfo;
|
||||||
|
struct ncp_dirent *dirent = NCP_FINFO(inode);
|
||||||
|
|
||||||
|
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
||||||
|
dirent->path, attr->ia_size);
|
||||||
|
|
||||||
|
if (attr->ia_size != 0) {
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NCP_FINFO(inode)->opened != 0) {
|
||||||
|
ncp_close_file(NCP_SERVER(inode), dirent->file_id);
|
||||||
|
dirent->opened = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_create_file(NCP_SERVER(inode), 0,
|
||||||
|
dirent->path, 0, &finfo) == 0) {
|
||||||
|
ncp_close_file(NCP_SERVER(inode), finfo.file_id);
|
||||||
|
dirent->opened = 0;
|
||||||
|
}
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_NCP_MALLOC
|
#ifdef DEBUG_NCP_MALLOC
|
||||||
int ncp_malloced;
|
int ncp_malloced;
|
||||||
|
|||||||
34
ncp.h
34
ncp.h
@@ -18,28 +18,28 @@
|
|||||||
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
||||||
|
|
||||||
struct ncp_request_header {
|
struct ncp_request_header {
|
||||||
__u16 type;
|
__u16 type __attribute__ ((packed));
|
||||||
__u8 sequence;
|
__u8 sequence __attribute__ ((packed));
|
||||||
__u8 conn_low;
|
__u8 conn_low __attribute__ ((packed));
|
||||||
__u8 task;
|
__u8 task __attribute__ ((packed));
|
||||||
__u8 conn_high;
|
__u8 conn_high __attribute__ ((packed));
|
||||||
__u8 function;
|
__u8 function __attribute__ ((packed));
|
||||||
__u8 data[0]; /* Depends upon request type */
|
__u8 data[0] __attribute__ ((packed));
|
||||||
} __attribute__ ((packed));
|
};
|
||||||
|
|
||||||
#define NCP_REPLY (0x3333)
|
#define NCP_REPLY (0x3333)
|
||||||
#define NCP_POSITIVE_ACK (0x9999)
|
#define NCP_POSITIVE_ACK (0x9999)
|
||||||
|
|
||||||
struct ncp_reply_header {
|
struct ncp_reply_header {
|
||||||
__u16 type;
|
__u16 type __attribute__ ((packed));
|
||||||
__u8 sequence;
|
__u8 sequence __attribute__ ((packed));
|
||||||
__u8 conn_low;
|
__u8 conn_low __attribute__ ((packed));
|
||||||
__u8 task;
|
__u8 task __attribute__ ((packed));
|
||||||
__u8 conn_high;
|
__u8 conn_high __attribute__ ((packed));
|
||||||
__u8 completion_code;
|
__u8 completion_code __attribute__ ((packed));
|
||||||
__u8 connection_state;
|
__u8 connection_state __attribute__ ((packed));
|
||||||
__u8 data[0]; /* Depends upon request type */
|
__u8 data[0] __attribute__ ((packed));
|
||||||
} __attribute__ ((packed));
|
};
|
||||||
|
|
||||||
|
|
||||||
#define NCP_BINDERY_USER (0x0001)
|
#define NCP_BINDERY_USER (0x0001)
|
||||||
|
|||||||
7
ncp_fs.h
7
ncp_fs.h
@@ -50,10 +50,10 @@ struct ncp_ioctl_request {
|
|||||||
#define NCP_SUPER_MAGIC 0x564c
|
#define NCP_SUPER_MAGIC 0x564c
|
||||||
|
|
||||||
|
|
||||||
#define NCP_SBP(sb) ((struct ncp_server *)(sb->u.generic_sbp))
|
#define NCP_SBP(sb) ((struct ncp_server *)((sb)->u.generic_sbp))
|
||||||
#define NCP_INOP(inode) ((struct ncp_inode_info *)(inode->u.generic_ip))
|
#define NCP_INOP(inode) ((struct ncp_inode_info *)((inode)->u.generic_ip))
|
||||||
|
|
||||||
#define NCP_SERVER(inode) NCP_SBP(inode->i_sb)
|
#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb)
|
||||||
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
||||||
|
|
||||||
static inline int min(int a, int b) {
|
static inline int min(int a, int b) {
|
||||||
@@ -124,7 +124,6 @@ int ncp_ioctl (struct inode * inode, struct file * filp,
|
|||||||
/* linux/fs/ncpfs/inode.c */
|
/* linux/fs/ncpfs/inode.c */
|
||||||
struct super_block *ncp_read_super(struct super_block *sb,
|
struct super_block *ncp_read_super(struct super_block *sb,
|
||||||
void *raw_data, int silent);
|
void *raw_data, int silent);
|
||||||
int ncp_notify_change(struct inode *inode, struct iattr *attr);
|
|
||||||
void ncp_invalidate_connection(struct ncp_server *server);
|
void ncp_invalidate_connection(struct ncp_server *server);
|
||||||
int ncp_conn_is_valid(struct ncp_server *server);
|
int ncp_conn_is_valid(struct ncp_server *server);
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
Begin3
|
Begin3
|
||||||
Title: ncpfs
|
Title: ncpfs
|
||||||
Version: 0.1
|
Version: 0.4
|
||||||
Entered-date: 19. October 1995
|
Entered-date: 02. November 1995
|
||||||
Description: With ncpfs you can mount volumes of your novell
|
Description: With ncpfs you can mount volumes of your novell
|
||||||
server under Linux.
|
server under Linux.
|
||||||
Keywords: filesystem kernel ncp novell
|
Keywords: filesystem kernel ncp novell netware
|
||||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
Primary-site: linux01.gwdg.de:/pub/smbfs
|
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
||||||
~30k ncpfs-0.1.tgz
|
~45k ncpfs-0.4.tgz
|
||||||
~ 1k ncpfs-0.1.lsm
|
~ 1k ncpfs-0.4.lsm
|
||||||
Copying-policy: GPL
|
Copying-policy: GPL
|
||||||
End
|
End
|
||||||
237
ncplib.c
237
ncplib.c
@@ -126,6 +126,19 @@ ncp_add_mem(struct ncp_server *server, const char *source, int size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
static void
|
||||||
|
ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
|
||||||
|
{
|
||||||
|
assert_server_locked(server);
|
||||||
|
memcpy_fromfs(&(server->packet[server->current_size]), source, size);
|
||||||
|
server->current_size += size;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ncp_add_pstring(struct ncp_server *server, const char *s)
|
ncp_add_pstring(struct ncp_server *server, const char *s)
|
||||||
{
|
{
|
||||||
@@ -536,6 +549,176 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ncp_do_create(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target,
|
||||||
|
int function)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, dir_handle);
|
||||||
|
ncp_add_byte(server, attr);
|
||||||
|
ncp_add_pstring(server, path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, function)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(target->file_id), ncp_reply_data(server, 0),
|
||||||
|
NCP_FILE_ID_LEN);
|
||||||
|
|
||||||
|
memset(&(target->file_name), 0, sizeof(target->file_name));
|
||||||
|
memcpy(&(target->file_name), ncp_reply_data(server, 8),
|
||||||
|
NCP_MAX_FILENAME);
|
||||||
|
|
||||||
|
target->file_attributes = ncp_reply_byte(server, 22);
|
||||||
|
target->file_mode = ncp_reply_byte(server, 23);
|
||||||
|
target->file_length = ntohl(ncp_reply_dword(server, 24));
|
||||||
|
target->creation_date = ntohs(ncp_reply_word(server, 28));
|
||||||
|
target->access_date = ntohs(ncp_reply_word(server, 30));
|
||||||
|
target->update_date = ntohs(ncp_reply_word(server, 32));
|
||||||
|
target->update_time = ntohs(ncp_reply_word(server, 34));
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_newfile(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target)
|
||||||
|
{
|
||||||
|
return ncp_do_create(server, dir_handle, path, attr, target, 77);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_file(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target)
|
||||||
|
{
|
||||||
|
return ncp_do_create(server, dir_handle, path, attr, target, 67);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_erase_file(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, dir_handle);
|
||||||
|
ncp_add_byte(server, attr);
|
||||||
|
ncp_add_pstring(server, path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 68)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_rename_file(struct ncp_server *server,
|
||||||
|
int old_handle, const char *old_path,
|
||||||
|
int attr,
|
||||||
|
int new_handle, const char *new_path)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, old_handle);
|
||||||
|
ncp_add_byte(server, attr);
|
||||||
|
ncp_add_pstring(server, old_path);
|
||||||
|
ncp_add_byte(server, new_handle);
|
||||||
|
ncp_add_pstring(server, new_path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 69)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_directory(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int inherit_mask)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request_s(server, 10);
|
||||||
|
ncp_add_byte(server, dir_handle);
|
||||||
|
ncp_add_byte(server, inherit_mask);
|
||||||
|
ncp_add_pstring(server, path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 22)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_delete_directory(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request_s(server, 11);
|
||||||
|
ncp_add_byte(server, dir_handle);
|
||||||
|
ncp_add_byte(server, 0); /* reserved */
|
||||||
|
ncp_add_pstring(server, path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 22)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_rename_directory(struct ncp_server *server,
|
||||||
|
int dir_handle,
|
||||||
|
const char *old_path, const char *new_path)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request_s(server, 15);
|
||||||
|
ncp_add_byte(server, dir_handle);
|
||||||
|
ncp_add_pstring(server, old_path);
|
||||||
|
ncp_add_pstring(server, new_path);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 22)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef __KERNEL__
|
#ifndef __KERNEL__
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -565,9 +748,35 @@ ncp_read(struct ncp_server *server, const char *file_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_write(struct ncp_server *server, const char *file_id,
|
||||||
|
__u32 offset, __u16 to_write,
|
||||||
|
const char *source, int *bytes_written)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, 0);
|
||||||
|
ncp_add_mem(server, file_id, 6);
|
||||||
|
ncp_add_dword(server, htonl(offset));
|
||||||
|
ncp_add_word(server, htons(to_write));
|
||||||
|
ncp_add_mem(server, source, to_write);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 73)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytes_written = to_write;
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/* We have to read into user space */
|
/* We have to transfer to/from user space */
|
||||||
int
|
int
|
||||||
ncp_read(struct ncp_server *server, const char *file_id,
|
ncp_read(struct ncp_server *server, const char *file_id,
|
||||||
__u32 offset, __u16 to_read,
|
__u32 offset, __u16 to_read,
|
||||||
@@ -595,4 +804,30 @@ ncp_read(struct ncp_server *server, const char *file_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_write(struct ncp_server *server, const char *file_id,
|
||||||
|
__u32 offset, __u16 to_write,
|
||||||
|
const char *source, int *bytes_written)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
ncp_init_request(server);
|
||||||
|
ncp_add_byte(server, 0);
|
||||||
|
ncp_add_mem(server, file_id, 6);
|
||||||
|
ncp_add_dword(server, htonl(offset));
|
||||||
|
ncp_add_word(server, htons(to_write));
|
||||||
|
ncp_add_mem_fromfs(server, source, to_write);
|
||||||
|
|
||||||
|
if ((result = ncp_request(server, 73)) != 0) {
|
||||||
|
ncp_printf("ncp_request_error: %d\n", result);
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bytes_written = to_write;
|
||||||
|
|
||||||
|
ncp_unlock_server(server);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
44
ncplib.h
44
ncplib.h
@@ -94,9 +94,51 @@ ncp_open_file(struct ncp_server *server,
|
|||||||
int
|
int
|
||||||
ncp_close_file(struct ncp_server *server, const char *file_id);
|
ncp_close_file(struct ncp_server *server, const char *file_id);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_newfile(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_file(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr,
|
||||||
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_erase_file(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int attr);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_rename_file(struct ncp_server *server,
|
||||||
|
int old_handle, const char *old_path,
|
||||||
|
int attr,
|
||||||
|
int new_handle, const char *new_path);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_create_directory(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path,
|
||||||
|
int inherit_mask);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_delete_directory(struct ncp_server *server,
|
||||||
|
int dir_handle, const char *path);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_rename_directory(struct ncp_server *server,
|
||||||
|
int dir_handle,
|
||||||
|
const char *old_path, const char *new_path);
|
||||||
|
|
||||||
int
|
int
|
||||||
ncp_read(struct ncp_server *server, const char *file_id,
|
ncp_read(struct ncp_server *server, const char *file_id,
|
||||||
__u32 start, __u16 to_read,
|
__u32 offset, __u16 to_read,
|
||||||
char *target, int *bytes_read);
|
char *target, int *bytes_read);
|
||||||
|
|
||||||
|
int
|
||||||
|
ncp_write(struct ncp_server *server, const char *file_id,
|
||||||
|
__u32 offset, __u16 to_write,
|
||||||
|
const char *source, int *bytes_written);
|
||||||
|
|
||||||
#endif /* _NCPLIB_H */
|
#endif /* _NCPLIB_H */
|
||||||
|
|||||||
450
ncpmount.c
450
ncpmount.c
@@ -15,13 +15,11 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
|
||||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||||
extern pid_t waitpid(pid_t, int *, int);
|
extern pid_t waitpid(pid_t, int *, int);
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -38,8 +36,54 @@ extern pid_t waitpid(pid_t, int *, int);
|
|||||||
#include "ipxutil.h"
|
#include "ipxutil.h"
|
||||||
|
|
||||||
static char *progname;
|
static char *progname;
|
||||||
static char *mount_point;
|
|
||||||
static char *server_name;
|
|
||||||
|
static void
|
||||||
|
str_upper(char *name)
|
||||||
|
{
|
||||||
|
while (*name) {
|
||||||
|
*name = toupper(*name);
|
||||||
|
name = name + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
fullpath(const char *p)
|
||||||
|
{
|
||||||
|
char path[MAXPATHLEN];
|
||||||
|
|
||||||
|
if (realpath(p, path) == NULL)
|
||||||
|
return strdup(p);
|
||||||
|
else
|
||||||
|
return strdup(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
printf("usage: %s server mount-point [options]\n", progname);
|
||||||
|
printf("Try `%s -h' for more information\n", progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
help(void)
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("usage: %s server mount-point [options]\n", progname);
|
||||||
|
printf("\n"
|
||||||
|
"-U username Username sent to server\n"
|
||||||
|
"-u uid uid the mounted files get\n"
|
||||||
|
"-g gid gid the mounted files get\n"
|
||||||
|
"-f mode permission the files get (octal notation)\n"
|
||||||
|
"-d mode permission the dirs get (octal notation)\n"
|
||||||
|
"-C Don't convert password to uppercase\n"
|
||||||
|
"-P password Use this password\n"
|
||||||
|
"-n Do not use any password\n"
|
||||||
|
" If neither -P nor -n are given, you are\n"
|
||||||
|
" asked for a password.\n"
|
||||||
|
"-h print this help text\n"
|
||||||
|
"\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct sap_query {
|
struct sap_query {
|
||||||
unsigned short query_type; /* net order */
|
unsigned short query_type; /* net order */
|
||||||
@@ -47,15 +91,14 @@ struct sap_query {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct sap_server_ident {
|
struct sap_server_ident {
|
||||||
unsigned short server_type;
|
unsigned short server_type __attribute__ ((packed));
|
||||||
char server_name[48];
|
char server_name[48] __attribute__ ((packed));
|
||||||
IPXNet server_network;
|
IPXNet server_network __attribute__ ((packed));
|
||||||
IPXNode server_node;
|
IPXNode server_node __attribute__ ((packed));
|
||||||
IPXPort server_port;
|
IPXPort server_port __attribute__ ((packed));
|
||||||
unsigned short intermediate_network;
|
unsigned short intermediate_network __attribute__ ((packed));
|
||||||
} __attribute__ ((packed));
|
};
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ipx_fprint_node(FILE* file,IPXNode node)
|
ipx_fprint_node(FILE* file,IPXNode node)
|
||||||
{
|
{
|
||||||
@@ -212,33 +255,217 @@ ipx_sap_find_server(char *name, int server_type, int timeout,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipx_sscanf_node(char *buf, unsigned char node[6])
|
int
|
||||||
|
ipx_sscanf_node(char *buf, unsigned char node[6])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int n[6];
|
int n[6];
|
||||||
|
|
||||||
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
||||||
&(n[0]), &(n[1]), &(n[2]),
|
&(n[0]), &(n[1]), &(n[2]),
|
||||||
&(n[3]), &(n[4]), &(n[5]))) != 6) {
|
&(n[3]), &(n[4]), &(n[5]))) != 6) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<6; i++) {
|
for (i=0; i<6; i++) {
|
||||||
node[i] = n[i];
|
node[i] = n[i];
|
||||||
}
|
}
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
main(int argc, char **argv)
|
parse_args(int argc, char *argv[], struct ncp_mount_data *data,
|
||||||
|
int *got_password, int *upcase_password)
|
||||||
{
|
{
|
||||||
struct ncp_mount_data data;
|
int opt;
|
||||||
struct stat st;
|
struct passwd *pwd;
|
||||||
struct sockaddr_ipx addr;
|
struct group *grp;
|
||||||
int ncp_sock, wdog_sock;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
progname = argv[0];
|
*got_password = 0;
|
||||||
|
*upcase_password = 1;
|
||||||
|
|
||||||
|
while ((opt = getopt (argc, argv, "Cp:s:c:U:u:g:f:d:m:P:n")) != EOF) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'C':
|
||||||
|
*upcase_password = 0;
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
if (strlen(optarg) > 63) {
|
||||||
|
fprintf(stderr, "Username too long: %s\n",
|
||||||
|
optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(data->username, optarg);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (isdigit(optarg[0])) {
|
||||||
|
data->uid = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
pwd = getpwnam(optarg);
|
||||||
|
if (pwd == NULL) {
|
||||||
|
fprintf(stderr, "Unknown user: %s\n",
|
||||||
|
optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
data->uid = pwd->pw_uid;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
if (isdigit(optarg[0])) {
|
||||||
|
data->gid = atoi(optarg);
|
||||||
|
} else {
|
||||||
|
grp = getgrnam(optarg);
|
||||||
|
if (grp == NULL) {
|
||||||
|
fprintf(stderr, "Unknown group: %s\n",
|
||||||
|
optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
data->gid = grp->gr_gid;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
data->file_mode = strtol(optarg, NULL, 8);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
data->dir_mode = strtol(optarg, NULL, 8);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
strcpy(data->password, optarg);
|
||||||
|
*got_password = 1;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
data->password[0] = '\0';
|
||||||
|
*got_password = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns 0 if the filesystem is in the kernel after this routine
|
||||||
|
completes */
|
||||||
|
static int
|
||||||
|
load_ncpfs()
|
||||||
|
{
|
||||||
|
FILE *fver, *ffs;
|
||||||
|
char s[1024];
|
||||||
|
char modname[1024];
|
||||||
|
char *p, *p1;
|
||||||
|
pid_t pid;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/* Check if ncpfs is in the kernel */
|
||||||
|
ffs = fopen("/proc/filesystems", "r");
|
||||||
|
if (ffs == NULL) {
|
||||||
|
perror("Error: \"/proc/filesystems\" could not be read:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = NULL;
|
||||||
|
while (! feof(ffs)) {
|
||||||
|
p1 = fgets(s, sizeof(s), ffs);
|
||||||
|
if (p1) {
|
||||||
|
p = strstr(s, "ncpfs");
|
||||||
|
if (p) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(ffs);
|
||||||
|
if (p) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fver = fopen("/proc/version", "r");
|
||||||
|
if (fver == NULL) {
|
||||||
|
perror("Error: \"/proc/version\" could not be read:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fgets(s, 1024, fver);
|
||||||
|
fclose(fver);
|
||||||
|
p = strstr(s, "version ");
|
||||||
|
if (p == NULL) {
|
||||||
|
version_error:
|
||||||
|
fprintf(stderr, "Error: Unable to determine the Linux version"
|
||||||
|
"from \"/proc/version\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p = strchr(p, ' ') + 1;
|
||||||
|
p1 = strchr(p, ' ');
|
||||||
|
if (p1 == NULL) {
|
||||||
|
goto version_error;
|
||||||
|
}
|
||||||
|
strcpy(modname, "/lib/modules/");
|
||||||
|
strncat(modname, p, p1 - p);
|
||||||
|
strcat(modname, "/ncpfs.o");
|
||||||
|
|
||||||
|
/* system() function without signal handling, from Stevens */
|
||||||
|
|
||||||
|
if ((pid = fork()) < 0) {
|
||||||
|
return 1;
|
||||||
|
} else if (pid == 0) {
|
||||||
|
/* child */
|
||||||
|
execl("/sbin/insmod", "insmod", modname, NULL);
|
||||||
|
_exit(127); /* execl error */
|
||||||
|
} else {
|
||||||
|
/* parent */
|
||||||
|
while (waitpid(pid, &status, 0) < 0) {
|
||||||
|
if (errno != EINTR) {
|
||||||
|
status = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether user is allowed to mount on the specified mount point */
|
||||||
|
static int
|
||||||
|
mount_ok(struct stat *st)
|
||||||
|
{
|
||||||
|
if (!S_ISDIR(st->st_mode))
|
||||||
|
{
|
||||||
|
errno = ENOTDIR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (getuid() != 0)
|
||||||
|
&& ( (getuid() != st->st_uid)
|
||||||
|
|| ((st->st_mode & S_IRWXU) != S_IRWXU)))
|
||||||
|
{
|
||||||
|
errno = EPERM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct ncp_mount_data data;
|
||||||
|
struct sockaddr_ipx addr;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
int Got_Password;
|
||||||
|
int Upcase_Password;
|
||||||
|
int um;
|
||||||
|
unsigned int flags;
|
||||||
|
char hostname[MAXHOSTNAMELEN + 1];
|
||||||
|
|
||||||
|
char *server_name;
|
||||||
|
char *mount_point;
|
||||||
|
|
||||||
|
struct mntent ment;
|
||||||
|
FILE *mtab;
|
||||||
|
|
||||||
|
int ncp_sock, wdog_sock;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
if (geteuid() != 0) {
|
if (geteuid() != 0) {
|
||||||
fprintf(stderr, "%s must be installed suid root\n", progname);
|
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||||
@@ -247,22 +474,43 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
memset(&data, 0, sizeof(struct ncp_mount_data));
|
memset(&data, 0, sizeof(struct ncp_mount_data));
|
||||||
|
|
||||||
if (argc != 5) {
|
memset(hostname, '\0', MAXHOSTNAMELEN+1);
|
||||||
fprintf(stderr, "usage: %s server mount-point"
|
gethostname(hostname, MAXHOSTNAMELEN);
|
||||||
" user password\n", progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
server_name = argv[1];
|
if (argc < 3) {
|
||||||
mount_point = argv[2];
|
if ( (argc == 2)
|
||||||
|
&& (argv[1][0] == '-')
|
||||||
|
&& (argv[1][1] == 'h')
|
||||||
|
&& (argv[1][2] == '\0')) {
|
||||||
|
|
||||||
if (stat(mount_point, &st) == -1) {
|
help();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server_name = argv[1];
|
||||||
|
mount_point = argv[2];
|
||||||
|
|
||||||
|
argv += 2;
|
||||||
|
argc -= 2;
|
||||||
|
|
||||||
|
if (stat(mount_point, &st) == -1) {
|
||||||
fprintf(stderr, "could not find mount point %s: %s\n",
|
fprintf(stderr, "could not find mount point %s: %s\n",
|
||||||
mount_point, strerror(errno));
|
mount_point, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mount_ok(&st) != 0) {
|
||||||
|
fprintf(stderr, "cannot to mount on %s: %s\n",
|
||||||
|
mount_point, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||||
if (ncp_sock == -1) {
|
if (ncp_sock == -1) {
|
||||||
fprintf(stderr, "could not open ncp socket: %s\n",
|
fprintf(stderr, "could not open ncp socket: %s\n",
|
||||||
@@ -297,10 +545,13 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("server: ");
|
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
||||||
ipx_fprint_saddr(stdout, &addr);
|
* to load the ncpfs module */
|
||||||
printf("\n");
|
if (load_ncpfs() != 0) {
|
||||||
|
fprintf(stderr, "Error: Unable to start ncpfs, exiting...\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
data.version = NCP_MOUNT_VERSION;
|
data.version = NCP_MOUNT_VERSION;
|
||||||
data.ncp_fd = ncp_sock;
|
data.ncp_fd = ncp_sock;
|
||||||
data.wdog_fd = wdog_sock;
|
data.wdog_fd = wdog_sock;
|
||||||
@@ -309,24 +560,111 @@ main(int argc, char **argv)
|
|||||||
strcpy(data.server_name, server_name);
|
strcpy(data.server_name, server_name);
|
||||||
data.time_out = 20; /* 2 seconds */
|
data.time_out = 20; /* 2 seconds */
|
||||||
data.retry_count = 2;
|
data.retry_count = 2;
|
||||||
data.uid = 501; /* me */
|
|
||||||
data.gid = 100; /* users */
|
/* getuid() gives us the real uid, who may umount the fs */
|
||||||
data.file_mode = data.dir_mode = S_IRWXU|S_IRWXG|S_IRWXO;
|
data.mounted_uid = getuid();
|
||||||
strcpy(data.username, argv[3]);
|
|
||||||
strcpy(data.password, argv[4]);
|
if (getenv("USER")) {
|
||||||
|
strcpy(data.username, getenv("USER"));
|
||||||
|
str_upper(data.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.username[0] == 0 && getenv("LOGNAME"))
|
||||||
|
{
|
||||||
|
strcpy(data.username,getenv("LOGNAME"));
|
||||||
|
str_upper(data.username);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.uid = getuid();
|
||||||
|
data.gid = getgid();
|
||||||
|
um = umask(0);
|
||||||
|
umask(um);
|
||||||
|
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
||||||
|
data.dir_mode = 0;
|
||||||
|
|
||||||
|
if (parse_args(argc, argv, &data, &Got_Password,
|
||||||
|
&Upcase_Password) != 0) {
|
||||||
|
usage();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.dir_mode == 0) {
|
||||||
|
data.dir_mode = data.file_mode;
|
||||||
|
if ((data.dir_mode & S_IRUSR) != 0)
|
||||||
|
data.dir_mode |= S_IXUSR;
|
||||||
|
if ((data.dir_mode & S_IRGRP) != 0)
|
||||||
|
data.dir_mode |= S_IXGRP;
|
||||||
|
if ((data.dir_mode & S_IROTH) != 0)
|
||||||
|
data.dir_mode |= S_IXOTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Got_Password == 0) {
|
||||||
|
strcpy(data.password, getpass("Password: "));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Upcase_Password == 1) {
|
||||||
|
str_upper(data.password);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.server_name[0] == '\0') {
|
||||||
|
strcpy(data.server_name, server_name);
|
||||||
|
str_upper(data.server_name);
|
||||||
|
}
|
||||||
|
|
||||||
flags = MS_MGC_VAL;
|
flags = MS_MGC_VAL;
|
||||||
|
|
||||||
if (mount(NULL, mount_point, "ncpfs", flags, (char *)&data) < 0) {
|
if (mount(NULL, mount_point, "ncpfs",
|
||||||
|
flags, (char *)&data) < 0) {
|
||||||
perror("mount error");
|
perror("mount error");
|
||||||
fprintf(stderr, "Maybe you should try your password in "
|
close(wdog_sock);
|
||||||
"upper case\n");
|
close(ncp_sock);
|
||||||
|
printf("Maybe you should try to type the username and\n"
|
||||||
|
"password in UPPERCASE.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(ncp_sock);
|
close(ncp_sock);
|
||||||
close(wdog_sock);
|
close(wdog_sock);
|
||||||
|
|
||||||
return 0;
|
ment.mnt_fsname = server_name;
|
||||||
}
|
ment.mnt_dir = fullpath(mount_point);
|
||||||
|
ment.mnt_type = "ncpfs";
|
||||||
|
ment.mnt_opts = "rw";
|
||||||
|
ment.mnt_freq = 0;
|
||||||
|
ment.mnt_passno= 0;
|
||||||
|
|
||||||
|
mount_point = ment.mnt_dir;
|
||||||
|
|
||||||
|
if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't get "MOUNTED"~ lock file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't open " MOUNTED);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addmntent(mtab, &ment) == 1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't write mount entry");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fchmod(fileno(mtab), 0644) == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't set perms on "MOUNTED);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
endmntent(mtab);
|
||||||
|
|
||||||
|
if (unlink(MOUNTED"~") == -1)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Can't remove "MOUNTED"~");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
173
ncptest.c
Normal file
173
ncptest.c
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* ncpmount.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||||
|
extern pid_t waitpid(pid_t, int *, int);
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/ncp.h>
|
||||||
|
#include <linux/ncp_fs.h>
|
||||||
|
#include <linux/ncp_mount.h>
|
||||||
|
#include "ncplib.h"
|
||||||
|
#include "ipxutil.h"
|
||||||
|
|
||||||
|
static char *progname;
|
||||||
|
static char *mount_point;
|
||||||
|
|
||||||
|
void
|
||||||
|
test_filesearch(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
struct ncp_filesearch_info fsinfo;
|
||||||
|
struct ncp_file_info finfo;
|
||||||
|
|
||||||
|
if (ncp_file_search_init(server, 0, "sys:\\public", &fsinfo) != 0) {
|
||||||
|
printf("could not fs init\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ncp_file_search_continue(server, &fsinfo,
|
||||||
|
0,
|
||||||
|
"*", &finfo) == 0) {
|
||||||
|
printf("name: %s\n", finfo.file_name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_getfinfo(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
struct ncp_file_info finfo;
|
||||||
|
|
||||||
|
ncp_get_finfo(server, 0, "sys:", "public", &finfo);
|
||||||
|
ncp_get_finfo(server, 0, "sys:login", "login.exe", &finfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testopen(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
struct ncp_file_info finfo;
|
||||||
|
char buf[1025];
|
||||||
|
int bytes_read;
|
||||||
|
|
||||||
|
ncp_open_file(server, 0, "sys:\\etc\\samples\\protocol", 0,
|
||||||
|
AR_READ|AR_WRITE,
|
||||||
|
&finfo);
|
||||||
|
if (ncp_read(server, finfo.file_id, 0, 1024, buf, &bytes_read) == 0) {
|
||||||
|
printf("bytes: %d\n", bytes_read);
|
||||||
|
buf[bytes_read]=0;
|
||||||
|
puts(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_close_file(server, finfo.file_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testcreate(struct ncp_server *server)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ncp_rename_file(server, 0, "sys:\\me\\blub.txt", 0,
|
||||||
|
0, "sys:\\me\\blub1.txt") != 0) {
|
||||||
|
printf("create war nix\n");
|
||||||
|
}
|
||||||
|
if (ncp_create_directory(server, 0, "sys:\\me\\blubdir", 0xff) != 0) {
|
||||||
|
printf("mkdir war nix\n");
|
||||||
|
}
|
||||||
|
if (ncp_rename_directory(server, 0, "sys:\\me\\blubdir",
|
||||||
|
"\\me\\blubneu") != 0) {
|
||||||
|
printf("mvdir war nix\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ncp_delete_directory(server, 0, "sys:\\me\\blubneu") != 0) {
|
||||||
|
printf("rmdir war nix\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct ncp_mount_data data;
|
||||||
|
struct stat st;
|
||||||
|
struct ncp_server serv;
|
||||||
|
struct ncp_server *server = &serv;
|
||||||
|
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&data, 0, sizeof(struct ncp_mount_data));
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
mount_point = argv[1];
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "usage: %s mount-point\n", progname);
|
||||||
|
printf("defaulting to %s mnt\n", progname);
|
||||||
|
mount_point = "mnt";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (stat(mount_point, &st) == -1) {
|
||||||
|
fprintf(stderr, "could not find mount point %s: %s\n",
|
||||||
|
mount_point, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
server->mount_fid = open(mount_point, O_RDONLY, 0);
|
||||||
|
|
||||||
|
if (server->mount_fid == -1) {
|
||||||
|
fprintf(stderr, "Could not open %s: %s\n",
|
||||||
|
mount_point, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
for (i=0; i<5; i++) {
|
||||||
|
struct ncp_volume_info info;
|
||||||
|
ncp_get_volume_info_with_number(server, i, &info);
|
||||||
|
printf("vol %d: %s\n", i, info.volume_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_filesearch(server);
|
||||||
|
test_getfinfo(server);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
testcreate(server);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
75
nwcrypt.c
75
nwcrypt.c
@@ -1,9 +1,7 @@
|
|||||||
/*$*********************************************************
|
/*$*********************************************************
|
||||||
$*
|
$*
|
||||||
$* This code has been taken from DDJ 11/93, from an
|
$* This code has been taken from DDJ 11/93, from an
|
||||||
$* article by Pawel Szczerbina. Please read the file
|
$* article by Pawel Szczerbina.
|
||||||
$* README for my questions about the legal status of
|
|
||||||
$* this code.
|
|
||||||
$*
|
$*
|
||||||
$* Password encryption routines follow.
|
$* Password encryption routines follow.
|
||||||
$* Converted to C from Barry Nance's Pascal
|
$* Converted to C from Barry Nance's Pascal
|
||||||
@@ -15,6 +13,77 @@ $* October 1995.
|
|||||||
$*
|
$*
|
||||||
$**********************************************************/
|
$**********************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
|
||||||
|
I read that Novell is not very open when it comes to technical details
|
||||||
|
of the Netware Core Protocol. This might be especially true for the
|
||||||
|
encryption stuff. I took the necessary code from Dr. Dobb's Journal
|
||||||
|
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
|
||||||
|
the legal status of this piece of code:
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
Date: Thu, 12 Oct 1995 13:44:18 +0100
|
||||||
|
From: Volker Lendecke <lendecke>
|
||||||
|
To: jon@ddj.com
|
||||||
|
Subject: legal status of your source code?
|
||||||
|
|
||||||
|
|
||||||
|
Hello!
|
||||||
|
|
||||||
|
I hope that you're the right one to write to, you are the first on your WWW
|
||||||
|
server. If you are not, could you please forward this message to the right
|
||||||
|
person? Thanks.
|
||||||
|
|
||||||
|
I'm currently exploring the possibility to write a free (in the GNU GPL
|
||||||
|
sense) NCP filesystem, which would allow me to access a novell server
|
||||||
|
transparently. For that I would like to use the encryption functions you
|
||||||
|
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
|
||||||
|
changes, such as other indentations, minor code changes and so on. But I do
|
||||||
|
not know if that allows me to publish this code under GPL. One alternative
|
||||||
|
would be to publish a diff against your listing, but that would probably
|
||||||
|
contain much of your code as well, and it would be very inconvenient for
|
||||||
|
the average user.
|
||||||
|
|
||||||
|
I think that you have some kind of standard procedure for such a
|
||||||
|
case. Please tell me what I should do.
|
||||||
|
|
||||||
|
Many thanks in advance,
|
||||||
|
|
||||||
|
Volker
|
||||||
|
|
||||||
|
+=================================================================+
|
||||||
|
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
|
||||||
|
! D-37081 Goettingen, Germany !
|
||||||
|
+=================================================================+
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
I got the following answer:
|
||||||
|
|
||||||
|
---
|
||||||
|
From: Jon Erickson <jon@ddj.com>
|
||||||
|
X-Mailer: SCO System V Mail (version 3.2)
|
||||||
|
To: lendecke@namu01.gwdg.de
|
||||||
|
Subject: Re: legal status of your source code?
|
||||||
|
Date: Thu, 12 Oct 95 5:42:56 PDT
|
||||||
|
|
||||||
|
Volker,
|
||||||
|
Code from Dr. Dobb's Journal related articles is provided for
|
||||||
|
anyone to use. Clearly, the author of the article should be
|
||||||
|
given credit.
|
||||||
|
Jon Erickson
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
With this answer in mind, I took the code and made it a bit more
|
||||||
|
C-like. The original seemed to be translated by a mechanical pascal->c
|
||||||
|
translator. Jon's answer encouraged me to publish nwcrypt.c under the
|
||||||
|
GPL. If anybody who knows more about copyright and sees any problems
|
||||||
|
with this, please tell me.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/******************* Data types ***************************/
|
/******************* Data types ***************************/
|
||||||
typedef unsigned char buf32[32];
|
typedef unsigned char buf32[32];
|
||||||
typedef unsigned char buf16[16];
|
typedef unsigned char buf16[16];
|
||||||
|
|||||||
2
sock.c
2
sock.c
@@ -84,7 +84,7 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
|||||||
sendto(sock, (void *)packet_buf, 2, 1, 0,
|
sendto(sock, (void *)packet_buf, 2, 1, 0,
|
||||||
(struct sockaddr *)&sender,
|
(struct sockaddr *)&sender,
|
||||||
sizeof(sender));
|
sizeof(sender));
|
||||||
printk("send result: %d\n", result);
|
DPRINTK("send result: %d\n", result);
|
||||||
}
|
}
|
||||||
set_fs(fs);
|
set_fs(fs);
|
||||||
}
|
}
|
||||||
|
|||||||
7
start_ipx
Executable file
7
start_ipx
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# abcd is my ipx network number and 1234 my server's internal network number.
|
||||||
|
# 00001b038b11 is the server's node number.
|
||||||
|
#
|
||||||
|
ipx_interface add -p eth0 EtherII abcd
|
||||||
|
ipx_route add 1234 abcd 00001b038b11
|
||||||
Reference in New Issue
Block a user