Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7179281575 | ||
|
|
b8d830f9a3 | ||
|
|
b36a27bedb | ||
|
|
7d0e3d011b | ||
|
|
84cb1f167d | ||
|
|
64f006632a | ||
|
|
92f749a943 | ||
|
|
6cb56005ea | ||
|
|
0520c1d2f7 | ||
|
|
d5ac4601b1 | ||
|
|
1fa124bd7c | ||
|
|
5753870858 | ||
|
|
b8ce93c8bd | ||
|
|
7bef99df0f | ||
|
|
d31ec2ab61 | ||
|
|
1ee60bade6 | ||
|
|
20589ca203 | ||
|
|
517e207709 | ||
|
|
5d4b23a5c1 |
BIN
.downloads/ncpfs-0.10.tgz
Normal file
BIN
.downloads/ncpfs-0.10.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.11.tgz
Normal file
BIN
.downloads/ncpfs-0.11.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.12.tgz
Normal file
BIN
.downloads/ncpfs-0.12.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.13.tgz
Normal file
BIN
.downloads/ncpfs-0.13.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.14.tgz
Normal file
BIN
.downloads/ncpfs-0.14.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.15.tgz
Normal file
BIN
.downloads/ncpfs-0.15.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.16.tgz
Normal file
BIN
.downloads/ncpfs-0.16.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.17.tgz
Normal file
BIN
.downloads/ncpfs-0.17.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.18.tgz
Normal file
BIN
.downloads/ncpfs-0.18.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.19.tgz
Normal file
BIN
.downloads/ncpfs-0.19.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.20.tgz
Normal file
BIN
.downloads/ncpfs-0.20.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.21.tgz
Normal file
BIN
.downloads/ncpfs-0.21.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.22.tgz
Normal file
BIN
.downloads/ncpfs-0.22.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.23.tgz
Normal file
BIN
.downloads/ncpfs-0.23.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.24.tgz
Normal file
BIN
.downloads/ncpfs-0.24.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.9.tgz
Normal file
BIN
.downloads/ncpfs-0.9.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.0.tgz
Normal file
BIN
.downloads/ncpfs-2.0.0.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.1.tgz
Normal file
BIN
.downloads/ncpfs-2.0.1.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-2.0.2.tgz
Normal file
BIN
.downloads/ncpfs-2.0.2.tgz
Normal file
Binary file not shown.
21
BUGS
21
BUGS
@@ -3,17 +3,20 @@ them to be bugs.
|
||||
|
||||
But there are really problems that might be fixed in the future.
|
||||
|
||||
'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.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
'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
|
||||
mars_nwe and lwared that might change ...), I rejected the alternative
|
||||
to mount only a single volume for a unix mount point. So I simply
|
||||
return 0.
|
||||
|
||||
In your kernel log, there will appear messages like
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
If you use Linux 1.2.x, In your kernel log there will appear messages
|
||||
like
|
||||
|
||||
Nov 25 16:09:08 lx01 kernel: alloc_skb called nonatomically from interrupt 0000002e
|
||||
|
||||
These are a bit annoying, but completely harmless. Maybe this will be
|
||||
fixed in the future.
|
||||
These are a bit annoying, but completely harmless.
|
||||
|
||||
136
Changes
Normal file
136
Changes
Normal file
@@ -0,0 +1,136 @@
|
||||
I only began this file with ncpfs-0.12. If you're interested in older
|
||||
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
|
||||
|
||||
ncpfs-2.0.1 -> ncpfs-2.0.2
|
||||
- Added some values to ipxparse.
|
||||
- Added a patch against 2.0.7 for long file names support. I did not
|
||||
apply this change to the 1.2-module. Please upgrade to 2.0.7 if you
|
||||
want to use long file names.
|
||||
- nwbpvalues can print ITEM properties
|
||||
|
||||
ncpfs-2.0.0 -> ncpfs-2.0.1
|
||||
- Added some values to ipxparse.
|
||||
- Added the little bindery utilities. Maybe someone has the time to
|
||||
write a shellscript named 'nwadduser' ?
|
||||
- Fixed a bug that made the __255 message reappear. Many thanks to
|
||||
Guntram Blom for his detailed bug report.
|
||||
- Fixed a bug that made ncpfs incompatible with W95's server
|
||||
capabilities. Thanks to Tomasz Babczynski
|
||||
<faster@dino.ict.pwr.wroc.pl> for this one.
|
||||
|
||||
ncpfs-0.24 -> ncpfs-2.0.0
|
||||
- Changed the numbering scheme :-).
|
||||
- Added npasswd. Many thanks to Guntram Blom for his work!
|
||||
- Hopefully improved error messages a bit
|
||||
- Hopefully made slist a bit more robust
|
||||
|
||||
ncpfs-0.23 -> ncpfs-0.24
|
||||
- Fixed a bug that made it impossible to umount a filesystem after you
|
||||
tried 'mkdir .' or 'mkdir ..'.
|
||||
- Fixed a bad race condition when opening files.
|
||||
- Made the default timeout values more robust.
|
||||
|
||||
ncpfs-0.22 -> ncpfs-0.23
|
||||
- Fixed a memory allocation problem in nwmsg.c. Thanks to
|
||||
Andrew Ross <anr1001@hermes.cam.ac.uk>
|
||||
- slist hopefully does not ask for a password anymore.
|
||||
- cleaned up error messages a bit.
|
||||
- ncpmount now calls modprobe instead of insmod.
|
||||
|
||||
ncpfs-0.21 -> ncpfs-0.22
|
||||
- removed a bad race condition in kernel-1.2/src/dir.c.
|
||||
- handle 0x9999-responses from the ncp server correctly.
|
||||
- Bindery functions in ncplib.c by Brian G. Reid (breid@tim.com)
|
||||
- set blocksize to 512 to satisfy 'du -k'
|
||||
|
||||
ncpfs-0.20 -> ncpfs-0.21
|
||||
- Included two bugfixes in ncplib.c found by Jeff Buhrt
|
||||
<buhrt@iquest.net>.
|
||||
- Included a bugfix in kernel code that could only show for servers
|
||||
that do not support namespace calls. I should have tried ncpfs
|
||||
against lwared... Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for
|
||||
this fix.
|
||||
|
||||
ncpfs-0.19 -> ncpfs-0.20
|
||||
- Changed the home site for ncpfs from linux01.gwdg.de:/pub/ncpfs
|
||||
to ftp.gwdg.de:/pub/linux/misc/ncpfs. linux01 will remain available,
|
||||
but we would like to reduce the load on that machine. Sites
|
||||
mirroring linux01 please redirect your mirror software to
|
||||
ftp.gwdg.de. Thanks.
|
||||
- Removed a bug in ncplib.c that made slist require a full
|
||||
login. Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for the hint.
|
||||
- The first real user contribution: ncopy by Brian G. Reid
|
||||
(breid@tim.com) and Tom C. Henderson (thenderson@tim.com). Many
|
||||
thanks to you! If you find bugs in ncopy, tell them, not me ;-)
|
||||
- Handle expired passwords. Thanks to "Mathew Lim" <M.Lim@sp.ac.sg>
|
||||
for the hint.
|
||||
|
||||
ncpfs-0.18 -> ncpfs-0.19
|
||||
|
||||
- hacked around in ncplib.[ch] quite heavily.
|
||||
- SAP handling in ipxparse.c. Thanks to Jeff Buhrt <buhrt@iquest.net>
|
||||
- Changed error handling to use the com_err library. This should
|
||||
eventually provide better error messages, because it's now much
|
||||
easier to define nice messages.
|
||||
- If no server is active, report this correctly
|
||||
- added nsend
|
||||
|
||||
ncpfs-0.17 -> ncpfs-0.18
|
||||
|
||||
- Another attempt at solving the problem that -n is not working.
|
||||
- Forgot nprint in 0.17 util/Makefile.
|
||||
- nprint left connections open when it fails
|
||||
- added options -r and -t to ncpmount to tune ncpfs connections.
|
||||
|
||||
ncpfs-0.16 -> ncpfs-0.17
|
||||
|
||||
- Changed the name of fsinfo to nwfsinfo, to avoid a name clash with
|
||||
the X windows utility. Thanks to Henning Brockfeld
|
||||
<Henning.Brockfeld@lrz.uni-muenchen.de> for this hint. (still
|
||||
waiting for your scripts.. :-))
|
||||
- made nwmsg available. This enables you to receive NetWare user
|
||||
broadcast messages. Please note that you need at least kernel 1.3.68
|
||||
for this feature.
|
||||
- pserver now prints debugging output via syslog().
|
||||
- Included ipxdump, a nice little utility, that has helped some
|
||||
people.
|
||||
|
||||
- And now the big one: you can re-export ncpfs-mounted directories
|
||||
with nfsd! You have to mount single volumes by specifying -V volume
|
||||
to ncpmount, and call nfsd and mountd with the option --re-export.
|
||||
See the manual page of ncpmount for more information. Please note
|
||||
that I will send Linus the required patch on 1. March 1996, so you
|
||||
will have to use kernel 1.2.13 or wait at least for 1.3.70.
|
||||
|
||||
ncpfs-0.15 -> ncpfs-0.16
|
||||
|
||||
- Included ipx-1.0, made available by Greg Page <greg@caldera.com>,
|
||||
Caldera
|
||||
- Made -n work for password-less accounts. Thanks to Alexander Jolk
|
||||
<jolk@ap-pc513b.physik.uni-karlsruhe.de>.
|
||||
- Fixed the kerneld support.
|
||||
- Fixed the NetWare 4.1 problem. Many thanks to
|
||||
Chatchai JANTARAPRIM <chat@ratree.psu.ac.th> and
|
||||
hitesh.soneji@industry.net for their patience.
|
||||
|
||||
ncpfs-0.14 -> ncpfs-0.15
|
||||
|
||||
- A bug fixed that made normal mounting impossible. It was too late
|
||||
yesterday. Sorry
|
||||
- Manpage for pserver.c
|
||||
|
||||
ncpfs-0.13 -> ncpfs-0.14
|
||||
|
||||
- Improvements of manual pages by B. Galliart <bgallia@luc.edu> and
|
||||
Terry Dawson <terry@perf.no.itg.telecom.com.au>
|
||||
- fsinfo
|
||||
- pserver.c. Please see this as ALPHA software. There is no
|
||||
documentation, and it is not tested enough. But it might be useful for
|
||||
you.
|
||||
|
||||
ncpfs-0.12 -> ncpfs-0.13
|
||||
|
||||
- support for automatic loading of ncpfs.o by kerneld.
|
||||
Thanks to Steven N. Hirsch <hirsch@emba.uvm.edu>.
|
||||
- A subtle problem in the read routines has been removed by Uwe Bonnes
|
||||
<bon@elektron.ikp.physik.th-darmstadt.de>. Thanks a lot.
|
||||
74
FAQ
Normal file
74
FAQ
Normal file
@@ -0,0 +1,74 @@
|
||||
There is certainly not enough material to call this an FAQ, but some
|
||||
questions reach me regularly. Probably the documenation is not clear
|
||||
enough.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: The ncpfs utilities like slist or ncpmount tell me that they can
|
||||
not find a server, although I'm sure there are servers on my
|
||||
net. What's wrong?
|
||||
|
||||
You probably used
|
||||
|
||||
ipx_configure --auto_interface=on --auto_primary=on
|
||||
|
||||
and you have Windows (95?) workstations on your network. Windows 95
|
||||
makes Linux configure IPX interfaces for non-existent frame types. To
|
||||
solve this problem, you have to configure your IPX interface manually
|
||||
with the command
|
||||
|
||||
ipx_interface add -p <device> <frame>
|
||||
|
||||
For <device> use eth0, eth1 or whatever you network adapter is
|
||||
called. The value for <frame> must match the frame type used on your
|
||||
network. Possible values are 802.2, 802.3, SNAP and EtherII.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: I have difficulties with NetWare 4.1. What can I do?
|
||||
|
||||
To be honest, I do not really know. Currently my only test equipment
|
||||
is a NetWare 3.11 server. You should make your 4.1 Server as
|
||||
3.x-compatible as it can be. As I do not know 4.1, you are on your own
|
||||
doing this.
|
||||
|
||||
A promising hint that has already helped some people is to switch off
|
||||
packet signatures on the 4.1 server, as ncpfs does not support them.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: Does ncpfs support long file names, using the OS/2 namespace?
|
||||
|
||||
Yes. But you will have to patch your kernel. Look at the file
|
||||
kernel-2.0/README for more information.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: When I re-export ncpfs-mounted directories via nfs, I get messages like
|
||||
'pwd: cannot get current directory', and other strange things happen to
|
||||
the nfs clients. What's wrong?
|
||||
|
||||
When you want to export a directory via NFS, you have to do two things:
|
||||
|
||||
- You have to invoke mountd and nfsd with the option --re-export. On my
|
||||
computer, both are invoked at system startup from the file
|
||||
/etc/rc.d/rc.inet2.
|
||||
|
||||
- You can not export a complete NetWare server hierarchy with all volumes
|
||||
under a single mount point. You have to mount a single server volume to
|
||||
make it re-exportable. Invoke ncpmount with the option -V volume to do
|
||||
this.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: When I compile ncpfs, I get a message like the following:
|
||||
|
||||
make[1]: Entering directory `/home/me/netware/ncpfs/kernel-1.2/src'
|
||||
gcc -D__KERNEL__ -I. -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer -I/home/me/netware/ncpfs/kernel-1.2 -DNCPFS_VERSION=\"0.17\" -c dir.c
|
||||
dir.c:36: warning: `struct dirent' declared inside parameter list
|
||||
dir.c:36: warning: its scope is only this definition or declaration,
|
||||
...
|
||||
|
||||
You try to compile the part of ncpfs that is meant for kernel 1.2.13 under
|
||||
kernel 1.3.x. Please look at the Makefile and comment out the
|
||||
corresponding lines.
|
||||
56
Makefile
56
Makefile
@@ -2,37 +2,47 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
KERNEL = 1.2
|
||||
VERSION = 2.0.2
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -Ikernel
|
||||
BINDIR = ./bin
|
||||
# If you are using kerneld to autoload ncp support,
|
||||
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||
#KERNELD = -DHAVE_KERNELD
|
||||
|
||||
CFLAGS = -Wall $(INCLUDES)
|
||||
CC = gcc
|
||||
TOPDIR = $(shell pwd)
|
||||
BINDIR = /usr/local/bin
|
||||
SBINDIR = /sbin
|
||||
INTERM_BINDIR = $(TOPDIR)/bin
|
||||
SUBDIRS = util ipx-1.0 man
|
||||
|
||||
all: kernel
|
||||
make -C util
|
||||
make -C kernel/src ncpfs.o
|
||||
cp kernel/src/ncpfs.o bin
|
||||
KVERSION=$(shell uname -r | cut -b1-3)
|
||||
|
||||
kernel:
|
||||
rm -f kernel
|
||||
ln -s kernel-$(KERNEL) kernel
|
||||
ifeq ($(KVERSION),1.2)
|
||||
SUBDIRS += kernel-1.2/src
|
||||
INCLUDES = -I$(TOPDIR)/kernel-1.2
|
||||
endif
|
||||
|
||||
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
|
||||
|
||||
all:
|
||||
for i in $(SUBDIRS); do make -C $$i all; done
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
for i in $(SUBDIRS); do make -C $$i dep; done
|
||||
|
||||
install:
|
||||
for i in $(SUBDIRS); do make -C $$i install; done
|
||||
|
||||
clean:
|
||||
rm -f kernel
|
||||
rm -f `find . -type f -name '*.o' -print`
|
||||
rm -f `find . -type f -name '*~' -print`
|
||||
rm -f `find . -type f -name '.depend' -print`
|
||||
rm -f `find . -type f -name '*.out' -print`
|
||||
for i in $(SUBDIRS); do make -C $$i clean; done
|
||||
|
||||
|
||||
realclean: clean
|
||||
rm -fr bin/* ncpfs.tgz
|
||||
make -C util realclean
|
||||
mrproper: clean
|
||||
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
||||
make -C util mrproper
|
||||
make -C ipxdump mrproper
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
@@ -40,7 +50,15 @@ SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
|
||||
dist: realclean
|
||||
dist: mrproper
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
mv $(DISTFILE) $(SRCDIR))
|
||||
make dep
|
||||
make all
|
||||
|
||||
tgz: mrproper
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
|
||||
118
README
118
README
@@ -1,21 +1,64 @@
|
||||
This is version 0.7 of ncpfs, a free NetWare client filesystem for
|
||||
Linux. This one currently works with Kernel 1.2.13. I do not know
|
||||
whether it works with any other kernel of the 1.2.x series, I only
|
||||
used it with 1.2.13.
|
||||
This is ncpfs, a free NetWare client filesystem for Linux. Besides
|
||||
some little utilities it also contains nprint, which enables you to
|
||||
print on NetWare print queues. The opposite side, pserver, is also
|
||||
provided.
|
||||
|
||||
Due to problems in the 1.3.x IPX kernel code, ncpfs-0.7 does NOT work
|
||||
with any 1.3.x kernel up to 1.3.44, although there is a kernel-1.3
|
||||
subdirectory. It compiles fine and seems to work, but any connection
|
||||
will block after a very short time. Please be patient. I'm sure this
|
||||
will be solved. If you follow the kernel development closely, you
|
||||
might want to try ncpfs with a kernel later than 1.3.44, but I can not
|
||||
promise anything. To try it with 1.3, simply change the variable
|
||||
KERNEL in the Makefile from 1.2 to 1.3 and continue as usual.
|
||||
I'm planning major changes in the structure of ncpfs for Linux 2.1.x
|
||||
which will break the binary compatibility. So I changed the numbering
|
||||
scheme for ncpfs. ncpfs-2.0.x will be the version to be used with
|
||||
Linux 2.0.0 and older kernels, and ncpfs-2.1.x will be the version for
|
||||
the development kernels.
|
||||
|
||||
To install ncpfs, just type 'make'. After that, you find the
|
||||
neccessary kernel module and the mounting tools in ./bin. Type 'insmod
|
||||
ncpfs.o' and then 'ncpmount server mount-point'. For further
|
||||
information, please look at the manual pages in ./man.
|
||||
INSTALLATION
|
||||
|
||||
Before you start the installation, make sure that your kernel has IPX
|
||||
support compiled in. When 'make config' asks you for
|
||||
|
||||
The IPX protocol (CONFIG_IPX) [N/y/m/?]
|
||||
|
||||
simply answer 'y'. Probably you do not need the full internal net that
|
||||
you are asked for next.
|
||||
|
||||
The installation of ncpfs depends on the kernel version you are
|
||||
using. For kernel 1.2, you should simply type 'make' and look at
|
||||
what's in the bin/ directory after that. Please be sure that your
|
||||
kernel resides in /usr/src/linux, because the file
|
||||
kernel-1.2/src/sock.c has to refer directly to it.
|
||||
|
||||
If you use Kernel 1.3, please be sure that you use at least
|
||||
1.3.71. ncpfs does NOT work with any earlier 1.3.x kernel.
|
||||
|
||||
If you use Kernel 1.3.71 or later, you might have to recompile your
|
||||
kernel. With these kernels, the kernel part of ncpfs is already
|
||||
included in the main source tree. If you want to use ncpfs, you should
|
||||
say 'y' to 'make config' when you are asked for IPX, and again when it
|
||||
asks for ncpfs. After you have rebooted with the new kernel, 'cat
|
||||
/proc/filesystems' should show you a line saying that the kernel knows
|
||||
ncpfs.
|
||||
|
||||
If you are running kerneld, please uncomment the corresponding line in
|
||||
the Makefile to reflect this.
|
||||
|
||||
HELP
|
||||
|
||||
In the meantime my mail volume has grown considerably, so the response
|
||||
time might be better at the LinWare mailing list than at my personal
|
||||
email address. You can mail to and/or subscribe to the LinWare mailing
|
||||
list:
|
||||
|
||||
Topics for the list:
|
||||
- discussing LinWare server, its features, installation problems and bugs
|
||||
- using IPX protocol under Linux
|
||||
- IPX routing and router daemons under Linux
|
||||
- mars_nwe
|
||||
- ncpfs
|
||||
|
||||
You can subscribe to the list by sending the command "add linware" in
|
||||
the mail message body to address: "listserv@sh.cvut.cz". Your
|
||||
postings should be sent to: "linware@sh.cvut.cz".
|
||||
|
||||
|
||||
USING NCPFS
|
||||
|
||||
Please note that your IPX system has to be configured correctly. If
|
||||
you want to take the 'Plug-and-Play' route, you can simply say
|
||||
@@ -29,8 +72,8 @@ hand, note that there has to be a route to the internal network of
|
||||
your server. Please see the file util/start_ipx for an example.
|
||||
|
||||
I use tools written by Greg Page, Caldera. I hope I did not do too
|
||||
much harm to their business. For your convenience I included the file
|
||||
ipx.tar made available by Caldera.
|
||||
much harm to their business. For your convenience I included the
|
||||
contents of the file ipx.tar made available by Caldera.
|
||||
|
||||
My main source of information is a book written in german by Manfred
|
||||
Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH,
|
||||
@@ -40,7 +83,7 @@ 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!
|
||||
|
||||
For the curious: the file ncplib_user.[ch] is a library that makes it
|
||||
For the curious: the files ncplib.[ch] are a library that makes it
|
||||
possible to send NCP requests to the server over a mounted
|
||||
directory. I use it to keep the encryption stuff out of the kernel by
|
||||
logging in from user space. Look at the file ncptest.c for other
|
||||
@@ -50,6 +93,23 @@ free NetWare API for Linux! I would be happy to receive your comments
|
||||
on this.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
I do not want to leave those unmentioned, who have helped me with
|
||||
ncpfs.
|
||||
|
||||
The most enthusiastic user and tester is certainly Uwe Bonnes
|
||||
<bon@elektron.ikp.physik.th-darmstadt.de>. So far he's the only one
|
||||
who has contributed something, namely manpages and corretions to
|
||||
existing manpages.
|
||||
|
||||
Ales Dyrak has written lwared, which was the initial start for ncpfs.
|
||||
|
||||
Alan Cox has found some bugs I would probably never have found.
|
||||
|
||||
Look at the file Changes for others.
|
||||
|
||||
|
||||
LIMITATIONS (compare these with smbfs :-)
|
||||
|
||||
The limitations ncpfs has are the natural limitations of the NCP
|
||||
@@ -58,16 +118,10 @@ 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.
|
||||
You will not be able to access servers that require packet
|
||||
signatures. This seems to be one of Novell's bigger secrets :-(.
|
||||
|
||||
Have fun with ncpfs!
|
||||
|
||||
Volker
|
||||
lendecke@namu01.gwdg.de
|
||||
|
||||
15
TODO
Normal file
15
TODO
Normal file
@@ -0,0 +1,15 @@
|
||||
Here's a list of things I want to do. Feel free to send suggestions,
|
||||
or even help me ;-).
|
||||
|
||||
- Add flags to pserver's command line, so that the print command can
|
||||
find out the name of user who printed the job.
|
||||
|
||||
- do rtt estimation, like tcp does.
|
||||
|
||||
- Do better connection management. I imagine to create a ncpd.
|
||||
|
||||
- When ncp is done, one can think about mounting several volumes over
|
||||
a single NCP connection. This should make the trade-off mentioned in
|
||||
ncpmount.8 unnecessary.
|
||||
|
||||
- Do some kind of mapping of NCP uid's to unix uid's
|
||||
9
ipx-1.0/COPYING
Normal file
9
ipx-1.0/COPYING
Normal file
@@ -0,0 +1,9 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the original work is
|
||||
properly attributed to Greg Page and Caldera, Inc.
|
||||
Neither the name of Greg Page nor Caldera, Inc. may be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
This software is provided by Greg Page and Caldera, Inc. "AS IS"
|
||||
and without any express or implied warranties.
|
||||
|
||||
24
ipx-1.0/Gregs.Makefile
Normal file
24
ipx-1.0/Gregs.Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
CFLAGS = -O2 -Wall
|
||||
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||
all: $(UTILS)
|
||||
|
||||
clean:
|
||||
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||
|
||||
install: $(UTILS)
|
||||
for i in $(UTILS); \
|
||||
do \
|
||||
install --strip $$i /sbin; \
|
||||
install $$i.8 /usr/man/man8; \
|
||||
done
|
||||
install init.ipx /etc/rc.d/init.d/ipx
|
||||
install -m 0644 config.ipx /etc/sysconfig/ipx
|
||||
rm -f /etc/rc.d/rc2.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc2.d/S15ipx
|
||||
rm -f /etc/rc.d/rc3.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc3.d/S15ipx
|
||||
rm -f /etc/rc.d/rc5.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc5.d/S15ipx
|
||||
rm -f /etc/rc.d/rc6.d/K55ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc6.d/K55ipx
|
||||
|
||||
30
ipx-1.0/Makefile
Normal file
30
ipx-1.0/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
CFLAGS = -O2 -Wall
|
||||
UTILS = $(INTERM_BINDIR)/ipx_configure $(INTERM_BINDIR)/ipx_interface \
|
||||
$(INTERM_BINDIR)/ipx_internal_net $(INTERM_BINDIR)/ipx_route
|
||||
|
||||
all: $(UTILS)
|
||||
|
||||
$(INTERM_BINDIR)/ipx_configure: ipx_configure.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_route: ipx_route.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_route ipx_route.o
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||
|
||||
install: $(UTILS)
|
||||
for i in $(UTILS); \
|
||||
do \
|
||||
install $$i $(BINDIR); \
|
||||
done
|
||||
|
||||
65
ipx-1.0/README
Normal file
65
ipx-1.0/README
Normal file
@@ -0,0 +1,65 @@
|
||||
This file contains a very short introduction to the IPX implementation
|
||||
on Linux. Feel free to forward comments (especially suggested additions)
|
||||
to greg@caldera.com.
|
||||
|
||||
The following are important definitions in understanding the descriptions
|
||||
in this README file.
|
||||
|
||||
IPX Interface - This is the item to which IPX sockets are bound.
|
||||
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||
to a physical device and frame type. A sample IPX Interface would be:
|
||||
Network Number: 0x00ABCDEF
|
||||
Device: Eth0
|
||||
Frame Type: 802.2.
|
||||
The particular interface is selected during binding by using the
|
||||
Network Number (see sample code below).
|
||||
|
||||
Primary Interface - The interface that is selected by default when
|
||||
binding a socket. This is selected when binding by using
|
||||
a network number of 0 (see sample code below).
|
||||
|
||||
Internal Network - This is a special kind of IPX interface that does
|
||||
not have a physical device or frame type. It is used to provide
|
||||
a route-independent address for service providers. Internal network
|
||||
numbers are optional; however, when one is present it is also the
|
||||
Primary Interface.
|
||||
|
||||
This tar file contains the following IPX utilities:
|
||||
|
||||
ipx_interface.c
|
||||
This program is used to create an IPX interface.
|
||||
|
||||
ipx_internal_net.c
|
||||
This program is used to create an IPX Internal Network number.
|
||||
|
||||
ipx_route.c
|
||||
This program creates an IPX route.
|
||||
|
||||
ipx_configure.c
|
||||
This program is used to read/write two configuration parameters:
|
||||
AUTO INTERFACE CREATE - IPX should/shouldn't automatically create
|
||||
an IPX interface when it discovers one that has not been
|
||||
registered via ipx_interface above.
|
||||
AUTO PRIMARY SELECT - IPX should/shouldn't automatically select
|
||||
a primary interface when it one an interface exists and
|
||||
none are designated as the primary. Manual designation
|
||||
is performed via ipx_interface.
|
||||
|
||||
By default, these are both turned off.
|
||||
|
||||
The following are sample IPX programs (found in directory Samples):
|
||||
|
||||
ipxrcv.c and ipxsend.c
|
||||
ipxsend will send a single packet to an instance of ipxrcv running on the
|
||||
same machine. It uses getsockname(2) to determine the address to which to
|
||||
send the packet.
|
||||
rip.c
|
||||
rip passively monitors the rip traffic on the attached IPX network.
|
||||
sap.c
|
||||
sap passively monitors the sap traffic on the attached IPX network.
|
||||
|
||||
There are three files in /proc/net that relate to IPX.
|
||||
ipx_interface contains the list of IPX interfaces.
|
||||
ipx_route contains the list of IPX routes.
|
||||
ipx contains the list of IPX sockets in use.
|
||||
|
||||
52
ipx-1.0/Samples/ipxrcv.c
Normal file
52
ipx-1.0/Samples/ipxrcv.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int result;
|
||||
char msg[100];
|
||||
int len;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
sipx.sipx_type = 17;
|
||||
len = sizeof(sipx);
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
msg[0] = '\0';
|
||||
result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||
&len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom: ");
|
||||
}
|
||||
|
||||
printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
htonl(sipx.sipx_network),
|
||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||
sipx.sipx_node[4], sipx.sipx_node[5],
|
||||
htons(sipx.sipx_port));
|
||||
printf("\tGot \"%s\"\n", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
46
ipx-1.0/Samples/ipxsend.c
Normal file
46
ipx-1.0/Samples/ipxsend.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int result;
|
||||
char msg[100] = "Hi Mom";
|
||||
int len = sizeof(sipx);
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = 0;
|
||||
sipx.sipx_type = 17;
|
||||
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = getsockname(s, (struct sockaddr *)&sipx, &len);
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||
sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: send: ");
|
||||
exit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
ipx-1.0/Samples/rip.c
Normal file
68
ipx-1.0/Samples/rip.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct rip_data {
|
||||
unsigned long rip_net;
|
||||
unsigned short rip_hops __attribute__ ((packed));
|
||||
unsigned short rip_ticks __attribute__ ((packed));
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int result;
|
||||
int s;
|
||||
char msg[1024];
|
||||
int len;
|
||||
char *bptr;
|
||||
struct rip_data *rp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x453);
|
||||
sipx.sipx_type = 17;
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
len = sizeof(sipx);
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom");
|
||||
exit(-1);
|
||||
}
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("RIP packet from: %08lX:%02X%02X%02X%02X%02X%02X\n",
|
||||
htonl(sipx.sipx_network),
|
||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||
sipx.sipx_node[6], sipx.sipx_node[5]);
|
||||
bptr += 2;
|
||||
rp = (struct rip_data *) bptr;
|
||||
while (result >= sizeof(struct rip_data)) {
|
||||
printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net),
|
||||
ntohs(rp->rip_hops));
|
||||
result -= sizeof(struct rip_data);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
96
ipx-1.0/Samples/sap.c
Normal file
96
ipx-1.0/Samples/sap.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
struct sap_data {
|
||||
unsigned short sap_type __attribute__ ((packed));
|
||||
char sap_name[48] __attribute__ ((packed));
|
||||
unsigned long sap_net __attribute__ ((packed));
|
||||
unsigned char sap_node[6] __attribute__ ((packed));
|
||||
unsigned short sap_sock __attribute__ ((packed));
|
||||
unsigned short sap_hops __attribute__ ((packed));
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
int result;
|
||||
struct sockaddr_ipx sipx;
|
||||
char msg[1024];
|
||||
long val = 0;
|
||||
int len;
|
||||
char *bptr;
|
||||
struct sap_data *sp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
|
||||
if (result < 0) {
|
||||
perror("IPX: setsockopt: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx.sipx_family = PF_IPX;
|
||||
sipx.sipx_network = 0L;
|
||||
sipx.sipx_port = htons(0x452);
|
||||
sipx.sipx_type = 17;
|
||||
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
len = 1024;
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom: ");
|
||||
exit(-1);
|
||||
}
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("SAP: OP is %x %x\n", bptr[0], bptr[1]);
|
||||
printf("Length is %d\n", result);
|
||||
if (bptr[1] != 2)
|
||||
continue;
|
||||
|
||||
bptr += 2;
|
||||
sp = (struct sap_data *) bptr;
|
||||
while (result >= sizeof(struct sap_data)) {
|
||||
int i;
|
||||
|
||||
sp->sap_name[32] = '\0';
|
||||
for (i = 31; (i > 0) && (sp->sap_name[i] == '_'); i--);
|
||||
i++;
|
||||
sp->sap_name[i] = '\0';
|
||||
printf("NAME: %s TYPE: %x HOPS: %x\n", sp->sap_name,
|
||||
ntohs(sp->sap_type), ntohs(sp->sap_hops));
|
||||
printf("%lx:%x %x %x %x %x %x: %x\n",
|
||||
ntohl(sp->sap_net),
|
||||
sp->sap_node[0],
|
||||
sp->sap_node[1],
|
||||
sp->sap_node[2],
|
||||
sp->sap_node[3],
|
||||
sp->sap_node[4],
|
||||
sp->sap_node[5],
|
||||
ntohs(sp->sap_sock));
|
||||
result -= sizeof(struct sap_data);
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
7
ipx-1.0/config.ipx
Normal file
7
ipx-1.0/config.ipx
Normal file
@@ -0,0 +1,7 @@
|
||||
IPX_AUTO_PRIMARY=on
|
||||
IPX_AUTO_INTERFACE=on
|
||||
IPX_CONFIGURED=no
|
||||
IPX_DEVICE=eth0
|
||||
IPX_FRAME=802.2
|
||||
IPX_INTERNAL_NET=no
|
||||
IPX_NETNUM=0
|
||||
41
ipx-1.0/init.ipx
Normal file
41
ipx-1.0/init.ipx
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ipx Bring up/down IPX networking
|
||||
#
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
. /etc/sysconfig/network
|
||||
. /etc/sysconfig/ipx
|
||||
|
||||
# Check that networking is up.
|
||||
[ ${NETWORKING} = "no" ] && exit 0
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
if [ ${IPX_CONFIGURED} = "yes" ]; then
|
||||
if [ ${IPX_INTERNAL_NET} = "yes" ]; then
|
||||
/sbin/ipx_internal_net add ${IPX_NETNUM}
|
||||
else
|
||||
/sbin/ipx_interface add -p ${IPX_DEVICE} \
|
||||
${IPX_FRAME} ${IPX_NETNUM}
|
||||
fi
|
||||
fi
|
||||
ipx_configure \
|
||||
--auto_primary=${IPX_AUTO_PRIMARY} \
|
||||
--auto_interface=${IPX_AUTO_INTERFACE}
|
||||
touch /var/lock/subsys/ipx
|
||||
;;
|
||||
stop)
|
||||
ipx_configure --auto_primary=off --auto_interface=off
|
||||
ipx_interface delall
|
||||
rm -f /var/lock/subsys/ipx
|
||||
;;
|
||||
*)
|
||||
echo "Usage: network {start|stop}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
@@ -7,6 +12,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct option options[] = {
|
||||
{ "auto_primary", required_argument, NULL, 1 },
|
||||
@@ -61,8 +67,14 @@ main(int argc, char **argv)
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
int old_errno = errno;
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, "Probably you have no IPX support in "
|
||||
"your kernel\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
394
ipx-1.0/ipx_interface.c
Normal file
394
ipx-1.0/ipx_interface.c
Normal file
@@ -0,0 +1,394 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||
Usage: %s del device frame_type\n\
|
||||
Usage: %s delall\n\
|
||||
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct frame_type {
|
||||
char *ft_name;
|
||||
unsigned char ft_val;
|
||||
} frame_types[] = {
|
||||
{"802.2", IPX_FRAME_8022},
|
||||
#ifdef IPX_FRAME_TR_8022
|
||||
{"802.2TR", IPX_FRAME_TR_8022},
|
||||
#endif
|
||||
{"802.3", IPX_FRAME_8023},
|
||||
{"SNAP", IPX_FRAME_SNAP},
|
||||
{"EtherII", IPX_FRAME_ETHERII}
|
||||
};
|
||||
|
||||
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||
|
||||
int
|
||||
lookup_frame_type(char *frame)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; (j < NFTYPES) &&
|
||||
(strcasecmp(frame_types[j].ft_name, frame));
|
||||
j++)
|
||||
;
|
||||
|
||||
if (j != NFTYPES)
|
||||
return j;
|
||||
|
||||
fprintf(stderr, "%s: Frame type must be", progname);
|
||||
for (j = 0; j < NFTYPES; j++) {
|
||||
fprintf(stderr, "%s%s",
|
||||
(j == NFTYPES-1) ? " or " : " ",
|
||||
frame_types[j].ft_name);
|
||||
}
|
||||
fprintf(stderr, ".\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int i, fti = 0;
|
||||
char c;
|
||||
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||
switch (c) {
|
||||
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++) {
|
||||
switch (i-optind) {
|
||||
case 0: /* Physical Device - Required */
|
||||
strcpy(id.ifr_name, argv[i]);
|
||||
break;
|
||||
case 1: /* Frame Type - Required */
|
||||
fti = lookup_frame_type(argv[i]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
break;
|
||||
|
||||
case 2: /* Network Number - Optional */
|
||||
netnum = strtoul(argv[i], (char **)NULL, 16);
|
||||
if (netnum == 0xffffffffL) {
|
||||
fprintf(stderr,
|
||||
"%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
int old_errno = errno;
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, "Probably you have no IPX support in "
|
||||
"your kernel\n");
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
do {
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case ENETDOWN:
|
||||
fprintf(stderr, "%s: Requested device (%s) is down.\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create interface.\n",
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_delall_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fgets(buffer, 80, fp);
|
||||
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||
device, frame_type) == 5) {
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
if (strcasecmp(device, "Internal") == 0) {
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
} else {
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, device);
|
||||
fti = lookup_frame_type(frame_type);
|
||||
if (fti < 0) continue;
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
}
|
||||
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) continue;
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_type);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n",
|
||||
progname, device);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||
progname, device, frame_type);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_check_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCGIFADDR, &id);
|
||||
if (result == 0) {
|
||||
printf(
|
||||
"IPX Address for (%s, %s) is %08lX:%02X%02X%02X%02X%02X%02X.\n",
|
||||
argv[1], frame_types[fti].ft_name,
|
||||
htonl(sipx->sipx_network), sipx->sipx_node[0],
|
||||
sipx->sipx_node[1], sipx->sipx_node[2],
|
||||
sipx->sipx_node[3], sipx->sipx_node[4],
|
||||
sipx->sipx_node[5]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EADDRNOTAVAIL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "delall", 6) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_delall_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "check", 5) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_check_interface(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
200
ipx-1.0/ipx_internal_net.c
Normal file
200
ipx-1.0/ipx_internal_net.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||
Usage: %s del\n", progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_internal_net(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int nodelen;
|
||||
char *node;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
char *tin;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
node = argv[2];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node is invalid.\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
i = 0;
|
||||
do {
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create internal net.\n",
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_internal_net(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
|
||||
if (argc != 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_internal_net(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_internal_net(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
220
ipx-1.0/ipx_route.c
Normal file
220
ipx-1.0/ipx_route.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/route.h>
|
||||
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
|
||||
Usage: %s del network(hex)\n", progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
int nodelen;
|
||||
int i;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
char *node;
|
||||
char *tin;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
|
||||
if (argc != 4)
|
||||
usage();
|
||||
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Network Number */
|
||||
netnum = strtoul(argv[2], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
sr->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Node */
|
||||
node = argv[3];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||
i = 0;
|
||||
do {
|
||||
result = ioctl(s, SIOCADDRT, &rd);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENETUNREACH:
|
||||
fprintf(stderr, "%s: Router network (%08lX) not reachable.\n",
|
||||
progname, htonl(sr->sipx_network));
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
st->sipx_family = sr->sipx_family = AF_IPX;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
result = ioctl(s, SIOCDELRT, &rd);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||
progname, netnum);
|
||||
break;
|
||||
case EPERM:
|
||||
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||
progname, netnum);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_route(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_route(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
35
ipxdump/Makefile
Normal file
35
ipxdump/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
EXEC= ipxdump ipxparse
|
||||
|
||||
CFLAGS= -Wall -O2
|
||||
OBJECTS= ipxutil.o
|
||||
|
||||
all: $(EXEC)
|
||||
|
||||
ipxdump: ipxdump.o $(OBJECTS)
|
||||
$(CC) -o $@ ipxdump.o $(CFLAGS) $(OBJECTS)
|
||||
|
||||
ipxparse: ipxparse.o $(OBJECTS)
|
||||
$(CC) -o $@ ipxparse.o $(CFLAGS) $(OBJECTS)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(EXEC) *~
|
||||
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
|
||||
mrproper: clean
|
||||
rm -f $(DISTFILE)
|
||||
|
||||
dist: tgz
|
||||
make all
|
||||
|
||||
tgz: mrproper
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
mv $(DISTFILE) $(SRCDIR))
|
||||
|
||||
45
ipxdump/README
Normal file
45
ipxdump/README
Normal file
@@ -0,0 +1,45 @@
|
||||
This is a VERY stupid packet sniffer for IPX ethernet packets.
|
||||
|
||||
=============================================
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
! ! ! S E C U R I T Y W A R N I N G ! ! !
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
=============================================
|
||||
|
||||
If you are using unencrypted passwords, and use this tool to send a
|
||||
dump to somebody else or store it on a computer, you might very well
|
||||
store passwords there. So, be VERY careful! This is exactly the kind
|
||||
of tools Novell designed the encrypted passwords for (or against).
|
||||
|
||||
|
||||
|
||||
I hacked it together to be able to help people with problems with
|
||||
ncpfs. The socket handling was taken from Statnet-2.0.
|
||||
|
||||
You can use it to watch commercial NetWare clients when they talk to
|
||||
servers. I divided the program into 2 parts, ipxdump and ipxparse.
|
||||
|
||||
ipxdump simply pumps all the IPX frames it receives to stdout.
|
||||
|
||||
If you use ipxdump to watch a workstation, you can use the simple
|
||||
filter function ipxdump provides. You can call ipxdump with the node
|
||||
address of the workstation you want to watch. This way only the
|
||||
packets this workstation sends and receives are monitored. As an
|
||||
example, I call ipxdump as
|
||||
|
||||
./ipxdump 00001B038B11
|
||||
|
||||
to look at my 286/10MHz test 'workstation'. ipxdump still generates
|
||||
huge amounts of data, so you should be very careful to start it just
|
||||
before you perform the operation (such as file creation for OS/2
|
||||
clients with NW4.1 as a server, or a 'dir' on a directory with long
|
||||
and short file names, or an encrypted password change ;-)) and stop it
|
||||
directly after that. And, please gzip -9 and uuencode it before you
|
||||
send it to anybody.
|
||||
|
||||
ipxparse will eventually take apart the dump that ipxdump
|
||||
generates. They can as well be used in a pipe. Currently ipxparse does
|
||||
not do anything sensible, but that will definitely change.
|
||||
|
||||
Volker Lendecke
|
||||
<lendecke@namu01.gwdg.de>
|
||||
245
ipxdump/ipxdump.c
Normal file
245
ipxdump/ipxdump.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* ipxdump.c */
|
||||
|
||||
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <strings.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <signal.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/protocols.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
struct ipx_address
|
||||
{
|
||||
unsigned long net;
|
||||
unsigned char node[IPX_NODE_LEN];
|
||||
unsigned short sock;
|
||||
};
|
||||
|
||||
struct ipx_packet
|
||||
{
|
||||
unsigned short ipx_checksum;
|
||||
#define IPX_NO_CHECKSUM 0xFFFF
|
||||
unsigned short ipx_pktsize;
|
||||
unsigned char ipx_tctrl;
|
||||
unsigned char ipx_type;
|
||||
#define IPX_TYPE_UNKNOWN 0x00
|
||||
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||
struct ipx_address ipx_source __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
|
||||
void handle_ipx(char *frame, unsigned char *buf);
|
||||
|
||||
static int filter = 0;
|
||||
static IPXNode filter_node;
|
||||
|
||||
static int exit_request = 0;
|
||||
static void
|
||||
int_handler()
|
||||
{
|
||||
exit_request = 1;
|
||||
}
|
||||
|
||||
void
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int sd;
|
||||
struct ifreq ifr, oldifr;
|
||||
char *device = "eth0";
|
||||
struct sockaddr saddr;
|
||||
int sizeaddr;
|
||||
unsigned char buf[4096];
|
||||
int length;
|
||||
|
||||
signal(SIGINT, int_handler);
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (ipx_sscanf_node(argv[1], filter_node) != 0)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [node]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
filter = 1;
|
||||
}
|
||||
|
||||
if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
|
||||
{
|
||||
perror ("Can't get socket");
|
||||
fprintf(stderr, "You must run %s as root\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* SET PROMISC */
|
||||
|
||||
strcpy (oldifr.ifr_name, device);
|
||||
if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't get flags");
|
||||
exit (2);
|
||||
}
|
||||
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
ifr = oldifr;
|
||||
ifr.ifr_flags |= IFF_PROMISC;
|
||||
|
||||
if (ioctl (sd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't set flags");
|
||||
exit (3);
|
||||
}
|
||||
|
||||
while ( exit_request == 0 )
|
||||
{
|
||||
/* This is the main data-gathering loop; keep it small
|
||||
and fast */
|
||||
sizeaddr = sizeof(saddr);
|
||||
length = recvfrom (sd, buf, sizeof(buf), 0,
|
||||
&saddr, &sizeaddr);
|
||||
if (length < 0 ) continue;
|
||||
handle_frame (buf, length, &saddr);
|
||||
}
|
||||
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't set flags");
|
||||
exit (4);
|
||||
}
|
||||
|
||||
close (sd);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipx (char *frame, unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||
struct sockaddr_ipx s_addr;
|
||||
struct sockaddr_ipx d_addr;
|
||||
int length = ntohs(h->ipx_pktsize);
|
||||
|
||||
|
||||
memset(&s_addr, 0, sizeof(s_addr));
|
||||
memset(&d_addr, 0, sizeof(d_addr));
|
||||
|
||||
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||
s_addr.sipx_port = h->ipx_source.sock;
|
||||
s_addr.sipx_network = h->ipx_source.net;
|
||||
|
||||
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||
d_addr.sipx_port = h->ipx_dest.sock;
|
||||
d_addr.sipx_network = h->ipx_dest.net;
|
||||
|
||||
if (filter != 0)
|
||||
{
|
||||
if ( (memcmp(filter_node, s_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0)
|
||||
&& (memcmp(filter_node, d_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0))
|
||||
{
|
||||
/* Not for us */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s ", frame);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
printf("%2.2X", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
if (!isatty(STDOUT_FILENO))
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
struct ethhdr *eth = (struct ethhdr *)buf;
|
||||
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
|
||||
|
||||
if (ntohs(eth->h_proto) < 1536)
|
||||
{
|
||||
/* This is a magic hack to spot IPX packets. Older
|
||||
* Novell breaks the protocol design and runs IPX over
|
||||
* 802.3 without an 802.2 LLC layer. We look for FFFF
|
||||
* which isnt a used 802.2 SSAP/DSAP. This won't work
|
||||
* for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
|
||||
if (*(unsigned short *)p == 0xffff)
|
||||
{
|
||||
handle_ipx("802.3", p);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (*(unsigned short *)p == htons(0xe0e0))
|
||||
&& (p[2] == 0x03))
|
||||
{
|
||||
handle_ipx("802.2", p+3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||
{
|
||||
handle_ipx("snap", p+8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
/* Ethernet packet type ID field */
|
||||
unsigned short packet_type = ((struct ethhdr *)buf)->h_proto;
|
||||
switch( packet_type )
|
||||
{
|
||||
case __constant_ntohs(ETH_P_IPX):
|
||||
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
|
||||
break;
|
||||
default:
|
||||
handle_other(buf, length, saddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
644
ipxdump/ipxparse.c
Normal file
644
ipxdump/ipxparse.c
Normal file
@@ -0,0 +1,644 @@
|
||||
/* ipxparse.c */
|
||||
|
||||
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <strings.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <signal.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/protocols.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
#define DUMPALLSAPS /* #define if you want to dump all SAP's */
|
||||
|
||||
struct ipx_address
|
||||
{
|
||||
unsigned long net;
|
||||
unsigned char node[IPX_NODE_LEN];
|
||||
unsigned short sock;
|
||||
};
|
||||
|
||||
struct ipx_packet
|
||||
{
|
||||
unsigned short ipx_checksum;
|
||||
#define IPX_NO_CHECKSUM 0xFFFF
|
||||
unsigned short ipx_pktsize;
|
||||
unsigned char ipx_tctrl;
|
||||
unsigned char ipx_type;
|
||||
#define IPX_TYPE_UNKNOWN 0x00
|
||||
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||
struct ipx_address ipx_source __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_ALLOC_SLOT_REQUEST (0x1111)
|
||||
#define NCP_REQUEST (0x2222)
|
||||
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
||||
|
||||
struct ncp_request_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 function __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_REPLY (0x3333)
|
||||
#define NCP_POSITIVE_ACK (0x9999)
|
||||
|
||||
struct ncp_reply_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 completion_code __attribute__ ((packed));
|
||||
__u8 connection_state __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_BURST_PACKET (0x7777)
|
||||
|
||||
struct ncp_burst_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 system_flags __attribute__ ((packed));
|
||||
__u8 stream_type __attribute__ ((packed));
|
||||
__u32 source_conn __attribute__ ((packed));
|
||||
__u32 dest_conn __attribute__ ((packed));
|
||||
__u32 packet_sequence __attribute__ ((packed));
|
||||
__u32 send_delay __attribute__ ((packed));
|
||||
__u16 burst_sequence __attribute__ ((packed));
|
||||
__u16 ack_sequence __attribute__ ((packed));
|
||||
__u32 burst_length __attribute__ ((packed));
|
||||
__u32 data_offset __attribute__ ((packed));
|
||||
__u16 data_bytes __attribute__ ((packed));
|
||||
__u16 missing_frags __attribute__ ((packed));
|
||||
};
|
||||
|
||||
void handle_ipx (unsigned char *buf, int length, char *frame, int no);
|
||||
void handle_ncp (struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no);
|
||||
int handle_burst(struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no);
|
||||
|
||||
#define SAP_MAX_SERVER_NAME_LENGTH 48 /* in network packets */
|
||||
#define SAP_MAX_SAPS_PER_PACKET 7
|
||||
#define SAP_SHUTDOWN 16 /* Magic "hops" value to stop SAP advertising */
|
||||
|
||||
/* SAP Query structure (returned in sap_packet as an array)
|
||||
* NBO == Network Byte Order)
|
||||
*/
|
||||
typedef struct saps {
|
||||
__u16 serverType __attribute__ ((packed)); /* NBO */
|
||||
__u8 serverName[SAP_MAX_SERVER_NAME_LENGTH] __attribute__ ((packed));
|
||||
struct ipx_address serverAddress __attribute__ ((packed));
|
||||
__u16 serverHops __attribute__ ((packed)); /* NBO */
|
||||
} SAPS;
|
||||
|
||||
/* General Service/Nearest Server Response SAP packet */
|
||||
union sap_packet {
|
||||
unsigned short sapOperation;
|
||||
struct sap_query {
|
||||
__u16 sapOperation __attribute__ ((packed));
|
||||
__u16 serverType __attribute__ ((packed));
|
||||
} query;
|
||||
struct sap_response {
|
||||
__u16 sapOperation __attribute__ ((packed));
|
||||
/* each SAP can has a max of SAP_MAX_SAPS_PER_PACKET packets */
|
||||
SAPS sap[SAP_MAX_SAPS_PER_PACKET] __attribute__ ((packed));
|
||||
} response;
|
||||
};
|
||||
|
||||
/* print out one SAP record */
|
||||
static void
|
||||
print_sap(FILE *file, SAPS *sapp)
|
||||
{
|
||||
fprintf(file, " Name:%s, serverType 0x%x, ",
|
||||
sapp->serverName,
|
||||
ntohs(sapp->serverType));
|
||||
ipx_fprint_network(file, ntohl(sapp->serverAddress.net));
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_node(file, sapp->serverAddress.node);
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_port(file, ntohs(sapp->serverAddress.sock));
|
||||
fprintf(file, " (Hops %d)\n", ntohs(sapp->serverHops));
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
||||
{
|
||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||
struct sockaddr_ipx s_addr;
|
||||
struct sockaddr_ipx d_addr;
|
||||
union sap_packet *sappacket;
|
||||
int hbo_dsock; /* Host Byte Order of Destination SOCKet */
|
||||
int hbo_sapop; /* Host Byte Order of SAP OPeration */
|
||||
|
||||
memset(&s_addr, 0, sizeof(s_addr));
|
||||
memset(&d_addr, 0, sizeof(d_addr));
|
||||
|
||||
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||
s_addr.sipx_port = h->ipx_source.sock;
|
||||
s_addr.sipx_network = h->ipx_source.net;
|
||||
|
||||
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||
d_addr.sipx_port = h->ipx_dest.sock;
|
||||
d_addr.sipx_network = h->ipx_dest.net;
|
||||
|
||||
printf("%6.6d %s from ", no, frame);
|
||||
|
||||
ipx_print_saddr(&s_addr);
|
||||
printf(" to ");
|
||||
ipx_print_saddr(&d_addr);
|
||||
printf("\n");
|
||||
|
||||
if (handle_burst(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
||||
length - sizeof(struct ipx_packet), no) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (ntohs(s_addr.sipx_port) == 0x451)
|
||||
|| (ntohs(d_addr.sipx_port) == 0x451))
|
||||
{
|
||||
handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
||||
length - sizeof(struct ipx_packet), no);
|
||||
}
|
||||
else /* next 3 handle IPX by type vs by socket (one or other) */
|
||||
/* Note: most things use either ipx_type OR socket, not both */
|
||||
if (h->ipx_type == 0x01)
|
||||
printf(" type 0x01 (RIP packet (router))\n");
|
||||
else
|
||||
if (h->ipx_type == 0x05)
|
||||
printf(" type 0x05 (SPX sequenced packet)\n");
|
||||
else
|
||||
if (h->ipx_type == 0x14)
|
||||
printf(" type 0x14 (propogated Client-NetBios)\n");
|
||||
else
|
||||
{
|
||||
hbo_dsock = ntohs(d_addr.sipx_port);
|
||||
if (hbo_dsock == 0x452) /* SAP */
|
||||
{
|
||||
sappacket = (union sap_packet *)
|
||||
(buf + sizeof(struct ipx_packet));
|
||||
hbo_sapop = ntohs(sappacket->sapOperation);
|
||||
if ((hbo_sapop == 0x01) || (hbo_sapop == 0x03))
|
||||
{
|
||||
printf(" type 0x%x, SAP op:0x%x %s Query, "
|
||||
"serverType 0x%x wanted\n",
|
||||
h->ipx_type, hbo_sapop,
|
||||
(hbo_sapop == 0x01)?"General Service" :
|
||||
(hbo_sapop == 0x03)?"Nearest Server" :
|
||||
"Error",
|
||||
ntohs(sappacket->query.serverType));
|
||||
}
|
||||
else
|
||||
{
|
||||
int hops;
|
||||
|
||||
hops = ntohs(sappacket->
|
||||
response.sap[0].serverHops);
|
||||
printf(" type 0x%x, SAP op:0x%x %s %s\n",
|
||||
h->ipx_type, hbo_sapop,
|
||||
(hbo_sapop == 0x02)
|
||||
? "General Service Response" :
|
||||
(hbo_sapop == 0x04)
|
||||
? "Nearest Server Response" :
|
||||
"Unknown",
|
||||
(hops >= SAP_SHUTDOWN)
|
||||
? "[Shutdown]" : "");
|
||||
|
||||
/* Service ending */
|
||||
if (hops >= SAP_SHUTDOWN)
|
||||
{
|
||||
print_sap(stdout,
|
||||
sappacket->response.sap);
|
||||
}
|
||||
#ifdef DUMPALLSAPS
|
||||
/* If you want to dump all SAP's */
|
||||
else
|
||||
{ int num_saps;
|
||||
SAPS *sapp;
|
||||
|
||||
num_saps = (length
|
||||
- sizeof(struct ipx_packet)
|
||||
- 2) / sizeof(SAPS);
|
||||
|
||||
sapp = sappacket->response.sap;
|
||||
for(; num_saps > 0; sapp++, num_saps--)
|
||||
print_sap(stdout, sapp);
|
||||
}
|
||||
#endif /* DUMPALLSAPS */
|
||||
}
|
||||
|
||||
}
|
||||
else /* Other IPX types */
|
||||
printf(" type 0x%x, Socket 0x%x (%s)\n", h->ipx_type,
|
||||
hbo_dsock,
|
||||
(hbo_dsock == 0x451) ? "NCP" :
|
||||
/* (hbo_dsock == 0x452) ? "SAP" :*/
|
||||
(hbo_dsock == 0x453) ? "RIP" :
|
||||
(hbo_dsock == 0x455) ? "Client-NetBios" :
|
||||
(hbo_dsock == 0x456) ? "Diags" :
|
||||
(hbo_dsock == 0x002) ? "Xecho" :
|
||||
(hbo_dsock == 0x8063) ? "NVT2" : "Other");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int handle_burst(struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no)
|
||||
{
|
||||
struct ncp_burst_header *rq = (struct ncp_burst_header *)buf;
|
||||
|
||||
if (rq->type != NCP_BURST_PACKET)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Burst Packet\n");
|
||||
printf("Stream Type: %02X, System Flags: %02X\n",
|
||||
rq->stream_type, rq->system_flags);
|
||||
printf("Source Conn: %08X, Dest Conn: %08X, Packet Seq: %08X\n",
|
||||
rq->source_conn, rq->dest_conn,
|
||||
(unsigned int)ntohl(rq->packet_sequence));
|
||||
printf("Send Delay: %08X, Burst Seq: %04X, Ack Seq: %04X\n",
|
||||
(unsigned int)ntohl(rq->send_delay), ntohs(rq->burst_sequence),
|
||||
ntohs(rq->ack_sequence));
|
||||
printf("Burst Length: %08X\n", (unsigned int)ntohl(rq->burst_length));
|
||||
printf("Data Offset: %08X, Data Bytes: %04X, Missing Frags: %04X\n",
|
||||
(unsigned int)ntohl(rq->data_offset), ntohs(rq->data_bytes),
|
||||
ntohs(rq->missing_frags));
|
||||
|
||||
if (ntohs(rq->data_bytes) == 24)
|
||||
{
|
||||
struct ncp_burst_request
|
||||
{
|
||||
struct ncp_burst_header h __attribute__ ((packed));
|
||||
__u32 function __attribute__ ((packed));
|
||||
__u32 file_handle __attribute__ ((packed));
|
||||
__u8 reserved[8] __attribute__ ((packed));
|
||||
__u32 file_offset __attribute__ ((packed));
|
||||
__u32 number_of_bytes __attribute__ ((packed));
|
||||
} *brq = (struct ncp_burst_request *)rq;
|
||||
|
||||
printf("Assuming Burst Request:\n");
|
||||
printf("%s: Handle %08X, Offset %08X, Bytes %08X\n",
|
||||
brq->function == 1 ? "Read " : "Write",
|
||||
brq->file_handle,
|
||||
(unsigned int)ntohl(brq->file_offset),
|
||||
(unsigned int)ntohl(brq->number_of_bytes));
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void handle_ncp (struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no)
|
||||
{
|
||||
struct ncp_request_header *rq = (struct ncp_request_header *)buf;
|
||||
struct ncp_reply_header *rs = (struct ncp_reply_header *)buf;
|
||||
unsigned char *data = NULL;
|
||||
int data_length = 0;
|
||||
int i;
|
||||
|
||||
if (ntohs(rq->type) == NCP_REQUEST)
|
||||
{
|
||||
/* Request */
|
||||
printf("NCP request: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||
rq->conn_low + 256 * rq->conn_high,
|
||||
rq->sequence, rq->task);
|
||||
|
||||
data = buf + sizeof(struct ncp_request_header);
|
||||
data_length = length - sizeof(struct ncp_request_header);
|
||||
|
||||
switch(rq->function)
|
||||
{
|
||||
case 20:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Get File Server Date and Time\n");
|
||||
break;
|
||||
case 21:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 0:
|
||||
printf("Send Broadcast Message\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("Get Broadcast Message\n");
|
||||
break;
|
||||
}
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 22:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 00:
|
||||
printf("Set Directory Handle\n");
|
||||
break;
|
||||
case 01:
|
||||
printf("Get Directory Path\n");
|
||||
break;
|
||||
case 03:
|
||||
printf("Get Effective Directory Rights\n");
|
||||
break;
|
||||
case 05:
|
||||
printf("Get Volume Number\n");
|
||||
break;
|
||||
case 06:
|
||||
printf("Get Volume Name\n");
|
||||
break;
|
||||
case 18:
|
||||
printf("Allocate Permanent Dir Handle\n");
|
||||
break;
|
||||
case 20:
|
||||
printf("Deallocate Directory Handle\n");
|
||||
break;
|
||||
case 21:
|
||||
printf("Get Volume Info with handle\n");
|
||||
break;
|
||||
case 48:
|
||||
printf("Get Name Space Directory Entry\n");
|
||||
break;
|
||||
}
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 23:
|
||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||
data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 17:
|
||||
printf("Get Fileserver Information\n");
|
||||
break;
|
||||
case 22:
|
||||
printf("Get Station's logged Info (old)\n");
|
||||
break;
|
||||
case 23:
|
||||
printf("Get Crypt Key\n");
|
||||
break;
|
||||
case 24:
|
||||
printf("Encrypted Login\n");
|
||||
break;
|
||||
case 28:
|
||||
printf("Get Connection Information\n");
|
||||
break;
|
||||
case 53:
|
||||
printf("Get Bindery Object ID\n");
|
||||
break;
|
||||
case 55:
|
||||
printf("Scan Bindery Object\n");
|
||||
break;
|
||||
case 61:
|
||||
printf("Read Property Value\n");
|
||||
break;
|
||||
case 62:
|
||||
printf("Write Property Value\n");
|
||||
break;
|
||||
case 70:
|
||||
printf("Get Bindery Access Level\n");
|
||||
break;
|
||||
}
|
||||
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 24:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("End of Job\n");
|
||||
break;
|
||||
case 33:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Negotiate Buffer size\n");
|
||||
break;
|
||||
case 34:
|
||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||
data[2]);
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 62:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("File Search Initialize\n");
|
||||
break;
|
||||
case 63:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("File Search Continue\n");
|
||||
break;
|
||||
case 64:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Search for a file\n");
|
||||
break;
|
||||
case 66:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Close File\n");
|
||||
break;
|
||||
case 72:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Read from File\n");
|
||||
break;
|
||||
case 73:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Write to File\n");
|
||||
break;
|
||||
case 75:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Set File Time Date Stamp\n");
|
||||
break;
|
||||
case 87:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[0]);
|
||||
switch(data[0])
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
unsigned char *p = &(data[0]);
|
||||
printf("Open Create File or Subdirectory\n");
|
||||
printf("Name Space: %d\n", p[1]);
|
||||
printf("Open Create Mode: %x\n", p[2]);
|
||||
printf("Search Attributes: %x\n",
|
||||
*(__u16 *)&(p[3]));
|
||||
printf("Return Information Mask: %x\n",
|
||||
(unsigned int)(*(__u32 *)&(p[5])));
|
||||
printf("Desired Access Rights: %x\n",
|
||||
*(__u16 *)&(p[9]));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
printf("Initialize Search\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("Search for File or Subdirectory\n");
|
||||
break;
|
||||
case 6:
|
||||
printf("Obtain File Or Subdirectory "
|
||||
"Information\n");
|
||||
break;
|
||||
case 8:
|
||||
printf("Delete a File Or Subdirectory\n");
|
||||
break;
|
||||
case 12:
|
||||
printf("Allocate Short Directory Handle\n");
|
||||
break;
|
||||
}
|
||||
data += 1;
|
||||
data_length -= 1;
|
||||
break;
|
||||
case 97:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Get Big Packet NCP Max Packet Size\n");
|
||||
break;
|
||||
case 101:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Packet Burst Connection Request\n");
|
||||
break;
|
||||
default:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
}
|
||||
}
|
||||
|
||||
if (ntohs(rs->type) == NCP_REPLY)
|
||||
{
|
||||
printf("NCP respons: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||
rs->conn_low + 256 * rs->conn_high,
|
||||
rs->sequence, rs->task);
|
||||
printf("compl: %-3d, conn_st: %-3d\n",
|
||||
rs->completion_code, rs->connection_state);
|
||||
|
||||
data = buf + sizeof(struct ncp_reply_header);
|
||||
data_length = length - sizeof(struct ncp_reply_header);
|
||||
}
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
data = buf;
|
||||
data_length = length;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < data_length)
|
||||
{
|
||||
int j;
|
||||
for (j = i; j < i+16; j++)
|
||||
{
|
||||
if (j >= data_length)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%-2.2X", data[j]);
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
for (j = i; j < i+16; j++)
|
||||
{
|
||||
if (j >= data_length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (isprint(data[j]))
|
||||
{
|
||||
printf("%c", data[j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
i += 16;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
unsigned char buf[16384];
|
||||
unsigned char packet[8192];
|
||||
unsigned char *b;
|
||||
int len;
|
||||
int i = 1;
|
||||
|
||||
while (fgets(buf, sizeof(buf), stdin) != NULL)
|
||||
{
|
||||
if (strlen(buf) == sizeof(buf)-1)
|
||||
{
|
||||
fprintf(stderr, "line too long\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
b = strchr(buf, ' ');
|
||||
if (b == NULL)
|
||||
{
|
||||
fprintf(stderr, "illegal line format\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*b = '\0';
|
||||
b += 1;
|
||||
len = 0;
|
||||
|
||||
while ((b[0] != '\0') && (b[1] != '\0'))
|
||||
{
|
||||
unsigned int value;
|
||||
if (sscanf(b, "%2x", &value) != 1)
|
||||
{
|
||||
fprintf(stderr, "illegal packet\n");
|
||||
exit(1);
|
||||
}
|
||||
packet[len] = value;
|
||||
b += 2;
|
||||
len += 1;
|
||||
}
|
||||
handle_ipx(packet, len, buf, i);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
129
ipxdump/ipxutil.c
Normal file
129
ipxdump/ipxutil.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
IPX support library - general functions
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
ipx_fprint_node(FILE *file, IPXNode node)
|
||||
{
|
||||
fprintf(file,"%02X%02X%02X%02X%02X%02X",
|
||||
(unsigned char)node[0],
|
||||
(unsigned char)node[1],
|
||||
(unsigned char)node[2],
|
||||
(unsigned char)node[3],
|
||||
(unsigned char)node[4],
|
||||
(unsigned char)node[5]
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_network(FILE *file, IPXNet net)
|
||||
{
|
||||
fprintf(file,"%08lX",net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_port(FILE *file, IPXPort port)
|
||||
{
|
||||
fprintf(file,"%04X",port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx *sipx)
|
||||
{
|
||||
ipx_fprint_network(file,ntohl(sipx->sipx_network));
|
||||
fprintf(file,":");
|
||||
ipx_fprint_node(file,sipx->sipx_node);
|
||||
fprintf(file,":");
|
||||
ipx_fprint_port(file,ntohs(sipx->sipx_port));
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_node(IPXNode node)
|
||||
{
|
||||
ipx_fprint_node(stdout,node);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_network(IPXNet net)
|
||||
{
|
||||
ipx_fprint_network(stdout,net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_port(IPXPort port)
|
||||
{
|
||||
ipx_fprint_port(stdout,port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_saddr(struct sockaddr_ipx *sipx)
|
||||
{
|
||||
ipx_fprint_saddr(stdout,sipx);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src)
|
||||
{
|
||||
memcpy(dest,src,sizeof(IPXNode));
|
||||
}
|
||||
|
||||
int
|
||||
ipx_node_equal(IPXNode n1, IPXNode n2)
|
||||
{
|
||||
return memcmp(n1,n2,sizeof(IPXNode))==0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_node(char *buf, IPXNode node)
|
||||
{
|
||||
int i;
|
||||
int n[6];
|
||||
|
||||
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
||||
&(n[0]), &(n[1]), &(n[2]),
|
||||
&(n[3]), &(n[4]), &(n[5]))) != 6)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
node[i] = n[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_net(char *buf, IPXNet *target)
|
||||
{
|
||||
if (sscanf(buf, "%8lX", target) == 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
IPXNode ipx_this_node={0,0,0,0,0,0};
|
||||
IPXNode ipx_broadcast_node={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
char ipx_err_string[IPX_MAX_ERROR+1]="no error detected";
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
/*
|
||||
|
||||
IPX support library
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -24,53 +24,42 @@
|
||||
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define IPX_RIP_PTYPE (0x01)
|
||||
#define IPX_SAP_PTYPE (0x04)
|
||||
#define IPX_SAP_PORT (0x0452)
|
||||
#define IPX_RIP_PORT (0x0453)
|
||||
|
||||
#define IPX_SAP_GENERAL_QUERY (0x0001)
|
||||
#define IPX_SAP_GENERAL_RESPONSE (0x0002)
|
||||
#define IPX_SAP_NEAREST_QUERY (0x0003)
|
||||
#define IPX_SAP_NEAREST_RESPONSE (0x0004)
|
||||
|
||||
#define IPX_SAP_FILE_SERVER (0x0004)
|
||||
|
||||
#define IPX_RIP_REQUEST (0x1)
|
||||
#define IPX_RIP_RESPONSE (0x2)
|
||||
|
||||
struct ipx_rip_packet {
|
||||
__u16 operation __attribute__ ((packed));
|
||||
struct ipx_rt_def {
|
||||
__u32 network __attribute__ ((packed));
|
||||
__u16 hops __attribute__ ((packed));
|
||||
__u16 ticks __attribute__ ((packed));
|
||||
} rt[1] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define IPX_BROADCAST_NODE "\xff\xff\xff\xff\xff\xff"
|
||||
#define IPX_THIS_NODE "\0\0\0\0\0\0"
|
||||
|
||||
#ifndef IPX_NODE_LEN
|
||||
#define IPX_NODE_LEN (6)
|
||||
#endif
|
||||
|
||||
typedef unsigned long IPXNet;
|
||||
typedef unsigned short IPXPort;
|
||||
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
||||
#define IPX_MAX_ERROR (255)
|
||||
#define IPX_THIS_NET (0)
|
||||
#define IPX_THIS_NODE (ipx_this_node)
|
||||
#define IPX_BROADCAST (ipx_broadcast_node)
|
||||
#define IPX_AUTO_PORT (0)
|
||||
#define IPX_USER_PTYPE (0)
|
||||
#define IPX_IS_INTERNAL (1)
|
||||
|
||||
typedef unsigned char IPXNode[6];
|
||||
typedef unsigned long int IPXNet;
|
||||
typedef unsigned short int IPXPort;
|
||||
typedef unsigned short int hop_t;
|
||||
typedef unsigned short int tick_t;
|
||||
|
||||
void ipx_print_node(IPXNode node);
|
||||
void ipx_print_network(IPXNet net);
|
||||
void ipx_print_port(IPXPort port);
|
||||
void ipx_print_saddr(struct sockaddr_ipx* sipx);
|
||||
|
||||
static __inline__ void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src) {
|
||||
memcpy(dest, src, IPX_NODE_LEN);
|
||||
}
|
||||
void ipx_fprint_node(FILE* file,IPXNode node);
|
||||
void ipx_fprint_network(FILE* file,IPXNet net);
|
||||
void ipx_fprint_port(FILE* file,IPXPort port);
|
||||
void ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx);
|
||||
|
||||
int ipx_sscanf_node(char *buf, IPXNode node);
|
||||
int ipx_sscanf_net(char *buf, IPXNet *target);
|
||||
|
||||
void ipx_assign_node(IPXNode dest,IPXNode src);
|
||||
int ipx_node_equal(IPXNode n1,IPXNode n2);
|
||||
|
||||
extern IPXNode ipx_this_node;
|
||||
extern IPXNode ipx_broadcast_node;
|
||||
|
||||
extern char ipx_err_string[IPX_MAX_ERROR+1];
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ncp_fs.h
|
||||
* ncp.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
@@ -9,6 +9,7 @@
|
||||
#define _LINUX_NCP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define NCP_PTYPE (0x11)
|
||||
#define NCP_PORT (0x0451)
|
||||
@@ -51,6 +52,9 @@ struct ncp_bindery_object {
|
||||
__u32 object_id;
|
||||
__u16 object_type;
|
||||
__u8 object_name[NCP_BINDERY_NAME_LEN];
|
||||
__u8 object_flags;
|
||||
__u8 object_security;
|
||||
__u8 object_has_prop;
|
||||
};
|
||||
|
||||
struct nw_property {
|
||||
@@ -59,6 +63,11 @@ struct nw_property {
|
||||
__u8 property_flag;
|
||||
};
|
||||
|
||||
struct prop_net_address {
|
||||
__u32 network __attribute__ ((packed));
|
||||
__u8 node[IPX_NODE_LEN] __attribute__ ((packed));
|
||||
__u16 port __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_VOLNAME_LEN (16)
|
||||
#define NCP_NUMBER_OF_VOLUMES (64)
|
||||
@@ -263,16 +272,23 @@ struct queue_job {
|
||||
|
||||
/* ClientRecordArea for print jobs */
|
||||
|
||||
#define KEEP_ON 0x0400
|
||||
#define NO_FORM_FEED 0x0800
|
||||
#define NOTIFICATION 0x1000
|
||||
#define DELETE_FILE 0x2000
|
||||
#define EXPAND_TABS 0x4000
|
||||
#define PRINT_BANNER 0x8000
|
||||
|
||||
struct print_job_record {
|
||||
__u8 Version __attribute__ ((packed));
|
||||
__u16 TabSize __attribute__ ((packed));
|
||||
__u8 TabSize __attribute__ ((packed));
|
||||
__u16 Copies __attribute__ ((packed));
|
||||
__u8 CtrlFlags __attribute__ ((packed));
|
||||
__u16 CtrlFlags __attribute__ ((packed));
|
||||
__u16 Lines __attribute__ ((packed));
|
||||
__u16 Rows __attribute__ ((packed));
|
||||
char FormName[16] __attribute__ ((packed));
|
||||
__u8 Reserved[6] __attribute__ ((packed));
|
||||
char Banner[13] __attribute__ ((packed));
|
||||
char BannerName[13] __attribute__ ((packed));
|
||||
char FnameBanner[13] __attribute__ ((packed));
|
||||
char FnameHeader[14] __attribute__ ((packed));
|
||||
char Path[80] __attribute__ ((packed));
|
||||
|
||||
@@ -26,8 +26,24 @@ struct ncp_ioctl_request {
|
||||
char *data;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||
struct ncp_fs_info {
|
||||
int version;
|
||||
struct sockaddr_ipx addr;
|
||||
uid_t mounted_uid;
|
||||
int connection; /* Connection number the server assigned us */
|
||||
int buffer_size; /* The negotiated buffer size, to be
|
||||
used for read/write requests! */
|
||||
|
||||
int volume_number;
|
||||
__u32 directory_id;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
|
||||
#define NCP_IOC_GETMOUNTUID _IOW('n', 2, uid_t)
|
||||
#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
|
||||
|
||||
#define NCP_GET_FS_INFO_VERSION (1)
|
||||
#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
|
||||
|
||||
/*
|
||||
* The packet size to allocate. One page should be enough.
|
||||
@@ -45,7 +61,7 @@ struct ncp_ioctl_request {
|
||||
#define NCP_READDIR_CACHE_SIZE 64
|
||||
|
||||
|
||||
#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
|
||||
#define NCP_MAX_RPC_TIMEOUT (6*HZ)
|
||||
|
||||
/* Guess, what 0x564c is :-) */
|
||||
#define NCP_SUPER_MAGIC 0x564c
|
||||
@@ -58,10 +74,6 @@ struct ncp_ioctl_request {
|
||||
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
||||
#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i))
|
||||
|
||||
static inline int min(int a, int b) {
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
|
||||
#include <linux/malloc.h>
|
||||
@@ -113,9 +125,12 @@ extern struct inode_operations ncp_dir_inode_operations;
|
||||
void ncp_free_inode_info(struct ncp_inode_info *i);
|
||||
void ncp_free_all_inodes(struct ncp_server *server);
|
||||
void ncp_init_root(struct ncp_server *server);
|
||||
int ncp_conn_logged_in(struct ncp_server *server);
|
||||
int ncp_stat_root(struct ncp_server *server);
|
||||
void ncp_init_dir_cache(void);
|
||||
void ncp_invalid_dir_cache(unsigned long ino);
|
||||
void ncp_invalid_dir_cache(struct inode *ino);
|
||||
struct ncp_inode_info *ncp_find_inode(struct inode *inode);
|
||||
ino_t ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info);
|
||||
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
||||
void ncp_free_dir_cache(void);
|
||||
int ncp_date_dos2unix(__u16 time, __u16 date);
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
#ifdef __KERNEL__
|
||||
|
||||
enum ncp_inode_state {
|
||||
INODE_VALID = 19, /* Inode currently in use */
|
||||
INODE_LOOKED_UP, /* directly before iget */
|
||||
INODE_CACHED, /* in a path to an inode which is in use */
|
||||
INODE_INVALID
|
||||
NCP_INODE_VALID = 19, /* Inode currently in use */
|
||||
NCP_INODE_LOOKED_UP, /* directly before iget */
|
||||
NCP_INODE_CACHED, /* in a path to an inode which is in use */
|
||||
NCP_INODE_INVALID
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -28,6 +28,7 @@ struct ncp_inode_info {
|
||||
number of references in memory */
|
||||
struct ncp_inode_info *dir;
|
||||
struct ncp_inode_info *next, *prev;
|
||||
struct inode *inode;
|
||||
struct nw_file_info finfo;
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ struct ncp_server {
|
||||
it completely. */
|
||||
|
||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||
|
||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||
void *data_ready; /* The wdog socket gets a new
|
||||
data_ready callback. We store the
|
||||
@@ -35,7 +34,8 @@ struct ncp_server {
|
||||
|
||||
u8 completion; /* Status message from server */
|
||||
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
||||
requests allowed anymore */
|
||||
requests allowed anymore.
|
||||
Bit 0 = 1 ==> Server is down. */
|
||||
|
||||
int buffer_size; /* Negotiated bufsize */
|
||||
|
||||
@@ -56,6 +56,18 @@ struct ncp_server {
|
||||
char root_path; /* '\0' */
|
||||
};
|
||||
|
||||
static inline int
|
||||
ncp_conn_valid(struct ncp_server *server)
|
||||
{
|
||||
return ((server->conn_status & 0x11) == 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ncp_invalidate_conn(struct ncp_server *server)
|
||||
{
|
||||
server->conn_status |= 0x01;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs_i.h>
|
||||
|
||||
#define NCP_MOUNT_VERSION 1
|
||||
#define NCP_MOUNT_VERSION 2
|
||||
|
||||
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
||||
#define NCP_PASSWORD_LEN 20
|
||||
@@ -26,14 +26,14 @@ struct ncp_mount_data {
|
||||
int version;
|
||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||
unsigned int wdog_fd; /* Watchdog packets come here */
|
||||
unsigned int message_fd; /* Not used yet, maybe for messages */
|
||||
unsigned int message_fd; /* Message notifications come here */
|
||||
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
||||
|
||||
struct sockaddr_ipx serv_addr;
|
||||
unsigned char server_name[49];
|
||||
unsigned char server_name[NCP_BINDERY_NAME_LEN];
|
||||
|
||||
unsigned char username[NCP_USERNAME_LEN+1];
|
||||
unsigned char password[NCP_PASSWORD_LEN+1];
|
||||
unsigned char mount_point[PATH_MAX+1];
|
||||
unsigned char mounted_vol[NCP_VOLNAME_LEN+1];
|
||||
|
||||
unsigned int time_out; /* How long should I wait after
|
||||
sending a NCP request? */
|
||||
|
||||
@@ -2,10 +2,8 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -I..
|
||||
|
||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||
$(INCLUDES) \
|
||||
$(INCLUDES) -DNCPFS_VERSION=\"$(VERSION)\"\
|
||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||
# -DDEBUG_NCP_MALLOC
|
||||
|
||||
@@ -20,14 +18,14 @@ ARCH = i386
|
||||
.s.o:
|
||||
$(AS) -o $*.o $<
|
||||
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o mmap.o
|
||||
|
||||
all: ncpfs.o
|
||||
all: $(INTERM_BINDIR)/ncpfs.o
|
||||
|
||||
ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o ncpfs.o $(OBJS)
|
||||
$(INTERM_BINDIR)/ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o $@ $(OBJS)
|
||||
|
||||
ncplib.o: ncplib.c ncplib.h
|
||||
ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||
|
||||
dep:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,15 +5,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* #include <linux/module.h>*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define MOD_INC_USE_COUNT
|
||||
#define MOD_DEC_USE_COUNT
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
@@ -26,9 +21,15 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include "ncplib.h"
|
||||
#include <linux/locks.h>
|
||||
#include "ncplib_kernel.h"
|
||||
#include <linux/malloc.h>
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_fsync(struct inode *inode, struct file *file)
|
||||
{
|
||||
@@ -40,7 +41,8 @@ ncp_make_open(struct inode *i, int right)
|
||||
{
|
||||
struct nw_file_info *finfo;
|
||||
|
||||
if (i == NULL) {
|
||||
if (i == NULL)
|
||||
{
|
||||
printk("ncp_make_open: got NULL inode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -49,27 +51,31 @@ ncp_make_open(struct inode *i, int right)
|
||||
|
||||
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
|
||||
|
||||
if (finfo->opened == 0) {
|
||||
|
||||
lock_super(i->i_sb);
|
||||
if (finfo->opened == 0)
|
||||
{
|
||||
finfo->access = -1;
|
||||
/* tries max. rights */
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ | AR_WRITE,
|
||||
finfo) == 0) {
|
||||
finfo) == 0)
|
||||
{
|
||||
finfo->access = O_RDWR;
|
||||
}
|
||||
else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ,
|
||||
finfo) == 0) {
|
||||
finfo) == 0)
|
||||
{
|
||||
finfo->access = O_RDONLY;
|
||||
} else {
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
unlock_super(i->i_sb);
|
||||
|
||||
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|
||||
|| (finfo->access == O_RDWR)))
|
||||
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)
|
||||
@@ -83,18 +89,24 @@ ncp_make_open(struct inode *i, int right)
|
||||
static int
|
||||
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
{
|
||||
int bufsize, to_read, already_read;
|
||||
int bufsize, already_read;
|
||||
off_t pos;
|
||||
int errno;
|
||||
|
||||
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
if (!inode) {
|
||||
if (inode == NULL)
|
||||
{
|
||||
DPRINTK("ncp_file_read: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
|
||||
inode->i_mode);
|
||||
return -EINVAL;
|
||||
@@ -103,33 +115,34 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
pos = file->f_pos;
|
||||
|
||||
if (pos + count > inode->i_size)
|
||||
{
|
||||
count = inode->i_size - pos;
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
already_read = 0;
|
||||
|
||||
/* First read in as much as possible for each bufsize. */
|
||||
while (already_read < count) {
|
||||
|
||||
while (already_read < count)
|
||||
{
|
||||
int read_this_time;
|
||||
|
||||
if ((pos % bufsize) != 0) {
|
||||
to_read = bufsize - (pos % bufsize);
|
||||
} else {
|
||||
to_read = bufsize;
|
||||
}
|
||||
|
||||
to_read = min(to_read, count - already_read);
|
||||
int to_read = min(bufsize - (pos % bufsize),
|
||||
count - already_read);
|
||||
|
||||
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||
pos, to_read, buf, &read_this_time) != 0) {
|
||||
pos, to_read, buf, &read_this_time) != 0)
|
||||
{
|
||||
return -EIO; /* This is not exact, i know.. */
|
||||
}
|
||||
|
||||
@@ -137,14 +150,19 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
buf += read_this_time;
|
||||
already_read += read_this_time;
|
||||
|
||||
if (read_this_time < to_read) {
|
||||
if (read_this_time < to_read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file->f_pos = pos;
|
||||
|
||||
if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
|
||||
if (!IS_RDONLY(inode))
|
||||
{
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
}
|
||||
|
||||
inode->i_dirt = 1;
|
||||
|
||||
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
@@ -156,16 +174,22 @@ static int
|
||||
ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
int count)
|
||||
{
|
||||
int bufsize, to_write, already_written;
|
||||
int bufsize, already_written;
|
||||
off_t pos;
|
||||
int errno;
|
||||
|
||||
if (!inode) {
|
||||
if (inode == NULL)
|
||||
{
|
||||
DPRINTK("ncp_file_write: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
|
||||
inode->i_mode);
|
||||
return -EINVAL;
|
||||
@@ -174,33 +198,35 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
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) {
|
||||
|
||||
while (already_written < count)
|
||||
{
|
||||
int written_this_time;
|
||||
int to_write = min(bufsize - (pos % bufsize),
|
||||
count - already_written);
|
||||
|
||||
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_handle,
|
||||
pos, to_write, buf, &written_this_time) != 0) {
|
||||
pos, to_write, buf, &written_this_time) != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -208,7 +234,8 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
buf += written_this_time;
|
||||
already_written += written_this_time;
|
||||
|
||||
if (written_this_time < to_write) {
|
||||
if (written_this_time < to_write)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -218,8 +245,10 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
|
||||
file->f_pos = pos;
|
||||
|
||||
if (pos > inode->i_size) {
|
||||
if (pos > inode->i_size)
|
||||
{
|
||||
inode->i_size = pos;
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
}
|
||||
|
||||
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
@@ -234,7 +263,7 @@ static struct file_operations ncp_file_operations = {
|
||||
NULL, /* readdir - bad */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
ncp_mmap, /* mmap */
|
||||
NULL, /* open */
|
||||
NULL, /* release */
|
||||
ncp_fsync, /* fsync */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <linux/locks.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/malloc.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
extern int close_fp(struct file *filp);
|
||||
|
||||
@@ -46,7 +46,7 @@ static struct super_operations ncp_sops = {
|
||||
NULL, /* write superblock */
|
||||
ncp_statfs, /* stat filesystem */
|
||||
NULL
|
||||
};
|
||||
};
|
||||
|
||||
/* ncp_read_inode: Called from iget, it only traverses the allocated
|
||||
ncp_inode_info's and initializes the inode from the data found
|
||||
@@ -61,48 +61,29 @@ ncp_read_inode(struct inode *inode)
|
||||
inode->i_ino. Just to make sure everything went well, we
|
||||
check it's there. */
|
||||
|
||||
struct ncp_inode_info *inode_info
|
||||
= (struct ncp_inode_info *)(inode->i_ino);
|
||||
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
|
||||
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
||||
struct ncp_inode_info *check_info = root;
|
||||
if (inode_info == NULL)
|
||||
{
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (inode_info == check_info) {
|
||||
if (check_info->state == INODE_LOOKED_UP) {
|
||||
DDPRINTK("ncp_read_inode: found it!\n");
|
||||
goto good;
|
||||
}
|
||||
else {
|
||||
printk("ncp_read_inode: "
|
||||
"state != INODE_LOOKED_UP\n");
|
||||
goto good;
|
||||
}
|
||||
}
|
||||
check_info = check_info->next;
|
||||
} while (check_info != root);
|
||||
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
|
||||
good:
|
||||
DDPRINTK("ncp_read_inode: read entry %s\n",
|
||||
inode_info->finfo.i.entryName);
|
||||
#endif
|
||||
inode_info->state = INODE_VALID;
|
||||
inode_info->state = NCP_INODE_VALID;
|
||||
|
||||
NCP_INOP(inode) = inode_info;
|
||||
inode_info->inode = inode;
|
||||
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR) {
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR)
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
||||
/* for directories in dataStreamSize seems to be some
|
||||
/* for directories dataStreamSize seems to be some
|
||||
Object ID ??? */
|
||||
inode->i_size = 0;
|
||||
inode->i_size = 512;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
|
||||
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
|
||||
@@ -113,13 +94,18 @@ ncp_read_inode(struct inode *inode)
|
||||
inode->i_nlink = 1;
|
||||
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
||||
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
||||
inode->i_blksize = 1024;
|
||||
inode->i_blksize = 512;
|
||||
inode->i_rdev = 0;
|
||||
|
||||
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
||||
{
|
||||
inode->i_blocks =
|
||||
(inode->i_size - 1) / inode->i_blksize + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode->i_blocks = 0;
|
||||
}
|
||||
|
||||
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
|
||||
NCP_ISTRUCT(inode)->modifyDate);
|
||||
@@ -129,22 +115,30 @@ ncp_read_inode(struct inode *inode)
|
||||
NCP_ISTRUCT(inode)->lastAccessDate);
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
{
|
||||
inode->i_op = &ncp_file_inode_operations;
|
||||
}
|
||||
else if (S_ISDIR(inode->i_mode))
|
||||
{
|
||||
inode->i_op = &ncp_dir_inode_operations;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode->i_op = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_put_inode(struct inode *inode)
|
||||
{
|
||||
struct nw_file_info *finfo = NCP_FINFO(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
|
||||
if (finfo->opened != 0) {
|
||||
|
||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) {
|
||||
lock_super(sb);
|
||||
if (finfo->opened != 0)
|
||||
{
|
||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
|
||||
{
|
||||
/* We can't do anything but complain. */
|
||||
printk("ncp_put_inode: could not close\n");
|
||||
}
|
||||
@@ -152,16 +146,18 @@ ncp_put_inode(struct inode *inode)
|
||||
|
||||
DDPRINTK("ncp_put_inode: put %s\n",
|
||||
finfo->i.entryName);
|
||||
|
||||
|
||||
ncp_free_inode_info(NCP_INOP(inode));
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
{
|
||||
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||
inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode);
|
||||
}
|
||||
|
||||
clear_inode(inode);
|
||||
unlock_super(sb);
|
||||
}
|
||||
|
||||
struct super_block *
|
||||
@@ -174,22 +170,26 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
dev_t dev = sb->s_dev;
|
||||
int error;
|
||||
|
||||
if (!data) {
|
||||
if (data == NULL)
|
||||
{
|
||||
printk("ncp_read_super: missing data argument\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->version != NCP_MOUNT_VERSION) {
|
||||
if (data->version != NCP_MOUNT_VERSION)
|
||||
{
|
||||
printk("ncp warning: mount version %s than kernel\n",
|
||||
(data->version < NCP_MOUNT_VERSION) ?
|
||||
"older" : "newer");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if ( (data->ncp_fd >= NR_OPEN)
|
||||
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|
||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode))) {
|
||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
|
||||
{
|
||||
printk("ncp_read_super: invalid ncp socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
@@ -197,7 +197,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
if ( (data->wdog_fd >= NR_OPEN)
|
||||
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|
||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode))) {
|
||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
|
||||
{
|
||||
printk("ncp_read_super: invalid wdog socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
@@ -207,7 +208,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (server == NULL) {
|
||||
if (server == NULL)
|
||||
{
|
||||
printk("ncp_read_super: could not alloc ncp_server\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -231,6 +233,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server->wait = NULL;
|
||||
server->packet = NULL;
|
||||
server->buffer_size = 0;
|
||||
server->conn_status = 0;
|
||||
|
||||
server->m = *data;
|
||||
server->m.file_mode = (server->m.file_mode &
|
||||
@@ -241,7 +244,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server->packet_size = NCP_PACKET_SIZE;
|
||||
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
|
||||
|
||||
if (server->packet == NULL) {
|
||||
if (server->packet == NULL)
|
||||
{
|
||||
printk("ncpfs: could not alloc packet\n");
|
||||
error = -ENOMEM;
|
||||
unlock_super(sb);
|
||||
@@ -254,7 +258,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
* Make the connection to the server
|
||||
*/
|
||||
|
||||
if (ncp_catch_watchdog(server) != 0) {
|
||||
if (ncp_catch_watchdog(server) != 0)
|
||||
{
|
||||
printk("ncp_read_super: Could not catch watchdog\n");
|
||||
error = -EINVAL;
|
||||
unlock_super(sb);
|
||||
@@ -266,7 +271,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
ncp_unlock_server(server);
|
||||
unlock_super(sb);
|
||||
|
||||
if (error < 0) {
|
||||
if (error < 0)
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: Failed connection, bailing out "
|
||||
"(error = %d).\n", -error);
|
||||
@@ -277,14 +283,16 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
||||
|
||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
|
||||
if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: get root inode failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
|
||||
&(server->buffer_size)) != 0) {
|
||||
&(server->buffer_size)) != 0)
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: could not get bufsize\n");
|
||||
goto disconnect;
|
||||
@@ -292,14 +300,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
|
||||
|
||||
/* if (ncp_login_user(server, server->m.username,
|
||||
server->m.password) != 0) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: login failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
*/
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
return sb;
|
||||
|
||||
@@ -374,6 +374,11 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
int info_mask;
|
||||
struct nw_modify_dos_info info;
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||
return result;
|
||||
|
||||
@@ -393,43 +398,59 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
info_mask = 0;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if ((attr->ia_valid & ATTR_CTIME) != 0) {
|
||||
if ((attr->ia_valid & ATTR_CTIME) != 0)
|
||||
{
|
||||
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(info.creationTime), &(info.creationDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_MTIME) != 0) {
|
||||
if ((attr->ia_valid & ATTR_MTIME) != 0)
|
||||
{
|
||||
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
|
||||
ncp_date_unix2dos(attr->ia_mtime,
|
||||
&(info.modifyTime), &(info.modifyDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_ATIME) != 0) {
|
||||
if ((attr->ia_valid & ATTR_ATIME) != 0)
|
||||
{
|
||||
__u16 dummy;
|
||||
info_mask |= (DM_LAST_ACCESS_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(dummy), &(info.lastAccessDate));
|
||||
}
|
||||
|
||||
if (info_mask != 0) {
|
||||
if (info_mask != 0)
|
||||
{
|
||||
if ((result =
|
||||
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
||||
NCP_ISTRUCT(inode),
|
||||
info_mask,
|
||||
&info)) != 0) {
|
||||
&info)) != 0)
|
||||
{
|
||||
result = -EACCES;
|
||||
|
||||
if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
|
||||
{
|
||||
/* NetWare seems not to allow this. I
|
||||
do not know why. So, just tell the
|
||||
user everything went fine. This is
|
||||
a terrible hack, but I do not know
|
||||
how to do this correctly. */
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
||||
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0)
|
||||
{
|
||||
int written;
|
||||
|
||||
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
||||
NCP_ISTRUCT(inode)->entryName, attr->ia_size);
|
||||
|
||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
|
||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
@@ -445,7 +466,7 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
result = 0;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -475,6 +496,7 @@ init_module( void)
|
||||
|
||||
ncp_init_dir_cache();
|
||||
register_filesystem(&ncp_fs_type);
|
||||
printk("ncpfs version %s loaded\n", NCPFS_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define MOD_INC_USE_COUNT
|
||||
#define MOD_DEC_USE_COUNT
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
@@ -29,17 +26,41 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
{
|
||||
int result;
|
||||
struct ncp_ioctl_request request;
|
||||
struct ncp_server *server;
|
||||
struct ncp_fs_info info;
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
|
||||
/*
|
||||
* Binary compatible with 1.3.XX releases.
|
||||
* Take this out in 2.1.0 development series.
|
||||
* <mec@duracef.shout.net> 12 Mar 1996
|
||||
*/
|
||||
switch(cmd) {
|
||||
case _IOR('n', 1, unsigned char *):
|
||||
cmd = NCP_IOC_NCPREQUEST;
|
||||
break;
|
||||
case _IOR('u', 1, uid_t):
|
||||
cmd = NCP_IOC_GETMOUNTUID;
|
||||
break;
|
||||
case _IO('l', 1):
|
||||
cmd = NCP_IOC_CONN_LOGGED_IN;
|
||||
break;
|
||||
case _IOWR('i', 1, unsigned char *):
|
||||
cmd = NCP_IOC_GET_FS_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case NCP_IOC_NCPREQUEST:
|
||||
|
||||
if (!suser()) {
|
||||
return -EPERM;
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
||||
sizeof(request))) != 0) {
|
||||
sizeof(request))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -48,45 +69,93 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
|
||||
if ( (request.function > 255)
|
||||
|| (request.size >
|
||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
|
||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
||||
NCP_PACKET_SIZE)) != 0) {
|
||||
NCP_PACKET_SIZE)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
server = NCP_SERVER(inode);
|
||||
ncp_lock_server(server);
|
||||
|
||||
/* FIXME: We hack around in the server's structures
|
||||
here to be able to use ncp_request */
|
||||
|
||||
server->has_subfunction = 0;
|
||||
server->current_size =
|
||||
request.size + sizeof(struct ncp_request_header);
|
||||
memcpy_fromfs(server->packet, request.data,
|
||||
request.size+sizeof(struct ncp_request_header));
|
||||
server->current_size = request.size;
|
||||
memcpy_fromfs(server->packet, request.data, request.size);
|
||||
|
||||
|
||||
ncp_request(server, request.function);
|
||||
|
||||
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
||||
server->reply_size);
|
||||
memcpy_tofs(request.data, server->packet,
|
||||
server->reply_size);
|
||||
memcpy_tofs(request.data, server->packet, server->reply_size);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
|
||||
return server->reply_size;
|
||||
|
||||
case NCP_IOC_CONN_LOGGED_IN:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return ncp_conn_logged_in(server);
|
||||
|
||||
case NCP_IOC_GET_FS_INFO:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)arg,
|
||||
sizeof(info))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy_fromfs(&info, (struct ncp_fs_info *)arg,
|
||||
sizeof(info));
|
||||
|
||||
if (info.version != NCP_GET_FS_INFO_VERSION)
|
||||
{
|
||||
DPRINTK("info.version invalid: %d\n", info.version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info.addr = server->m.serv_addr;
|
||||
info.mounted_uid = server->m.mounted_uid;
|
||||
info.connection = server->connection;
|
||||
info.buffer_size = server->buffer_size;
|
||||
info.volume_number = NCP_ISTRUCT(inode)->volNumber;
|
||||
info.directory_id = NCP_ISTRUCT(inode)->DosDirNum;
|
||||
|
||||
memcpy_tofs((struct ncp_fs_info *)arg, &info, sizeof(info));
|
||||
return 0;
|
||||
|
||||
case NCP_IOC_GETMOUNTUID:
|
||||
|
||||
if ( (permission(inode, MAY_READ) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
||||
sizeof(uid_t))) != 0) {
|
||||
sizeof(uid_t))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
|
||||
put_fs_word(server->m.mounted_uid, (uid_t*) arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
||||
157
kernel-1.2/src/mmap.c
Normal file
157
kernel-1.2/src/mmap.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* mmap.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <linux/stat.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
|
||||
#include "ncplib_kernel.h"
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the supplied page for mmap
|
||||
*/
|
||||
static unsigned long
|
||||
ncp_file_mmap_nopage(struct vm_area_struct * area,
|
||||
unsigned long address, unsigned long page, int no_share)
|
||||
{
|
||||
struct inode * inode = area->vm_inode;
|
||||
unsigned int clear;
|
||||
unsigned long tmp;
|
||||
int bufsize;
|
||||
int pos;
|
||||
unsigned short fs;
|
||||
|
||||
address &= PAGE_MASK;
|
||||
pos = address - area->vm_start + area->vm_offset;
|
||||
|
||||
clear = 0;
|
||||
if (address + PAGE_SIZE > area->vm_end)
|
||||
{
|
||||
clear = address + PAGE_SIZE - area->vm_end;
|
||||
}
|
||||
|
||||
/* what we can read in one go */
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
if (ncp_make_open(inode, O_RDONLY) < 0)
|
||||
{
|
||||
clear = PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int already_read = 0;
|
||||
int count = PAGE_SIZE - clear;
|
||||
int to_read;
|
||||
|
||||
while (already_read < count)
|
||||
{
|
||||
int read_this_time;
|
||||
|
||||
if ((pos % bufsize) != 0)
|
||||
{
|
||||
to_read = bufsize - (pos % bufsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_read = bufsize;
|
||||
}
|
||||
|
||||
to_read = min(to_read, count - already_read);
|
||||
|
||||
if (ncp_read(NCP_SERVER(inode),
|
||||
NCP_FINFO(inode)->file_handle,
|
||||
pos, to_read,
|
||||
(char *)(page + already_read),
|
||||
&read_this_time) != 0)
|
||||
{
|
||||
read_this_time = 0;
|
||||
}
|
||||
|
||||
pos += read_this_time;
|
||||
already_read += read_this_time;
|
||||
|
||||
if (read_this_time < to_read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_fs(fs);
|
||||
|
||||
tmp = page + PAGE_SIZE;
|
||||
while (clear--) {
|
||||
*(char *)--tmp = 0;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
struct vm_operations_struct ncp_file_mmap = {
|
||||
NULL, /* open */
|
||||
NULL, /* close */
|
||||
NULL, /* unmap */
|
||||
NULL, /* protect */
|
||||
NULL, /* sync */
|
||||
NULL, /* advise */
|
||||
ncp_file_mmap_nopage, /* nopage */
|
||||
NULL, /* wppage */
|
||||
NULL, /* swapout */
|
||||
NULL, /* swapin */
|
||||
};
|
||||
|
||||
|
||||
/* This is used for a general mmap of a ncp file */
|
||||
int
|
||||
ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
|
||||
{
|
||||
DPRINTK("ncp_mmap: called\n");
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* only PAGE_COW or read-only supported now */
|
||||
if (vma->vm_flags & VM_SHARED)
|
||||
return -EINVAL;
|
||||
if (!inode->i_sb || !S_ISREG(inode->i_mode))
|
||||
return -EACCES;
|
||||
if (!IS_RDONLY(inode)) {
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
inode->i_dirt = 1;
|
||||
}
|
||||
|
||||
vma->vm_inode = inode;
|
||||
inode->i_count++;
|
||||
vma->vm_ops = &ncp_file_mmap;
|
||||
return 0;
|
||||
}
|
||||
@@ -2,23 +2,24 @@
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define MOD_INC_USE_COUNT
|
||||
#define MOD_DEC_USE_COUNT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
typedef __u8 byte;
|
||||
typedef __u16 word;
|
||||
typedef __u32 dword;
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
static void
|
||||
assert_server_locked(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
if (server->lock == 0)
|
||||
{
|
||||
DPRINTK("ncpfs: server not locked!\n");
|
||||
}
|
||||
}
|
||||
@@ -73,7 +74,8 @@ ncp_add_pstring(struct ncp_server *server, const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
assert_server_locked(server);
|
||||
if (len > 255) {
|
||||
if (len > 255)
|
||||
{
|
||||
DPRINTK("ncpfs: string too long: %s\n", s);
|
||||
len = 255;
|
||||
}
|
||||
@@ -128,14 +130,15 @@ ncp_reply_dword(struct ncp_server *server, int offset)
|
||||
|
||||
int
|
||||
ncp_negotiate_buffersize(struct ncp_server *server,
|
||||
int size, int *target) {
|
||||
|
||||
int size, int *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_word(server, htons(size));
|
||||
|
||||
if ((result = ncp_request(server, 33)) != 0) {
|
||||
if ((result = ncp_request(server, 33)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -156,7 +159,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
ncp_init_request_s(server, 44);
|
||||
ncp_add_byte(server, n);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
if ((result = ncp_request(server, 22)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -172,7 +176,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
||||
|
||||
len = ncp_reply_byte(server, 29);
|
||||
if (len > NCP_VOLNAME_LEN) {
|
||||
if (len > NCP_VOLNAME_LEN)
|
||||
{
|
||||
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
||||
ncp_unlock_server(server);
|
||||
return -EIO;
|
||||
@@ -191,7 +196,8 @@ ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
|
||||
ncp_init_request_s(server, 5);
|
||||
ncp_add_pstring(server, name);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
if ((result = ncp_request(server, 22)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -210,7 +216,8 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
|
||||
ncp_add_byte(server, 0);
|
||||
ncp_add_mem(server, file_id, 6);
|
||||
|
||||
if ((result = ncp_request(server, 66)) != 0) {
|
||||
if ((result = ncp_request(server, 66)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -227,12 +234,16 @@ ncp_add_handle_path(struct ncp_server *server,
|
||||
{
|
||||
ncp_add_byte(server, vol_num);
|
||||
ncp_add_dword(server, dir_base);
|
||||
if (have_dir_base != 0) {
|
||||
if (have_dir_base != 0)
|
||||
{
|
||||
ncp_add_byte(server, 1); /* dir_base */
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ncp_add_byte(server, 0xff); /* no handle */
|
||||
}
|
||||
if (path != NULL) {
|
||||
if (path != NULL)
|
||||
{
|
||||
ncp_add_byte(server, 1); /* 1 component */
|
||||
ncp_add_pstring(server, path);
|
||||
}
|
||||
@@ -255,52 +266,18 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
||||
target->entryName[*name_len] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target)
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
int result;
|
||||
char *volname = NULL;
|
||||
|
||||
if (target == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir == NULL) {
|
||||
|
||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
||||
|
||||
/* Access a volume's root directory */
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte (server, 8);
|
||||
ncp_unlock_server(server);
|
||||
volname = path;
|
||||
path = NULL;
|
||||
}
|
||||
else
|
||||
if (target == NULL)
|
||||
{
|
||||
vol_num = dir->volNumber;
|
||||
dir_base = dir->DosDirNum;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
@@ -309,22 +286,63 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
||||
ncp_add_word(server, 0xff); /* get all */
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
||||
path);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (volname != NULL) {
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
int result;
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
|
||||
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
||||
ncp_add_byte(server, 0); /* DOS name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
|
||||
ncp_add_byte(server, 0); /* faked volume number */
|
||||
ncp_add_dword(server, 0); /* faked dir_base */
|
||||
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
||||
ncp_add_byte(server, 1); /* 1 path component */
|
||||
ncp_add_pstring(server, volname);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte(server, 8);
|
||||
ncp_unlock_server(server);
|
||||
|
||||
if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
|
||||
target)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
|
||||
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -347,7 +365,8 @@ ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, file->volNumber,
|
||||
file->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -370,7 +389,8 @@ ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -399,28 +419,38 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_file_info *target)
|
||||
{
|
||||
int result;
|
||||
__u16 search_attribs = 0x0006;
|
||||
|
||||
if ((create_attributes & aDIR) != 0)
|
||||
{
|
||||
search_attribs |= 0x8000;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 1); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, open_create_mode);
|
||||
ncp_add_word(server, 0x8006);
|
||||
ncp_add_word(server, search_attribs);
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_dword(server, create_attributes);
|
||||
/* The desired acc rights seem to be the inherited rights mask
|
||||
for directories */
|
||||
ncp_add_word(server, desired_acc_rights);
|
||||
|
||||
if (dir != NULL) {
|
||||
if (dir != NULL)
|
||||
{
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ncp_add_handle_path(server,
|
||||
target->i.volNumber, target->i.DosDirNum,
|
||||
1, NULL);
|
||||
}
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -429,7 +459,8 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
target->server_file_handle = ncp_reply_dword(server, 0);
|
||||
target->open_create_action = ncp_reply_byte(server, 4);
|
||||
|
||||
if (dir != NULL) {
|
||||
if (dir != NULL)
|
||||
{
|
||||
/* in target there's a new finfo to fill */
|
||||
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
|
||||
}
|
||||
@@ -454,7 +485,8 @@ ncp_initialize_search(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -484,7 +516,8 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
||||
ncp_add_byte(server, '*');
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -550,14 +583,15 @@ ncp_read(struct ncp_server *server, const char *file_id,
|
||||
ncp_add_dword(server, htonl(offset));
|
||||
ncp_add_word(server, htons(to_read));
|
||||
|
||||
if ((result = ncp_request(server, 72)) != 0) {
|
||||
if ((result = ncp_request(server, 72)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
||||
|
||||
memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read);
|
||||
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
@@ -577,7 +611,8 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
||||
ncp_add_word(server, htons(to_write));
|
||||
ncp_add_mem_fromfs(server, source, to_write);
|
||||
|
||||
if ((result = ncp_request(server, 73)) != 0) {
|
||||
if ((result = ncp_request(server, 73)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -114,10 +114,16 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
||||
const char *source, int *bytes_written);
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
@@ -11,9 +11,6 @@
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define MOD_INC_USE_COUNT
|
||||
#define MOD_DEC_USE_COUNT
|
||||
#endif
|
||||
|
||||
#include <linux/sched.h>
|
||||
@@ -69,7 +66,9 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
printk("ncpfs: got strange packet on watchdog "
|
||||
"socket\n");
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int result;
|
||||
DDPRINTK("ncpfs: got watchdog from:\n");
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
||||
@@ -104,8 +103,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
|| (!S_ISSOCK(inode->i_mode)))
|
||||
{
|
||||
printk("ncp_catch_watchdog: did not get valid server!\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -113,7 +112,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
if (sock->type != SOCK_DGRAM)
|
||||
{
|
||||
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -121,7 +121,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
if (sk == NULL)
|
||||
{
|
||||
printk("ncp_catch_watchdog: sk == NULL");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -131,7 +132,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
(unsigned int)(sk->data_ready),
|
||||
(unsigned int)(server->data_ready));
|
||||
|
||||
if (sk->data_ready == ncp_wdog_data_ready) {
|
||||
if (sk->data_ready == ncp_wdog_data_ready)
|
||||
{
|
||||
printk("ncp_catch_watchdog: already done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -152,8 +154,8 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
|| (!S_ISSOCK(inode->i_mode)))
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"did not get valid server!\n");
|
||||
return -EINVAL;
|
||||
@@ -161,25 +163,29 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
if (sock->type != SOCK_DGRAM)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
if (sk == NULL)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: sk == NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (server->data_ready == NULL) {
|
||||
if (server->data_ready == NULL)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"server->data_ready == NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sk->data_ready != ncp_wdog_data_ready) {
|
||||
if (sk->data_ready != ncp_wdog_data_ready)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"sk->data_callback != ncp_data_callback\n");
|
||||
return -EINVAL;
|
||||
@@ -216,7 +222,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
int timeout;
|
||||
int retrans;
|
||||
int major_timeout_seen;
|
||||
char *server_name;
|
||||
int acknowledge_seen;
|
||||
int n;
|
||||
int addrlen;
|
||||
unsigned long old_mask;
|
||||
@@ -232,15 +238,16 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
inode = file->f_inode;
|
||||
select = file->f_op->select;
|
||||
sock = &inode->u.socket_i;
|
||||
if (!sock) {
|
||||
if (!sock)
|
||||
{
|
||||
printk("ncp_rpc_call: socki_lookup failed\n");
|
||||
return -EBADF;
|
||||
}
|
||||
init_timeout = server->m.time_out;
|
||||
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
|
||||
max_timeout = NCP_MAX_RPC_TIMEOUT;
|
||||
acknowledge_seen = 0;
|
||||
retrans = server->m.retry_count;
|
||||
major_timeout_seen = 0;
|
||||
server_name = server->m.server_name;
|
||||
old_mask = current->blocked;
|
||||
current->blocked |= ~(_S(SIGKILL)
|
||||
#if 0
|
||||
@@ -254,7 +261,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
: 0));
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
|
||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
|
||||
{
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
htonl(server->m.serv_addr.sipx_network),
|
||||
server->m.serv_addr.sipx_node[0],
|
||||
@@ -276,7 +284,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
(struct sockaddr *)
|
||||
&(server->m.serv_addr),
|
||||
sizeof(server->m.serv_addr));
|
||||
if (result < 0) {
|
||||
if (result < 0)
|
||||
{
|
||||
printk("ncp_rpc_call: send error = %d\n", result);
|
||||
break;
|
||||
}
|
||||
@@ -285,39 +294,45 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
wait_table.entry = &entry;
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if ( !select(inode, file, SEL_IN, &wait_table)
|
||||
&& !select(inode, file, SEL_IN, NULL)) {
|
||||
if (timeout > max_timeout) {
|
||||
/* JEJB/JSP 2/7/94
|
||||
* This is useful to see if the system is
|
||||
* hanging */
|
||||
printk("NCP max timeout reached on %s\n",
|
||||
server_name);
|
||||
timeout = max_timeout;
|
||||
&& !select(inode, file, SEL_IN, NULL))
|
||||
{
|
||||
if (timeout > max_timeout)
|
||||
{
|
||||
/* JEJB/JSP 2/7/94
|
||||
* This is useful to see if the system is
|
||||
* hanging */
|
||||
if (acknowledge_seen == 0)
|
||||
{
|
||||
printk("NCP max timeout reached\n");
|
||||
}
|
||||
timeout = max_timeout;
|
||||
}
|
||||
current->timeout = jiffies + timeout;
|
||||
schedule();
|
||||
remove_wait_queue(entry.wait_address, &entry.wait);
|
||||
current->state = TASK_RUNNING;
|
||||
if (current->signal & ~current->blocked) {
|
||||
if (current->signal & ~current->blocked)
|
||||
{
|
||||
current->timeout = 0;
|
||||
result = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (!current->timeout) {
|
||||
if (!current->timeout)
|
||||
{
|
||||
if (n < retrans)
|
||||
continue;
|
||||
if (server->m.flags & NCP_MOUNT_SOFT) {
|
||||
printk("NCP server %s not responding, "
|
||||
"timed out\n", server_name);
|
||||
if (server->m.flags & NCP_MOUNT_SOFT)
|
||||
{
|
||||
printk("NCP server not responding\n");
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
n = 0;
|
||||
timeout = init_timeout;
|
||||
init_timeout <<= 1;
|
||||
if (!major_timeout_seen) {
|
||||
printk("NCP server %s not responding, "
|
||||
"still trying\n", server_name);
|
||||
if (!major_timeout_seen)
|
||||
{
|
||||
printk("NCP server not responding\n");
|
||||
}
|
||||
major_timeout_seen = 1;
|
||||
continue;
|
||||
@@ -336,28 +351,36 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
result = sock->ops->recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, MSG_PEEK,
|
||||
NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
if (result == -EAGAIN) {
|
||||
if (result < 0)
|
||||
{
|
||||
if (result == -EAGAIN)
|
||||
{
|
||||
DPRINTK("ncp_rpc_call: bad select ready\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result == -ECONNREFUSED) {
|
||||
if (result == -ECONNREFUSED)
|
||||
{
|
||||
DPRINTK("ncp_rpc_call: server playing coy\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result != -ERESTARTSYS) {
|
||||
if (result != -ERESTARTSYS)
|
||||
{
|
||||
printk("ncp_rpc_call: recv error = %d\n",
|
||||
-result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( (result == sizeof(reply))
|
||||
&& (reply.type == NCP_POSITIVE_ACK)) {
|
||||
&& (reply.type == NCP_POSITIVE_ACK))
|
||||
{
|
||||
/* Throw away the packet */
|
||||
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
|
||||
sock->ops->recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
n = 0;
|
||||
timeout = max_timeout;
|
||||
acknowledge_seen = 1;
|
||||
goto re_select;
|
||||
}
|
||||
|
||||
@@ -374,9 +397,10 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
|| ( (reply.sequence == request.sequence)
|
||||
&& (reply.conn_low == request.conn_low)
|
||||
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
|
||||
&& (reply.conn_high == request.conn_high)))) {
|
||||
&& (reply.conn_high == request.conn_high))))
|
||||
{
|
||||
if (major_timeout_seen)
|
||||
printk("NCP server %s OK\n", server_name);
|
||||
printk("NCP server OK\n");
|
||||
break;
|
||||
}
|
||||
/* JEJB/JSP 2/7/94
|
||||
@@ -385,9 +409,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
* a null buffer yet. */
|
||||
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
#if 1
|
||||
printk("ncp_rpc_call: reply mismatch\n");
|
||||
#endif
|
||||
|
||||
DPRINTK("ncp_rpc_call: reply mismatch\n");
|
||||
goto re_select;
|
||||
}
|
||||
/*
|
||||
@@ -396,9 +419,12 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
*/
|
||||
result = sock->ops->recvfrom(sock, (void *)start, server->packet_size,
|
||||
1, 0, NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
if (result < 0)
|
||||
{
|
||||
printk("NCP: notice message: result=%d\n", result);
|
||||
} else if (result < sizeof(struct ncp_reply_header)) {
|
||||
}
|
||||
else if (result < sizeof(struct ncp_reply_header))
|
||||
{
|
||||
printk("NCP: just caught a too small read memory size..., "
|
||||
"email to NET channel\n");
|
||||
printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
|
||||
@@ -418,7 +444,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
static int
|
||||
ncp_do_request(struct ncp_server *server, int size)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
if (server->lock == 0)
|
||||
{
|
||||
printk("ncpfs: Server not locked!\n");
|
||||
return -EIO;
|
||||
}
|
||||
@@ -442,7 +469,8 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
int result;
|
||||
|
||||
if (server->has_subfunction != 0) {
|
||||
if (server->has_subfunction != 0)
|
||||
{
|
||||
*(__u16 *)&(h->data[0]) = request_size - 2;
|
||||
}
|
||||
|
||||
@@ -455,7 +483,8 @@ ncp_request(struct ncp_server *server, int function)
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = function;
|
||||
|
||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) {
|
||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
|
||||
{
|
||||
DPRINTK("ncp_request_error: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
@@ -467,8 +496,9 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
result = reply->completion_code;
|
||||
|
||||
if (result != 0) {
|
||||
DPRINTK("ncp_completion_code: %d\n", result);
|
||||
if (result != 0)
|
||||
{
|
||||
DPRINTK("ncp_completion_code: %x\n", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -489,7 +519,8 @@ ncp_connect(struct ncp_server *server)
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = 0;
|
||||
|
||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0) {
|
||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -519,9 +550,10 @@ ncp_disconnect(struct ncp_server *server)
|
||||
void
|
||||
ncp_lock_server(struct ncp_server *server)
|
||||
{
|
||||
#if 1
|
||||
#if 0
|
||||
/* For testing, only 1 process */
|
||||
if (server->lock != 0) {
|
||||
if (server->lock != 0)
|
||||
{
|
||||
DPRINTK("ncpfs: server locked!!!\n");
|
||||
}
|
||||
#endif
|
||||
@@ -533,7 +565,8 @@ ncp_lock_server(struct ncp_server *server)
|
||||
void
|
||||
ncp_unlock_server(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock != 1) {
|
||||
if (server->lock != 1)
|
||||
{
|
||||
printk("ncp_unlock_server: was not locked!\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
/*
|
||||
* ncp_fs.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_NCP_H
|
||||
#define _LINUX_NCP_H
|
||||
|
||||
#error "Please use kernel 1.2.13"
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define NCP_PTYPE (0x11)
|
||||
#define NCP_PORT (0x0451)
|
||||
|
||||
#define NCP_ALLOC_SLOT_REQUEST (0x1111)
|
||||
#define NCP_REQUEST (0x2222)
|
||||
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
||||
|
||||
struct ncp_request_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 function __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_REPLY (0x3333)
|
||||
#define NCP_POSITIVE_ACK (0x9999)
|
||||
|
||||
struct ncp_reply_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 completion_code __attribute__ ((packed));
|
||||
__u8 connection_state __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
#define NCP_BINDERY_USER (0x0001)
|
||||
#define NCP_BINDERY_UGROUP (0x0002)
|
||||
#define NCP_BINDERY_PQUEUE (0x0003)
|
||||
#define NCP_BINDERY_FSERVER (0x0004)
|
||||
#define NCP_BINDERY_NAME_LEN (48)
|
||||
struct ncp_bindery_object {
|
||||
__u32 object_id;
|
||||
__u16 object_type;
|
||||
__u8 object_name[NCP_BINDERY_NAME_LEN];
|
||||
};
|
||||
|
||||
struct nw_property {
|
||||
__u8 value[128];
|
||||
__u8 more_flag;
|
||||
__u8 property_flag;
|
||||
};
|
||||
|
||||
|
||||
#define NCP_VOLNAME_LEN (16)
|
||||
#define NCP_NUMBER_OF_VOLUMES (64)
|
||||
struct ncp_volume_info {
|
||||
__u32 total_blocks;
|
||||
__u32 free_blocks;
|
||||
__u32 purgeable_blocks;
|
||||
__u32 not_yet_purgeable_blocks;
|
||||
__u32 total_dir_entries;
|
||||
__u32 available_dir_entries;
|
||||
__u8 sectors_per_block;
|
||||
char volume_name[NCP_VOLNAME_LEN+1];
|
||||
};
|
||||
|
||||
struct ncp_filesearch_info {
|
||||
__u8 volume_number;
|
||||
__u16 directory_id;
|
||||
__u16 sequence_no;
|
||||
__u8 access_rights;
|
||||
};
|
||||
|
||||
#define NCP_MAX_FILENAME 14
|
||||
|
||||
/* these define the attribute byte as seen by NCP */
|
||||
#define aRONLY (1L<<0)
|
||||
#define aHIDDEN (1L<<1)
|
||||
#define aSYSTEM (1L<<2)
|
||||
#define aEXECUTE (1L<<3)
|
||||
#define aDIR (1L<<4)
|
||||
#define aARCH (1L<<5)
|
||||
|
||||
#define AR_READ (0x01)
|
||||
#define AR_WRITE (0x02)
|
||||
#define AR_EXCLUSIVE (0x20)
|
||||
|
||||
#define NCP_FILE_ID_LEN 6
|
||||
struct ncp_file_info {
|
||||
__u8 file_id[NCP_FILE_ID_LEN];
|
||||
char file_name[NCP_MAX_FILENAME+1];
|
||||
__u8 file_attributes;
|
||||
__u8 file_mode;
|
||||
__u32 file_length;
|
||||
__u16 creation_date;
|
||||
__u16 access_date;
|
||||
__u16 update_date;
|
||||
__u16 update_time;
|
||||
};
|
||||
|
||||
|
||||
/* Defines for ReturnInformationMask */
|
||||
#define RIM_NAME (0x0001L)
|
||||
#define RIM_SPACE_ALLOCATED (0x0002L)
|
||||
#define RIM_ATTRIBUTES (0x0004L)
|
||||
#define RIM_DATA_SIZE (0x0008L)
|
||||
#define RIM_TOTAL_SIZE (0x0010L)
|
||||
#define RIM_EXT_ATTR_INFO (0x0020L)
|
||||
#define RIM_ARCHIVE (0x0040L)
|
||||
#define RIM_MODIFY (0x0080L)
|
||||
#define RIM_CREATION (0x0100L)
|
||||
#define RIM_OWNING_NAMESPACE (0x0200L)
|
||||
#define RIM_DIRECTORY (0x0400L)
|
||||
#define RIM_RIGHTS (0x0800L)
|
||||
#define RIM_ALL (0x0FFFL)
|
||||
#define RIM_COMPRESSED_INFO (0x80000000L)
|
||||
|
||||
/* open/create modes */
|
||||
#define OC_MODE_OPEN 0x01
|
||||
#define OC_MODE_TRUNCATE 0x02
|
||||
#define OC_MODE_REPLACE 0x02
|
||||
#define OC_MODE_CREATE 0x08
|
||||
|
||||
/* open/create results */
|
||||
#define OC_ACTION_NONE 0x00
|
||||
#define OC_ACTION_OPEN 0x01
|
||||
#define OC_ACTION_CREATE 0x02
|
||||
#define OC_ACTION_TRUNCATE 0x04
|
||||
#define OC_ACTION_REPLACE 0x04
|
||||
|
||||
/* access rights attributes */
|
||||
#ifndef AR_READ_ONLY
|
||||
#define AR_READ_ONLY 0x0001
|
||||
#define AR_WRITE_ONLY 0x0002
|
||||
#define AR_DENY_READ 0x0004
|
||||
#define AR_DENY_WRITE 0x0008
|
||||
#define AR_COMPATIBILITY 0x0010
|
||||
#define AR_WRITE_THROUGH 0x0040
|
||||
#define AR_OPEN_COMPRESSED 0x0100
|
||||
#endif
|
||||
|
||||
struct nw_info_struct
|
||||
{
|
||||
__u32 spaceAlloc __attribute__ ((packed));
|
||||
__u32 attributes __attribute__ ((packed));
|
||||
__u16 flags __attribute__ ((packed));
|
||||
__u32 dataStreamSize __attribute__ ((packed));
|
||||
__u32 totalStreamSize __attribute__ ((packed));
|
||||
__u16 numberOfStreams __attribute__ ((packed));
|
||||
__u16 creationTime __attribute__ ((packed));
|
||||
__u16 creationDate __attribute__ ((packed));
|
||||
__u32 creatorID __attribute__ ((packed));
|
||||
__u16 modifyTime __attribute__ ((packed));
|
||||
__u16 modifyDate __attribute__ ((packed));
|
||||
__u32 modifierID __attribute__ ((packed));
|
||||
__u16 lastAccessDate __attribute__ ((packed));
|
||||
__u16 archiveTime __attribute__ ((packed));
|
||||
__u16 archiveDate __attribute__ ((packed));
|
||||
__u32 archiverID __attribute__ ((packed));
|
||||
__u16 inheritedRightsMask __attribute__ ((packed));
|
||||
__u32 dirEntNum __attribute__ ((packed));
|
||||
__u32 DosDirNum __attribute__ ((packed));
|
||||
__u32 volNumber __attribute__ ((packed));
|
||||
__u32 EADataSize __attribute__ ((packed));
|
||||
__u32 EAKeyCount __attribute__ ((packed));
|
||||
__u32 EAKeySize __attribute__ ((packed));
|
||||
__u32 NSCreator __attribute__ ((packed));
|
||||
__u8 nameLen __attribute__ ((packed));
|
||||
__u8 entryName[256] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
/* modify mask - use with MODIFY_DOS_INFO structure */
|
||||
#define DM_ATTRIBUTES (0x0002L)
|
||||
#define DM_CREATE_DATE (0x0004L)
|
||||
#define DM_CREATE_TIME (0x0008L)
|
||||
#define DM_CREATOR_ID (0x0010L)
|
||||
#define DM_ARCHIVE_DATE (0x0020L)
|
||||
#define DM_ARCHIVE_TIME (0x0040L)
|
||||
#define DM_ARCHIVER_ID (0x0080L)
|
||||
#define DM_MODIFY_DATE (0x0100L)
|
||||
#define DM_MODIFY_TIME (0x0200L)
|
||||
#define DM_MODIFIER_ID (0x0400L)
|
||||
#define DM_LAST_ACCESS_DATE (0x0800L)
|
||||
#define DM_INHERITED_RIGHTS_MASK (0x1000L)
|
||||
#define DM_MAXIMUM_SPACE (0x2000L)
|
||||
|
||||
struct nw_modify_dos_info
|
||||
{
|
||||
__u32 attributes __attribute__ ((packed));
|
||||
__u16 creationDate __attribute__ ((packed));
|
||||
__u16 creationTime __attribute__ ((packed));
|
||||
__u32 creatorID __attribute__ ((packed));
|
||||
__u16 modifyDate __attribute__ ((packed));
|
||||
__u16 modifyTime __attribute__ ((packed));
|
||||
__u32 modifierID __attribute__ ((packed));
|
||||
__u16 archiveDate __attribute__ ((packed));
|
||||
__u16 archiveTime __attribute__ ((packed));
|
||||
__u32 archiverID __attribute__ ((packed));
|
||||
__u16 lastAccessDate __attribute__ ((packed));
|
||||
__u16 inheritanceGrantMask __attribute__ ((packed));
|
||||
__u16 inheritanceRevokeMask __attribute__ ((packed));
|
||||
__u32 maximumSpace __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct nw_file_info {
|
||||
struct nw_info_struct i;
|
||||
int opened;
|
||||
int access;
|
||||
__u32 server_file_handle __attribute__ ((packed));
|
||||
__u8 open_create_action __attribute__ ((packed));
|
||||
__u8 file_handle[6] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct nw_search_sequence {
|
||||
__u8 volNumber __attribute__ ((packed));
|
||||
__u32 dirBase __attribute__ ((packed));
|
||||
__u32 sequence __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct nw_queue_job_entry {
|
||||
__u16 InUse __attribute__ ((packed));
|
||||
__u32 prev __attribute__ ((packed));
|
||||
__u32 next __attribute__ ((packed));
|
||||
__u32 ClientStation __attribute__ ((packed));
|
||||
__u32 ClientTask __attribute__ ((packed));
|
||||
__u32 ClientObjectID __attribute__ ((packed));
|
||||
__u32 TargetServerID __attribute__ ((packed));
|
||||
__u8 TargetExecTime[6] __attribute__ ((packed));
|
||||
__u8 JobEntryTime[6] __attribute__ ((packed));
|
||||
__u32 JobNumber __attribute__ ((packed));
|
||||
__u16 JobType __attribute__ ((packed));
|
||||
__u16 JobPosition __attribute__ ((packed));
|
||||
__u16 JobControlFlags __attribute__ ((packed));
|
||||
__u8 FileNameLen __attribute__ ((packed));
|
||||
char JobFileName[13] __attribute__ ((packed));
|
||||
__u32 JobFileHandle __attribute__ ((packed));
|
||||
__u32 ServerStation __attribute__ ((packed));
|
||||
__u32 ServerTaskNumber __attribute__ ((packed));
|
||||
__u32 ServerObjectID __attribute__ ((packed));
|
||||
char JobTextDescription[50] __attribute__ ((packed));
|
||||
char ClientRecordArea[152] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct queue_job {
|
||||
struct nw_queue_job_entry j;
|
||||
__u8 file_handle[6];
|
||||
};
|
||||
|
||||
#define QJE_OPER_HOLD 0x80
|
||||
#define QJE_USER_HOLD 0x40
|
||||
#define QJE_ENTRYOPEN 0x20
|
||||
#define QJE_SERV_RESTART 0x10
|
||||
#define QJE_SERV_AUTO 0x08
|
||||
|
||||
/* ClientRecordArea for print jobs */
|
||||
|
||||
struct print_job_record {
|
||||
__u8 Version __attribute__ ((packed));
|
||||
__u16 TabSize __attribute__ ((packed));
|
||||
__u16 Copies __attribute__ ((packed));
|
||||
__u8 CtrlFlags __attribute__ ((packed));
|
||||
__u16 Lines __attribute__ ((packed));
|
||||
__u16 Rows __attribute__ ((packed));
|
||||
char FormName[16] __attribute__ ((packed));
|
||||
__u8 Reserved[6] __attribute__ ((packed));
|
||||
char Banner[13] __attribute__ ((packed));
|
||||
char FnameBanner[13] __attribute__ ((packed));
|
||||
char FnameHeader[14] __attribute__ ((packed));
|
||||
char Path[80] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
#endif /* _LINUX_NCP_H */
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* ncp_fs.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_NCP_FS_H
|
||||
#define _LINUX_NCP_FS_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/ncp_mount.h>
|
||||
#include <linux/ncp_fs_sb.h>
|
||||
#include <linux/ncp_fs_i.h>
|
||||
|
||||
/*
|
||||
* ioctl commands
|
||||
*/
|
||||
|
||||
struct ncp_ioctl_request {
|
||||
unsigned int function;
|
||||
unsigned int size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||
|
||||
/*
|
||||
* The packet size to allocate. One page should be enough.
|
||||
*/
|
||||
#define NCP_PACKET_SIZE 4070
|
||||
|
||||
#define NCP_MAXPATHLEN 255
|
||||
#define NCP_MAXNAMELEN 14
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* The readdir cache size controls how many directory entries are
|
||||
* cached.
|
||||
*/
|
||||
#define NCP_READDIR_CACHE_SIZE 64
|
||||
|
||||
|
||||
#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
|
||||
|
||||
/* Guess, what 0x564c is :-) */
|
||||
#define NCP_SUPER_MAGIC 0x564c
|
||||
|
||||
|
||||
#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_SERVER(inode) NCP_SBP((inode)->i_sb)
|
||||
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
||||
#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i))
|
||||
|
||||
static inline int min(int a, int b) {
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
|
||||
#include <linux/malloc.h>
|
||||
|
||||
extern int ncp_malloced;
|
||||
extern int ncp_current_malloced;
|
||||
|
||||
static inline void *
|
||||
ncp_kmalloc(unsigned int size, int priority)
|
||||
{
|
||||
ncp_malloced += 1;
|
||||
ncp_current_malloced += 1;
|
||||
return kmalloc(size, priority);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ncp_kfree_s(void *obj, int size)
|
||||
{
|
||||
ncp_current_malloced -= 1;
|
||||
kfree_s(obj, size);
|
||||
}
|
||||
|
||||
#else /* DEBUG_NCP_MALLOC */
|
||||
|
||||
#define ncp_kmalloc(s,p) kmalloc(s,p)
|
||||
#define ncp_kfree_s(o,s) kfree_s(o,s)
|
||||
|
||||
#endif /* DEBUG_NCP_MALLOC */
|
||||
|
||||
#if DEBUG_NCP > 0
|
||||
#define DPRINTK(format, args...) printk(format , ## args)
|
||||
#else
|
||||
#define DPRINTK(format, args...)
|
||||
#endif
|
||||
|
||||
#if DEBUG_NCP > 1
|
||||
#define DDPRINTK(format, args...) printk(format , ## args)
|
||||
#else
|
||||
#define DDPRINTK(format, args...)
|
||||
#endif
|
||||
|
||||
|
||||
/* linux/fs/ncpfs/file.c */
|
||||
extern struct inode_operations ncp_file_inode_operations;
|
||||
int ncp_make_open(struct inode *i, int right);
|
||||
|
||||
/* linux/fs/ncpfs/dir.c */
|
||||
extern struct inode_operations ncp_dir_inode_operations;
|
||||
void ncp_free_inode_info(struct ncp_inode_info *i);
|
||||
void ncp_free_all_inodes(struct ncp_server *server);
|
||||
void ncp_init_root(struct ncp_server *server);
|
||||
int ncp_stat_root(struct ncp_server *server);
|
||||
void ncp_init_dir_cache(void);
|
||||
void ncp_invalid_dir_cache(unsigned long ino);
|
||||
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
||||
void ncp_free_dir_cache(void);
|
||||
int ncp_date_dos2unix(__u16 time, __u16 date);
|
||||
void ncp_date_unix2dos(int unix_date, __u16 *time, __u16 *date);
|
||||
|
||||
|
||||
/* linux/fs/ncpfs/ioctl.c */
|
||||
int ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
/* linux/fs/ncpfs/inode.c */
|
||||
struct super_block *ncp_read_super(struct super_block *sb,
|
||||
void *raw_data, int silent);
|
||||
void ncp_invalidate_connection(struct ncp_server *server);
|
||||
int ncp_conn_is_valid(struct ncp_server *server);
|
||||
|
||||
/* linux/fs/ncpfs/sock.c */
|
||||
int ncp_request(struct ncp_server *server, int function);
|
||||
int ncp_connect(struct ncp_server *server);
|
||||
int ncp_disconnect(struct ncp_server *server);
|
||||
int ncp_catch_watchdog(struct ncp_server *server);
|
||||
int ncp_dont_catch_watchdog(struct ncp_server *server);
|
||||
void ncp_lock_server(struct ncp_server *server);
|
||||
void ncp_unlock_server(struct ncp_server *server);
|
||||
|
||||
/* linux/fs/ncpfs/mmap.c */
|
||||
int ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_NCP_FS_H */
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* ncp_fs_i.h
|
||||
*
|
||||
* Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_NCP_FS_I
|
||||
#define _LINUX_NCP_FS_I
|
||||
|
||||
#include <linux/ncp.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
enum ncp_inode_state {
|
||||
INODE_VALID = 19, /* Inode currently in use */
|
||||
INODE_LOOKED_UP, /* directly before iget */
|
||||
INODE_CACHED, /* in a path to an inode which is in use */
|
||||
INODE_INVALID
|
||||
};
|
||||
|
||||
/*
|
||||
* ncp fs inode data (in memory only)
|
||||
*/
|
||||
struct ncp_inode_info {
|
||||
enum ncp_inode_state state;
|
||||
int nused; /* for directories:
|
||||
number of references in memory */
|
||||
struct ncp_inode_info *dir;
|
||||
struct ncp_inode_info *next, *prev;
|
||||
struct nw_file_info finfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* ncp_fs_sb.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NCP_FS_SB
|
||||
#define _NCP_FS_SB
|
||||
|
||||
#include <linux/ncp_mount.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define NCP_DEFAULT_BUFSIZE 1024
|
||||
|
||||
struct ncp_server {
|
||||
|
||||
struct ncp_mount_data m; /* Nearly all of the mount data is of
|
||||
interest for us later, so we store
|
||||
it completely. */
|
||||
|
||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||
|
||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||
void *data_ready; /* The wdog socket gets a new
|
||||
data_ready callback. We store the
|
||||
old one for checking purposes and
|
||||
to reset it on unmounting. */
|
||||
|
||||
u8 sequence;
|
||||
u8 task;
|
||||
u16 connection; /* Remote connection number */
|
||||
|
||||
u8 completion; /* Status message from server */
|
||||
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
||||
requests allowed anymore */
|
||||
|
||||
int buffer_size; /* Negotiated bufsize */
|
||||
|
||||
int reply_size; /* Size of last reply */
|
||||
|
||||
int packet_size;
|
||||
unsigned char *packet; /* Here we prepare requests and
|
||||
receive replies */
|
||||
|
||||
int lock; /* To prevent mismatch in protocols. */
|
||||
struct wait_queue *wait;
|
||||
|
||||
int current_size; /* for packet preparation */
|
||||
int has_subfunction;
|
||||
int ncp_reply_size;
|
||||
|
||||
struct ncp_inode_info root;
|
||||
char root_path; /* '\0' */
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* ncp_mount.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_NCP_MOUNT_H
|
||||
#define _LINUX_NCP_MOUNT_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs_i.h>
|
||||
|
||||
#define NCP_MOUNT_VERSION 1
|
||||
|
||||
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
||||
#define NCP_PASSWORD_LEN 20
|
||||
|
||||
/* Values for flags */
|
||||
#define NCP_MOUNT_SOFT 0x0001
|
||||
#define NCP_MOUNT_INTR 0x0002
|
||||
|
||||
struct ncp_mount_data {
|
||||
int version;
|
||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||
unsigned int wdog_fd; /* Watchdog packets come here */
|
||||
unsigned int message_fd; /* Not used yet, maybe for messages */
|
||||
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
||||
|
||||
struct sockaddr_ipx serv_addr;
|
||||
unsigned char server_name[49];
|
||||
|
||||
unsigned char username[NCP_USERNAME_LEN+1];
|
||||
unsigned char password[NCP_PASSWORD_LEN+1];
|
||||
|
||||
unsigned int time_out; /* How long should I wait after
|
||||
sending a NCP request? */
|
||||
unsigned int retry_count; /* And how often should I retry? */
|
||||
unsigned int flags;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t file_mode;
|
||||
mode_t dir_mode;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,67 +0,0 @@
|
||||
#
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -I..
|
||||
|
||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||
$(INCLUDES) \
|
||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||
# -DDEBUG_NCP_MALLOC
|
||||
|
||||
CC = gcc -D__KERNEL__ -I.
|
||||
AS = as
|
||||
ARCH = i386
|
||||
|
||||
.c.s:
|
||||
$(CC) $(CFLAGS) -S $<
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
.s.o:
|
||||
$(AS) -o $*.o $<
|
||||
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o
|
||||
|
||||
all: ncpfs.o
|
||||
|
||||
ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o ncpfs.o $(OBJS)
|
||||
|
||||
ncplib.o: ncplib.c ncplib.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
|
||||
realclean: clean
|
||||
rm -f ncpmount ncptest .depend $(DISTFILE) *.out
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
BACKUPFILE=ncpfs01.tgz
|
||||
HOME=/home/me
|
||||
|
||||
backup:
|
||||
(rm -f $(DISTFILE); cd ..; tar cvf - $(SRCDIR) | gzip -1 \
|
||||
> $(HOME)/tarz/backup/$(BACKUPFILE))
|
||||
(cd $(HOME)/tarz/backup; ls -l $(BACKUPFILE); mcopy $(BACKUPFILE) a:)
|
||||
|
||||
dist: realclean
|
||||
rm -fr mnt
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
mv $(DISTFILE) $(SRCDIR))
|
||||
|
||||
#
|
||||
# include a dependency file if one exists
|
||||
#
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
include .depend
|
||||
endif
|
||||
@@ -1,949 +0,0 @@
|
||||
/*
|
||||
* dir.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
struct ncp_dirent {
|
||||
struct nw_info_struct i;
|
||||
struct nw_search_sequence s; /* given back for i */
|
||||
unsigned long f_pos;
|
||||
};
|
||||
|
||||
static int
|
||||
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
|
||||
|
||||
static int
|
||||
ncp_readdir(struct inode *inode, struct file *filp,
|
||||
void *dirent, filldir_t filldir);
|
||||
|
||||
static int
|
||||
ncp_read_volume_list(struct ncp_server *server, int start_with,
|
||||
int cache_size);
|
||||
|
||||
static int
|
||||
ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
||||
int cache_size, struct ncp_dirent *entry);
|
||||
|
||||
static struct inode *
|
||||
ncp_iget(struct inode *dir, struct nw_file_info *finfo);
|
||||
|
||||
static struct ncp_inode_info *
|
||||
ncp_find_inode(struct inode *dir, const char *name);
|
||||
|
||||
static int
|
||||
ncp_lookup(struct inode *dir, const char *__name,
|
||||
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 inline void
|
||||
str_upper(char *name)
|
||||
{
|
||||
while (*name) {
|
||||
if (*name >= 'a' && *name <= 'z')
|
||||
*name -= ('a' - 'A');
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
str_lower(char *name)
|
||||
{
|
||||
while (*name) {
|
||||
if (*name >= 'A' && *name <= 'Z')
|
||||
*name += ('a' - 'A');
|
||||
name ++;
|
||||
}
|
||||
}
|
||||
|
||||
static struct file_operations ncp_dir_operations = {
|
||||
NULL, /* lseek - default */
|
||||
ncp_dir_read, /* read - bad */
|
||||
NULL, /* write - bad */
|
||||
ncp_readdir, /* readdir */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl - default */
|
||||
NULL, /* mmap */
|
||||
NULL, /* no special open code */
|
||||
NULL, /* no special release code */
|
||||
NULL /* fsync */
|
||||
};
|
||||
|
||||
struct inode_operations ncp_dir_inode_operations = {
|
||||
&ncp_dir_operations, /* default directory file ops */
|
||||
ncp_create, /* create */
|
||||
ncp_lookup, /* lookup */
|
||||
NULL, /* link */
|
||||
ncp_unlink, /* unlink */
|
||||
NULL, /* symlink */
|
||||
ncp_mkdir, /* mkdir */
|
||||
ncp_rmdir, /* rmdir */
|
||||
NULL, /* mknod */
|
||||
ncp_rename, /* rename */
|
||||
NULL, /* readlink */
|
||||
NULL, /* follow_link */
|
||||
NULL, /* bmap */
|
||||
NULL, /* truncate */
|
||||
NULL, /* permission */
|
||||
NULL /* smap */
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||
{
|
||||
return -EISDIR;
|
||||
}
|
||||
|
||||
/* In ncpfs, we have unique inodes across all mounted filesystems, for
|
||||
all inodes that are in memory. That's why it's enough to index the
|
||||
directory cache by the inode number. */
|
||||
|
||||
static unsigned long c_ino = 0;
|
||||
static int c_size;
|
||||
static int c_seen_eof;
|
||||
static int c_last_returned_index;
|
||||
static struct ncp_dirent* c_entry = NULL;
|
||||
|
||||
static int
|
||||
ncp_readdir(struct inode *inode, struct file *filp,
|
||||
void *dirent, filldir_t filldir)
|
||||
{
|
||||
int result, i = 0;
|
||||
int index = 0;
|
||||
struct ncp_dirent *entry = NULL;
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
|
||||
|
||||
DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
||||
DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
||||
inode->i_ino, c_ino);
|
||||
|
||||
if (!inode || !S_ISDIR(inode->i_mode)) {
|
||||
printk("ncp_readdir: inode is NULL or not a directory\n");
|
||||
return -EBADF;
|
||||
}
|
||||
|
||||
if (c_entry == NULL)
|
||||
{
|
||||
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
||||
c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
|
||||
if (c_entry == NULL) {
|
||||
printk("ncp_readdir: no MEMORY for cache\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (filp->f_pos == 0) {
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0) {
|
||||
return 0;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
}
|
||||
|
||||
if (filp->f_pos == 1) {
|
||||
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0) {
|
||||
return 0;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (inode->i_ino == c_ino) {
|
||||
for (i = 0; i < c_size; i++) {
|
||||
if (filp->f_pos == c_entry[i].f_pos) {
|
||||
entry = &c_entry[i];
|
||||
c_last_returned_index = i;
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((entry == NULL) && c_seen_eof)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
||||
|
||||
if (inode->i_ino == (int)&(server->root)) {
|
||||
|
||||
result = ncp_read_volume_list(server, filp->f_pos,
|
||||
NCP_READDIR_CACHE_SIZE);
|
||||
DPRINTK("ncp_read_volume_list returned %d\n", result);
|
||||
|
||||
} else {
|
||||
|
||||
result = ncp_do_readdir(server, inode, filp->f_pos,
|
||||
NCP_READDIR_CACHE_SIZE,
|
||||
c_entry);
|
||||
DPRINTK("ncp_readdir returned %d\n", result);
|
||||
}
|
||||
|
||||
|
||||
if (result < 0) {
|
||||
c_ino = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
||||
c_ino = inode->i_ino;
|
||||
c_size = result;
|
||||
entry = c_entry;
|
||||
c_last_returned_index = 0;
|
||||
index = 0;
|
||||
|
||||
for (i = 0; i < c_size; i++) {
|
||||
str_lower(c_entry[i].i.entryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
/* Nothing found, even from a ncp call */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (index < c_size) {
|
||||
|
||||
/* We found it. For getwd(), we have to return the
|
||||
correct inode in d_ino if the inode is currently in
|
||||
use. Otherwise the inode number does not
|
||||
matter. (You can argue a lot about this..) */
|
||||
|
||||
struct ncp_inode_info *ino_info;
|
||||
ino_info = ncp_find_inode(inode, entry->i.entryName);
|
||||
|
||||
|
||||
/* Some programs seem to be confused about a zero
|
||||
inode number, so we set it to one. Thanks to
|
||||
Gordon Chaffee for this one. */
|
||||
if (ino_info == NULL) {
|
||||
ino_info = (struct ncp_inode_info *) 1;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
|
||||
DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
||||
|
||||
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
||||
entry->f_pos, (ino_t)ino_info) < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (inode->i_ino != c_ino)
|
||||
|| (entry->f_pos != filp->f_pos)) {
|
||||
/* Someone has destroyed the cache while we slept
|
||||
in filldir */
|
||||
break;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
index += 1;
|
||||
entry += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
||||
{
|
||||
struct ncp_dirent *entry = c_entry;
|
||||
|
||||
int total_count = 2;
|
||||
int i;
|
||||
|
||||
#if 1
|
||||
if (fpos < 2) {
|
||||
printk("OOPS, we expect fpos >= 2");
|
||||
fpos = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++) {
|
||||
|
||||
struct ncp_volume_info info;
|
||||
|
||||
if (ncp_get_volume_info_with_number(server, i, &info) != 0) {
|
||||
return total_count;
|
||||
}
|
||||
|
||||
if (strlen(info.volume_name) > 0) {
|
||||
if (total_count < fpos) {
|
||||
DPRINTK("ncp_read_volumes: skipped vol: %s\n",
|
||||
info.volume_name);
|
||||
} else if (total_count >= fpos + cache_size) {
|
||||
return (total_count - fpos);
|
||||
} else {
|
||||
DPRINTK("ncp_read_volumes: found vol: %s\n",
|
||||
info.volume_name);
|
||||
|
||||
if (ncp_do_lookup(server, NULL,
|
||||
info.volume_name,
|
||||
&(entry->i)) != 0) {
|
||||
printk("ncpfs: could not lookup vol "
|
||||
"%s\n", info.volume_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry->f_pos = total_count;
|
||||
entry += 1;
|
||||
}
|
||||
total_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (total_count - fpos);
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
||||
int cache_size, struct ncp_dirent *entry)
|
||||
{
|
||||
static struct nw_search_sequence seq;
|
||||
static struct inode *last_dir;
|
||||
static int total_count;
|
||||
|
||||
#if 1
|
||||
if (fpos < 2) {
|
||||
printk("OOPS, we expect fpos >= 2");
|
||||
fpos = 2;
|
||||
}
|
||||
#endif
|
||||
DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
|
||||
|
||||
if (fpos == 2) {
|
||||
last_dir = NULL;
|
||||
total_count = 2;
|
||||
}
|
||||
|
||||
if ((fpos != total_count) || (dir != last_dir)) {
|
||||
|
||||
total_count = 2;
|
||||
last_dir = dir;
|
||||
|
||||
DPRINTK("ncp_do_readdir: re-used seq for %s\n",
|
||||
NCP_ISTRUCT(dir)->entryName);
|
||||
|
||||
if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0) {
|
||||
DPRINTK("ncp_init_search failed\n");
|
||||
return total_count - fpos;
|
||||
}
|
||||
}
|
||||
|
||||
while (total_count < fpos + cache_size) {
|
||||
|
||||
if (ncp_search_for_file_or_subdir(server, &seq,
|
||||
&(entry->i)) != 0) {
|
||||
return total_count - fpos;
|
||||
}
|
||||
|
||||
if (total_count < fpos) {
|
||||
DPRINTK("ncp_do_readdir: skipped file: %s\n",
|
||||
entry->i.entryName);
|
||||
} else {
|
||||
DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d",
|
||||
entry->i.entryName, fpos, total_count);
|
||||
entry->s = seq;
|
||||
entry->f_pos = total_count;
|
||||
entry += 1;
|
||||
}
|
||||
total_count += 1;
|
||||
}
|
||||
|
||||
return (total_count - fpos);
|
||||
}
|
||||
|
||||
void
|
||||
ncp_init_dir_cache(void)
|
||||
{
|
||||
c_ino = 0;
|
||||
c_entry = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_invalid_dir_cache(unsigned long ino)
|
||||
{
|
||||
if (ino == c_ino) {
|
||||
c_ino = 0;
|
||||
c_seen_eof = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncp_free_dir_cache(void)
|
||||
{
|
||||
DPRINTK("ncp_free_dir_cache: enter\n");
|
||||
|
||||
if (c_entry == NULL)
|
||||
return;
|
||||
|
||||
ncp_kfree_s(c_entry,
|
||||
sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE);
|
||||
c_entry = NULL;
|
||||
|
||||
DPRINTK("ncp_free_dir_cache: exit\n");
|
||||
}
|
||||
|
||||
|
||||
static struct inode *
|
||||
ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
{
|
||||
struct inode *inode;
|
||||
struct ncp_inode_info *new_inode_info;
|
||||
struct ncp_inode_info *root;
|
||||
|
||||
if (!dir) {
|
||||
printk("ncp_iget: dir is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!finfo) {
|
||||
printk("ncp_iget: finfo is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (new_inode_info == NULL) {
|
||||
printk("ncp_iget: could not alloc mem for %s\n",
|
||||
finfo->i.entryName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_inode_info->state = INODE_LOOKED_UP;
|
||||
new_inode_info->nused = 0;
|
||||
new_inode_info->dir = NCP_INOP(dir);
|
||||
new_inode_info->finfo = *finfo;
|
||||
|
||||
NCP_INOP(dir)->nused += 1;
|
||||
|
||||
/* We have to link the new inode_info into the doubly linked
|
||||
list of inode_infos to make a complete linear search
|
||||
possible. */
|
||||
|
||||
root = &(NCP_SERVER(dir)->root);
|
||||
|
||||
new_inode_info->prev = root;
|
||||
new_inode_info->next = root->next;
|
||||
root->next->prev = new_inode_info;
|
||||
root->next = new_inode_info;
|
||||
|
||||
if (!(inode = iget(dir->i_sb, (int)new_inode_info))) {
|
||||
printk("ncp_iget: iget failed!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_free_inode_info(struct ncp_inode_info *i)
|
||||
{
|
||||
if (i == NULL) {
|
||||
printk("ncp_free_inode: i == NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
i->state = INODE_CACHED;
|
||||
while ((i->nused == 0) && (i->state == INODE_CACHED)) {
|
||||
struct ncp_inode_info *dir = i->dir;
|
||||
|
||||
i->next->prev = i->prev;
|
||||
i->prev->next = i->next;
|
||||
|
||||
DDPRINTK("ncp_free_inode_info: freeing %s\n",
|
||||
i->finfo.i.entryName);
|
||||
|
||||
ncp_kfree_s(i, sizeof(struct ncp_inode_info));
|
||||
|
||||
if (dir == i) return;
|
||||
|
||||
(dir->nused)--;
|
||||
i = dir;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncp_init_root(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_inode_info *root = &(server->root);
|
||||
struct nw_info_struct *i = &(root->finfo.i);
|
||||
unsigned short dummy;
|
||||
|
||||
DPRINTK("ncp_init_root: server %s\n", server->m.server_name);
|
||||
DPRINTK("ncp_init_root: i = %x\n", (int)i);
|
||||
|
||||
root->finfo.opened = 0;
|
||||
i->attributes = aDIR;
|
||||
i->dataStreamSize = 1024;
|
||||
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
|
||||
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
|
||||
ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
|
||||
i->nameLen = 0;
|
||||
i->entryName[0] = '\0';
|
||||
|
||||
root->state = INODE_LOOKED_UP;
|
||||
root->nused = 1;
|
||||
root->dir = root;
|
||||
root->next = root->prev = root;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_free_all_inodes(struct ncp_server *server)
|
||||
{
|
||||
/* Here nothing should be to do. I do not know whether it's
|
||||
better to leave some memory allocated or be stuck in an
|
||||
endless loop */
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(server->root);
|
||||
|
||||
if (root->next != root) {
|
||||
printk("ncp_free_all_inodes: INODES LEFT!!!\n");
|
||||
}
|
||||
|
||||
while (root->next != root) {
|
||||
printk("ncp_free_all_inodes: freeing inode\n");
|
||||
ncp_free_inode_info(root->next);
|
||||
/* In case we have an endless loop.. */
|
||||
schedule();
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* We will search the inode that belongs to this name, currently by a
|
||||
complete linear search through the inodes belonging to this
|
||||
filesystem. This has to be fixed. */
|
||||
static struct ncp_inode_info *
|
||||
ncp_find_inode(struct inode *dir, const char *name)
|
||||
{
|
||||
struct ncp_server *server = NCP_SERVER(dir);
|
||||
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
|
||||
struct ncp_inode_info *result = &(server->root);
|
||||
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
|
||||
&& (strcmp(result->finfo.i.entryName, name) == 0))
|
||||
return result;
|
||||
result = result->next;
|
||||
|
||||
} while (result != &(server->root));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
struct inode **result)
|
||||
{
|
||||
struct nw_file_info finfo;
|
||||
struct ncp_server *server;
|
||||
struct ncp_inode_info *result_info;
|
||||
int found_in_cache;
|
||||
|
||||
*result = NULL;
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
printk("ncp_lookup: inode is NULL or not a directory.\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
|
||||
|
||||
server = NCP_SERVER(dir);
|
||||
|
||||
/* Fast cheat for . */
|
||||
if (len == 0 || (len == 1 && __name[0] == '.')) {
|
||||
*result = dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ..and for .. */
|
||||
if (len == 2 && __name[0] == '.' && __name[1] == '.') {
|
||||
struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
|
||||
|
||||
if (parent->state == INODE_CACHED) {
|
||||
parent->state = INODE_LOOKED_UP;
|
||||
}
|
||||
|
||||
*result = iget(dir->i_sb, (int)parent);
|
||||
iput(dir);
|
||||
if (*result == 0)
|
||||
return -EACCES;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
result_info = ncp_find_inode(dir, __name);
|
||||
|
||||
if (result_info != 0) {
|
||||
|
||||
if (result_info->state == INODE_CACHED)
|
||||
result_info->state = INODE_LOOKED_UP;
|
||||
|
||||
/* Here we convert the inode_info address into an
|
||||
inode number */
|
||||
|
||||
*result = iget(dir->i_sb, (int)result_info);
|
||||
iput(dir);
|
||||
|
||||
if (*result == NULL) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the file is in the dir cache, we do not have to ask the
|
||||
server. */
|
||||
|
||||
found_in_cache = 0;
|
||||
|
||||
if (dir->i_ino == c_ino) {
|
||||
int first = c_last_returned_index;
|
||||
int i;
|
||||
|
||||
i = first;
|
||||
do {
|
||||
DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
|
||||
i, c_entry[i].i.entryName);
|
||||
if (strcmp(c_entry[i].i.entryName, __name) == 0) {
|
||||
DPRINTK("ncp_lookup: found in cache!\n");
|
||||
finfo.i = c_entry[i].i;
|
||||
found_in_cache = 1;
|
||||
break;
|
||||
}
|
||||
i = (i + 1) % c_size;
|
||||
} while (i != first);
|
||||
}
|
||||
|
||||
if (found_in_cache == 0) {
|
||||
|
||||
char this_name[len+1];
|
||||
|
||||
memcpy(this_name, __name, len);
|
||||
this_name[len] = 0;
|
||||
str_upper(this_name);
|
||||
|
||||
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
||||
NCP_ISTRUCT(dir)->entryName, this_name);
|
||||
|
||||
if (ncp_do_lookup(server,
|
||||
dir->i_ino == (int)&(NCP_SERVER(dir)->root)
|
||||
? NULL : NCP_ISTRUCT(dir),
|
||||
this_name,
|
||||
&(finfo.i)) != 0) {
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
finfo.opened = 0;
|
||||
str_lower(finfo.i.entryName);
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo))) {
|
||||
iput(dir);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
iput(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
struct inode **result)
|
||||
{
|
||||
struct nw_file_info finfo;
|
||||
__u8 _name[len+1];
|
||||
|
||||
*result = NULL;
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
printk("ncp_create: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir), _name,
|
||||
OC_MODE_CREATE|OC_MODE_OPEN,
|
||||
0, AR_READ|AR_WRITE,
|
||||
&finfo) != 0) {
|
||||
iput(dir);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
|
||||
str_lower(finfo.i.entryName);
|
||||
finfo.access = O_RDWR;
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo)) < 0) {
|
||||
ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
|
||||
iput(dir);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
iput(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||
{
|
||||
int error;
|
||||
struct nw_file_info new_dir;
|
||||
__u8 _name[len+1];
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
printk("ncp_mkdir: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir), _name,
|
||||
OC_MODE_CREATE, aDIR, 0xffff,
|
||||
&new_dir) != 0) {
|
||||
error = -EACCES;
|
||||
} else {
|
||||
error = 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;
|
||||
__u8 _name[len+1];
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
printk("ncp_rmdir: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL) {
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0) {
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = -EINVAL;
|
||||
}
|
||||
}
|
||||
iput(dir);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_unlink(struct inode *dir, const char *name, int len)
|
||||
{
|
||||
int error;
|
||||
__u8 _name[len+1];
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
printk("ncp_unlink: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL) {
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0) {
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = -EINVAL;
|
||||
}
|
||||
}
|
||||
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_name[old_len+1];
|
||||
char _new_name[new_len+1];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ( (ncp_find_inode(old_dir, old_name) != NULL)
|
||||
|| (ncp_find_inode(new_dir, new_name) != NULL)) {
|
||||
res = -EBUSY;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
strncpy(_old_name, old_name, old_len);
|
||||
_old_name[old_len] = '\0';
|
||||
str_upper(_old_name);
|
||||
|
||||
strncpy(_new_name, new_name, new_len);
|
||||
_new_name[old_len] = '\0';
|
||||
str_upper(_new_name);
|
||||
|
||||
res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
|
||||
NCP_ISTRUCT(old_dir), _old_name,
|
||||
NCP_ISTRUCT(new_dir), _new_name);
|
||||
|
||||
if (res == 0) {
|
||||
ncp_invalid_dir_cache(old_dir->i_ino);
|
||||
ncp_invalid_dir_cache(new_dir->i_ino);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = -EACCES;
|
||||
}
|
||||
|
||||
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. */
|
||||
|
||||
static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
|
||||
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
|
||||
|
||||
|
||||
extern struct timezone sys_tz;
|
||||
|
||||
static int
|
||||
utc2local(int time)
|
||||
{
|
||||
return time - sys_tz.tz_minuteswest*60;
|
||||
}
|
||||
|
||||
static int
|
||||
local2utc(int time)
|
||||
{
|
||||
return time + sys_tz.tz_minuteswest*60;
|
||||
}
|
||||
|
||||
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
|
||||
|
||||
int
|
||||
ncp_date_dos2unix(unsigned short time,unsigned short date)
|
||||
{
|
||||
int month,year,secs;
|
||||
|
||||
month = ((date >> 5) & 15)-1;
|
||||
year = date >> 9;
|
||||
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
|
||||
((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
|
||||
month < 2 ? 1 : 0)+3653);
|
||||
/* days since 1.1.70 plus 80's leap day */
|
||||
return local2utc(secs);
|
||||
}
|
||||
|
||||
|
||||
/* Convert linear UNIX date to a MS-DOS time/date pair. */
|
||||
void
|
||||
ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
|
||||
{
|
||||
int day,year,nl_day,month;
|
||||
|
||||
unix_date = utc2local(unix_date);
|
||||
*time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
|
||||
(((unix_date/3600) % 24) << 11);
|
||||
day = unix_date/86400-3652;
|
||||
year = day/365;
|
||||
if ((year+3)/4+365*year > day) year--;
|
||||
day -= (year+3)/4+365*year;
|
||||
if (day == 59 && !(year & 3)) {
|
||||
nl_day = day;
|
||||
month = 2;
|
||||
}
|
||||
else {
|
||||
nl_day = (year & 3) || day <= 59 ? day : day-1;
|
||||
for (month = 0; month < 12; month++)
|
||||
if (day_n[month] > nl_day) break;
|
||||
}
|
||||
*date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* file.c
|
||||
*
|
||||
* Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include "ncplib.h"
|
||||
#include <linux/malloc.h>
|
||||
|
||||
static int
|
||||
ncp_fsync(struct inode *inode, struct file *file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_make_open(struct inode *i, int right)
|
||||
{
|
||||
struct nw_file_info *finfo;
|
||||
|
||||
if (i == NULL) {
|
||||
printk("ncp_make_open: got NULL inode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
finfo = NCP_FINFO(i);
|
||||
|
||||
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
|
||||
|
||||
if (finfo->opened == 0) {
|
||||
|
||||
/* tries max. rights */
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ | AR_WRITE,
|
||||
finfo) == 0) {
|
||||
finfo->access = O_RDWR;
|
||||
}
|
||||
else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ,
|
||||
finfo) == 0) {
|
||||
finfo->access = O_RDONLY;
|
||||
} else {
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|
||||
|| (finfo->access == O_RDWR)))
|
||||
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)
|
||||
|| (finfo->access == O_RDWR)))
|
||||
|| ((right == O_RDWR) && (finfo->access == O_RDWR)))
|
||||
return 0;
|
||||
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
{
|
||||
int bufsize, to_read, already_read;
|
||||
off_t pos;
|
||||
int errno;
|
||||
|
||||
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
if (!inode) {
|
||||
DPRINTK("ncp_file_read: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
|
||||
inode->i_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pos = file->f_pos;
|
||||
|
||||
if (pos + count > inode->i_size)
|
||||
count = inode->i_size - pos;
|
||||
|
||||
if (count <= 0)
|
||||
return 0;
|
||||
|
||||
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
||||
return errno;
|
||||
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
already_read = 0;
|
||||
|
||||
/* First read in as much as possible for each bufsize. */
|
||||
while (already_read < count) {
|
||||
|
||||
int read_this_time;
|
||||
|
||||
if ((pos % bufsize) != 0) {
|
||||
to_read = bufsize - (pos % bufsize);
|
||||
} else {
|
||||
to_read = bufsize;
|
||||
}
|
||||
|
||||
to_read = min(to_read, count - already_read);
|
||||
|
||||
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||
pos, to_read, buf, &read_this_time) != 0) {
|
||||
return -EIO; /* This is not exact, i know.. */
|
||||
}
|
||||
|
||||
pos += read_this_time;
|
||||
buf += read_this_time;
|
||||
already_read += read_this_time;
|
||||
|
||||
if (read_this_time < to_read) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file->f_pos = pos;
|
||||
|
||||
if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
|
||||
inode->i_dirt = 1;
|
||||
|
||||
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
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_ISTRUCT(inode)->entryName);
|
||||
|
||||
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_handle,
|
||||
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_ISTRUCT(inode)->entryName);
|
||||
|
||||
return already_written;
|
||||
}
|
||||
|
||||
static struct file_operations ncp_file_operations = {
|
||||
NULL, /* lseek - default */
|
||||
ncp_file_read, /* read */
|
||||
ncp_file_write, /* write */
|
||||
NULL, /* readdir - bad */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
NULL, /* open */
|
||||
NULL, /* release */
|
||||
ncp_fsync, /* fsync */
|
||||
};
|
||||
|
||||
struct inode_operations ncp_file_inode_operations = {
|
||||
&ncp_file_operations, /* default file operations */
|
||||
NULL, /* create */
|
||||
NULL, /* lookup */
|
||||
NULL, /* link */
|
||||
NULL, /* unlink */
|
||||
NULL, /* symlink */
|
||||
NULL, /* mkdir */
|
||||
NULL, /* rmdir */
|
||||
NULL, /* mknod */
|
||||
NULL, /* rename */
|
||||
NULL, /* readlink */
|
||||
NULL, /* follow_link */
|
||||
NULL, /* bmap */
|
||||
NULL /* truncate */
|
||||
};
|
||||
@@ -1,484 +0,0 @@
|
||||
/*
|
||||
* inode.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/locks.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/malloc.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
extern int close_fp(struct file *filp);
|
||||
|
||||
static void ncp_put_inode(struct inode *);
|
||||
static void ncp_read_inode(struct inode *);
|
||||
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 = {
|
||||
ncp_read_inode, /* read inode */
|
||||
ncp_notify_change, /* notify change */
|
||||
NULL, /* write inode */
|
||||
ncp_put_inode, /* put inode */
|
||||
ncp_put_super, /* put superblock */
|
||||
NULL, /* write superblock */
|
||||
ncp_statfs, /* stat filesystem */
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ncp_read_inode: Called from iget, it only traverses the allocated
|
||||
ncp_inode_info's and initializes the inode from the data found
|
||||
there. It does not allocate or deallocate anything. */
|
||||
|
||||
static void
|
||||
ncp_read_inode(struct inode *inode)
|
||||
{
|
||||
/* Our task should be extremely simple here. We only have to
|
||||
look up the infomation somebody else (ncp_iget) put into
|
||||
the inode tree. The address of this information is the
|
||||
inode->i_ino. Just to make sure everything went well, we
|
||||
check it's there. */
|
||||
|
||||
struct ncp_inode_info *inode_info
|
||||
= (struct ncp_inode_info *)(inode->i_ino);
|
||||
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
||||
struct ncp_inode_info *check_info = root;
|
||||
|
||||
do {
|
||||
if (inode_info == check_info) {
|
||||
if (check_info->state == INODE_LOOKED_UP) {
|
||||
DDPRINTK("ncp_read_inode: found it!\n");
|
||||
goto good;
|
||||
}
|
||||
else {
|
||||
printk("ncp_read_inode: "
|
||||
"state != INODE_LOOKED_UP\n");
|
||||
goto good;
|
||||
}
|
||||
}
|
||||
check_info = check_info->next;
|
||||
} while (check_info != root);
|
||||
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
|
||||
good:
|
||||
DDPRINTK("ncp_read_inode: read entry %s\n",
|
||||
inode_info->finfo.i.entryName);
|
||||
#endif
|
||||
inode_info->state = INODE_VALID;
|
||||
|
||||
NCP_INOP(inode) = inode_info;
|
||||
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR) {
|
||||
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
||||
/* for directories in dataStreamSize seems to be some
|
||||
Object ID ??? */
|
||||
inode->i_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
|
||||
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
|
||||
|
||||
inode->i_nlink = 1;
|
||||
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
||||
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
||||
inode->i_blksize = 1024;
|
||||
inode->i_rdev = 0;
|
||||
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
||||
inode->i_blocks =
|
||||
(inode->i_size - 1) / inode->i_blksize + 1;
|
||||
else
|
||||
inode->i_blocks = 0;
|
||||
|
||||
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
|
||||
NCP_ISTRUCT(inode)->modifyDate);
|
||||
inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
|
||||
NCP_ISTRUCT(inode)->creationDate);
|
||||
inode->i_atime = ncp_date_dos2unix(0,
|
||||
NCP_ISTRUCT(inode)->lastAccessDate);
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
inode->i_op = &ncp_file_inode_operations;
|
||||
else if (S_ISDIR(inode->i_mode))
|
||||
inode->i_op = &ncp_dir_inode_operations;
|
||||
else
|
||||
inode->i_op = NULL;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_put_inode(struct inode *inode)
|
||||
{
|
||||
struct nw_file_info *finfo = NCP_FINFO(inode);
|
||||
|
||||
if (finfo->opened != 0) {
|
||||
|
||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) {
|
||||
/* We can't do anything but complain. */
|
||||
printk("ncp_put_inode: could not close\n");
|
||||
}
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_put_inode: put %s\n",
|
||||
finfo->i.entryName);
|
||||
|
||||
ncp_free_inode_info(NCP_INOP(inode));
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||
inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
}
|
||||
|
||||
clear_inode(inode);
|
||||
}
|
||||
|
||||
struct super_block *
|
||||
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
{
|
||||
struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
|
||||
struct ncp_server *server;
|
||||
struct file *ncp_filp;
|
||||
struct file *wdog_filp;
|
||||
kdev_t dev = sb->s_dev;
|
||||
int error;
|
||||
|
||||
if (!data) {
|
||||
printk("ncp_read_super: missing data argument\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->version != NCP_MOUNT_VERSION) {
|
||||
printk("ncp warning: mount version %s than kernel\n",
|
||||
(data->version < NCP_MOUNT_VERSION) ?
|
||||
"older" : "newer");
|
||||
}
|
||||
|
||||
|
||||
if ( (data->ncp_fd >= NR_OPEN)
|
||||
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|
||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode))) {
|
||||
printk("ncp_read_super: invalid ncp socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( (data->wdog_fd >= NR_OPEN)
|
||||
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|
||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode))) {
|
||||
printk("ncp_read_super: invalid wdog socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We must malloc our own super-block info */
|
||||
server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (server == NULL) {
|
||||
printk("ncp_read_super: could not alloc ncp_server\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ncp_filp->f_count += 1;
|
||||
wdog_filp->f_count += 1;
|
||||
|
||||
lock_super(sb);
|
||||
|
||||
NCP_SBP(sb) = server;
|
||||
|
||||
sb->s_blocksize = 1024; /* Eh... Is this correct? */
|
||||
sb->s_blocksize_bits = 10;
|
||||
sb->s_magic = NCP_SUPER_MAGIC;
|
||||
sb->s_dev = dev;
|
||||
sb->s_op = &ncp_sops;
|
||||
|
||||
server->ncp_filp = ncp_filp;
|
||||
server->wdog_filp = wdog_filp;
|
||||
server->lock = 0;
|
||||
server->wait = NULL;
|
||||
server->packet = NULL;
|
||||
server->buffer_size = 0;
|
||||
|
||||
server->m = *data;
|
||||
server->m.file_mode = (server->m.file_mode &
|
||||
(S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
|
||||
server->m.dir_mode = (server->m.dir_mode &
|
||||
(S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
|
||||
|
||||
server->packet_size = NCP_PACKET_SIZE;
|
||||
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
|
||||
|
||||
if (server->packet == NULL) {
|
||||
printk("ncpfs: could not alloc packet\n");
|
||||
error = -ENOMEM;
|
||||
unlock_super(sb);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ncp_init_root(server);
|
||||
|
||||
/*
|
||||
* Make the connection to the server
|
||||
*/
|
||||
|
||||
if (ncp_catch_watchdog(server) != 0) {
|
||||
printk("ncp_read_super: Could not catch watchdog\n");
|
||||
error = -EINVAL;
|
||||
unlock_super(sb);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ncp_lock_server(server);
|
||||
error = ncp_connect(server);
|
||||
ncp_unlock_server(server);
|
||||
unlock_super(sb);
|
||||
|
||||
if (error < 0) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: Failed connection, bailing out "
|
||||
"(error = %d).\n", -error);
|
||||
ncp_kfree_s(server->packet, server->packet_size);
|
||||
ncp_dont_catch_watchdog(server);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
||||
|
||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: get root inode failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
|
||||
&(server->buffer_size)) != 0) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: could not get bufsize\n");
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
|
||||
|
||||
/* if (ncp_login_user(server, server->m.username,
|
||||
server->m.password) != 0) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: login failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
*/
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
return sb;
|
||||
|
||||
disconnect:
|
||||
ncp_lock_server(server);
|
||||
ncp_disconnect(server);
|
||||
ncp_unlock_server(server);
|
||||
ncp_kfree_s(server->packet, server->packet_size);
|
||||
ncp_dont_catch_watchdog(server);
|
||||
fail:
|
||||
ncp_filp->f_count -= 1;
|
||||
wdog_filp->f_count -= 1;
|
||||
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_put_super(struct super_block *sb)
|
||||
{
|
||||
struct ncp_server *server = NCP_SBP(sb);
|
||||
|
||||
lock_super(sb);
|
||||
|
||||
ncp_lock_server(server);
|
||||
ncp_disconnect(server);
|
||||
ncp_unlock_server(server);
|
||||
|
||||
close_fp(server->ncp_filp);
|
||||
|
||||
ncp_dont_catch_watchdog(server);
|
||||
close_fp(server->wdog_filp);
|
||||
|
||||
ncp_free_all_inodes(server);
|
||||
|
||||
ncp_kfree_s(server->packet, server->packet_size);
|
||||
|
||||
sb->s_dev = 0;
|
||||
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
|
||||
NCP_SBP(sb) = NULL;
|
||||
|
||||
unlock_super(sb);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
{
|
||||
int result = 0;
|
||||
int info_mask;
|
||||
struct nw_modify_dos_info info;
|
||||
|
||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||
return result;
|
||||
|
||||
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;
|
||||
|
||||
info_mask = 0;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if ((attr->ia_valid & ATTR_CTIME) != 0) {
|
||||
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(info.creationTime), &(info.creationDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_MTIME) != 0) {
|
||||
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
|
||||
ncp_date_unix2dos(attr->ia_mtime,
|
||||
&(info.modifyTime), &(info.modifyDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_ATIME) != 0) {
|
||||
__u16 dummy;
|
||||
info_mask |= (DM_LAST_ACCESS_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(dummy), &(info.lastAccessDate));
|
||||
}
|
||||
|
||||
if (info_mask != 0) {
|
||||
if ((result =
|
||||
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
||||
NCP_ISTRUCT(inode),
|
||||
info_mask,
|
||||
&info)) != 0) {
|
||||
result = -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
||||
|
||||
int written;
|
||||
|
||||
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
||||
NCP_ISTRUCT(inode)->entryName, attr->ia_size);
|
||||
|
||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||
attr->ia_size, 0, "", &written);
|
||||
|
||||
/* According to ndir, the changes only take effect after
|
||||
closing the file */
|
||||
ncp_close_file(NCP_SERVER(inode),
|
||||
NCP_FINFO(inode)->file_handle);
|
||||
NCP_FINFO(inode)->opened = 0;
|
||||
|
||||
result = 0;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
int ncp_malloced;
|
||||
int ncp_current_malloced;
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
static struct file_system_type ncp_fs_type = {
|
||||
ncp_read_super, "ncpfs", 0, NULL
|
||||
};
|
||||
|
||||
int
|
||||
init_module( void)
|
||||
{
|
||||
DPRINTK("ncpfs: init_module called\n");
|
||||
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
ncp_malloced = 0;
|
||||
ncp_current_malloced = 0;
|
||||
#endif
|
||||
|
||||
ncp_init_dir_cache();
|
||||
register_filesystem(&ncp_fs_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_module(void)
|
||||
{
|
||||
DPRINTK("ncpfs: cleanup_module called\n");
|
||||
ncp_free_dir_cache();
|
||||
unregister_filesystem(&ncp_fs_type);
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
printk("ncp_malloced: %d\n", ncp_malloced);
|
||||
printk("ncp_current_malloced: %d\n", ncp_current_malloced);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* ioctl.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int result;
|
||||
struct ncp_ioctl_request request;
|
||||
struct ncp_server *server;
|
||||
|
||||
switch(cmd) {
|
||||
case NCP_IOC_NCPREQUEST:
|
||||
|
||||
if (!suser()) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
||||
sizeof(request))) != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
|
||||
sizeof(request));
|
||||
|
||||
if ( (request.function > 255)
|
||||
|| (request.size >
|
||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
||||
NCP_PACKET_SIZE)) != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
server = NCP_SERVER(inode);
|
||||
ncp_lock_server(server);
|
||||
|
||||
/* FIXME: We hack around in the server's structures
|
||||
here to be able to use ncp_request */
|
||||
|
||||
server->has_subfunction = 0;
|
||||
server->current_size =
|
||||
request.size + sizeof(struct ncp_request_header);
|
||||
memcpy_fromfs(server->packet, request.data,
|
||||
request.size+sizeof(struct ncp_request_header));
|
||||
|
||||
|
||||
ncp_request(server, request.function);
|
||||
|
||||
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
||||
server->reply_size);
|
||||
memcpy_tofs(request.data, server->packet,
|
||||
server->reply_size);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
|
||||
return server->reply_size;
|
||||
|
||||
case NCP_IOC_GETMOUNTUID:
|
||||
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
||||
sizeof(uid_t))) != 0) {
|
||||
return result;
|
||||
}
|
||||
put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1,579 +0,0 @@
|
||||
#include "ncplib.h"
|
||||
|
||||
typedef __u8 byte;
|
||||
typedef __u16 word;
|
||||
typedef __u32 dword;
|
||||
|
||||
static void
|
||||
assert_server_locked(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
DPRINTK("ncpfs: server not locked!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_byte(struct ncp_server *server, byte x)
|
||||
{
|
||||
assert_server_locked(server);
|
||||
*(byte *)(&(server->packet[server->current_size])) = x;
|
||||
server->current_size += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_word(struct ncp_server *server, word x)
|
||||
{
|
||||
assert_server_locked(server);
|
||||
*(word *)(&(server->packet[server->current_size])) = x;
|
||||
server->current_size += 2;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_dword(struct ncp_server *server, dword x)
|
||||
{
|
||||
assert_server_locked(server);
|
||||
*(dword *)(&(server->packet[server->current_size])) = x;
|
||||
server->current_size += 4;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_mem(struct ncp_server *server, const void *source, int size)
|
||||
{
|
||||
assert_server_locked(server);
|
||||
memcpy(&(server->packet[server->current_size]), source, size);
|
||||
server->current_size += size;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_pstring(struct ncp_server *server, const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
assert_server_locked(server);
|
||||
if (len > 255) {
|
||||
DPRINTK("ncpfs: string too long: %s\n", s);
|
||||
len = 255;
|
||||
}
|
||||
ncp_add_byte(server, len);
|
||||
ncp_add_mem(server, s, len);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_init_request(struct ncp_server *server)
|
||||
{
|
||||
ncp_lock_server(server);
|
||||
|
||||
server->current_size = sizeof(struct ncp_request_header);
|
||||
server->has_subfunction = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_init_request_s(struct ncp_server *server, int subfunction)
|
||||
{
|
||||
ncp_init_request(server);
|
||||
ncp_add_word(server, 0); /* preliminary size */
|
||||
|
||||
ncp_add_byte(server, subfunction);
|
||||
|
||||
server->has_subfunction = 1;
|
||||
}
|
||||
|
||||
static char *
|
||||
ncp_reply_data(struct ncp_server *server, int offset)
|
||||
{
|
||||
return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
|
||||
}
|
||||
|
||||
static byte
|
||||
ncp_reply_byte(struct ncp_server *server, int offset)
|
||||
{
|
||||
return *(byte *)(ncp_reply_data(server, offset));
|
||||
}
|
||||
|
||||
static word
|
||||
ncp_reply_word(struct ncp_server *server, int offset)
|
||||
{
|
||||
return *(word *)(ncp_reply_data(server, offset));
|
||||
}
|
||||
|
||||
static dword
|
||||
ncp_reply_dword(struct ncp_server *server, int offset)
|
||||
{
|
||||
return *(dword *)(ncp_reply_data(server, offset));
|
||||
}
|
||||
|
||||
int
|
||||
ncp_negotiate_buffersize(struct ncp_server *server,
|
||||
int size, int *target) {
|
||||
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_word(server, htons(size));
|
||||
|
||||
if ((result = ncp_request(server, 33)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*target =min(ntohs(ncp_reply_word(server, 0)), size);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
struct ncp_volume_info *target)
|
||||
{
|
||||
int result;
|
||||
int len;
|
||||
|
||||
ncp_init_request_s(server, 44);
|
||||
ncp_add_byte(server, n);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
target->total_blocks = ncp_reply_dword(server, 0);
|
||||
target->free_blocks = ncp_reply_dword(server, 4);
|
||||
target->purgeable_blocks = ncp_reply_dword(server, 8);
|
||||
target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
|
||||
target->total_dir_entries = ncp_reply_dword(server, 16);
|
||||
target->available_dir_entries = ncp_reply_dword(server, 20);
|
||||
target->sectors_per_block = ncp_reply_byte(server, 28);
|
||||
|
||||
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
||||
|
||||
len = ncp_reply_byte(server, 29);
|
||||
if (len > NCP_VOLNAME_LEN) {
|
||||
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
||||
ncp_unlock_server(server);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request_s(server, 5);
|
||||
ncp_add_pstring(server, name);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*target = ncp_reply_byte(server, 0);
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_close_file(struct ncp_server *server, const char *file_id)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 0);
|
||||
ncp_add_mem(server, file_id, 6);
|
||||
|
||||
if ((result = ncp_request(server, 66)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_handle_path(struct ncp_server *server,
|
||||
__u8 vol_num,
|
||||
__u32 dir_base, int have_dir_base,
|
||||
char *path)
|
||||
{
|
||||
ncp_add_byte(server, vol_num);
|
||||
ncp_add_dword(server, dir_base);
|
||||
if (have_dir_base != 0) {
|
||||
ncp_add_byte(server, 1); /* dir_base */
|
||||
} else {
|
||||
ncp_add_byte(server, 0xff); /* no handle */
|
||||
}
|
||||
if (path != NULL) {
|
||||
ncp_add_byte(server, 1); /* 1 component */
|
||||
ncp_add_pstring(server, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
ncp_add_byte(server, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
||||
{
|
||||
__u8 *name_len;
|
||||
const int info_struct_size = sizeof(struct nw_info_struct) - 257;
|
||||
|
||||
memcpy(target, structure, info_struct_size);
|
||||
name_len = structure + info_struct_size;
|
||||
target->nameLen = *name_len;
|
||||
strncpy(target->entryName, name_len+1, *name_len);
|
||||
target->entryName[*name_len] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
int result;
|
||||
char *volname = NULL;
|
||||
|
||||
if (target == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir == NULL) {
|
||||
|
||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
||||
|
||||
/* Access a volume's root directory */
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte (server, 8);
|
||||
ncp_unlock_server(server);
|
||||
volname = path;
|
||||
path = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
vol_num = dir->volNumber;
|
||||
dir_base = dir->DosDirNum;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 6); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
||||
ncp_add_word(server, 0xff); /* get all */
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
||||
|
||||
if (volname != NULL) {
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
}
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
struct nw_info_struct *file,
|
||||
__u32 info_mask,
|
||||
struct nw_modify_dos_info *info)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 7); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||
|
||||
ncp_add_dword(server, info_mask);
|
||||
ncp_add_mem(server, info, sizeof(*info));
|
||||
ncp_add_handle_path(server, file->volNumber,
|
||||
file->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 8); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
|
||||
{
|
||||
__u16 *dest = (__u16 *) ret;
|
||||
memcpy(&(dest[1]), &sfd, 4);
|
||||
dest[0] = dest[1] + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If both dir and name are NULL, then in target there's already a
|
||||
looked-up entry that wants to be opened. */
|
||||
int
|
||||
ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name,
|
||||
int open_create_mode,
|
||||
__u32 create_attributes,
|
||||
int desired_acc_rights,
|
||||
struct nw_file_info *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 1); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, open_create_mode);
|
||||
ncp_add_word(server, 0x8006);
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_dword(server, create_attributes);
|
||||
/* The desired acc rights seem to be the inherited rights mask
|
||||
for directories */
|
||||
ncp_add_word(server, desired_acc_rights);
|
||||
|
||||
if (dir != NULL) {
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
} else {
|
||||
ncp_add_handle_path(server,
|
||||
target->i.volNumber, target->i.DosDirNum,
|
||||
1, NULL);
|
||||
}
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
target->opened = 1;
|
||||
target->server_file_handle = ncp_reply_dword(server, 0);
|
||||
target->open_create_action = ncp_reply_byte(server, 4);
|
||||
|
||||
if (dir != NULL) {
|
||||
/* in target there's a new finfo to fill */
|
||||
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
|
||||
}
|
||||
|
||||
ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncp_initialize_search(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
struct nw_search_sequence *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 2); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search for everything */
|
||||
int
|
||||
ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_search_sequence *seq,
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 3); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* data stream (???) */
|
||||
ncp_add_word(server, 0xffff); /* Search attribs */
|
||||
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
||||
ncp_add_mem(server, seq, 9);
|
||||
ncp_add_byte(server, 2); /* 2 byte pattern */
|
||||
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
||||
ncp_add_byte(server, '*');
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
|
||||
ncp_extract_file_info(ncp_reply_data(server, 10), target);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *old_dir, char *old_name,
|
||||
struct nw_info_struct *new_dir, char *new_name)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ( (old_dir == NULL) || (old_name == NULL)
|
||||
|| (new_dir == NULL) || (new_name == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 4); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 1); /* rename flag */
|
||||
ncp_add_word(server, 0x8006); /* search attributes */
|
||||
|
||||
/* source Handle Path */
|
||||
ncp_add_byte(server, old_dir->volNumber);
|
||||
ncp_add_dword(server, old_dir->DosDirNum);
|
||||
ncp_add_byte(server, 1);
|
||||
ncp_add_byte(server, 1); /* 1 source component */
|
||||
|
||||
/* dest Handle Path */
|
||||
ncp_add_byte(server, new_dir->volNumber);
|
||||
ncp_add_dword(server, new_dir->DosDirNum);
|
||||
ncp_add_byte(server, 1);
|
||||
ncp_add_byte(server, 1); /* 1 destination component */
|
||||
|
||||
/* source path string */
|
||||
ncp_add_pstring(server, old_name);
|
||||
/* dest path string */
|
||||
ncp_add_pstring(server, new_name);
|
||||
|
||||
result = ncp_request(server, 87);
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* We have to transfer to/from user space */
|
||||
int
|
||||
ncp_read(struct ncp_server *server, const char *file_id,
|
||||
__u32 offset, __u16 to_read,
|
||||
char *target, int *bytes_read)
|
||||
{
|
||||
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_read));
|
||||
|
||||
if ((result = ncp_request(server, 72)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
||||
|
||||
memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
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_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*bytes_written = to_write;
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
#ifndef _NCPLIB_H
|
||||
#define _NCPLIB_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_fs_sb.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/string.h>
|
||||
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_negotiate_buffersize(struct ncp_server *server, int size,
|
||||
int *target);
|
||||
int
|
||||
ncp_get_encryption_key(struct ncp_server *server,
|
||||
char *target);
|
||||
int
|
||||
ncp_get_bindery_object_id(struct ncp_server *server,
|
||||
int object_type, char *object_name,
|
||||
struct ncp_bindery_object *target);
|
||||
int
|
||||
ncp_login_encrypted(struct ncp_server *server,
|
||||
struct ncp_bindery_object *object,
|
||||
unsigned char *key,
|
||||
unsigned char *passwd);
|
||||
int
|
||||
ncp_login_user(struct ncp_server *server,
|
||||
unsigned char *username,
|
||||
unsigned char *password);
|
||||
int
|
||||
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
struct ncp_volume_info *target);
|
||||
|
||||
int
|
||||
ncp_get_volume_number(struct ncp_server *server, const char *name,
|
||||
int *target);
|
||||
|
||||
int
|
||||
ncp_file_search_init(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
struct ncp_filesearch_info *target);
|
||||
|
||||
int
|
||||
ncp_file_search_continue(struct ncp_server *server,
|
||||
struct ncp_filesearch_info *fsinfo,
|
||||
int attributes, const char *path,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_get_finfo(struct ncp_server *server,
|
||||
int dir_handle, const char *path, const char *name,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_open_file(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int attr, int access,
|
||||
struct ncp_file_info *target);
|
||||
int
|
||||
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
|
||||
ncp_read(struct ncp_server *server, const char *file_id,
|
||||
__u32 offset, __u16 to_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);
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
struct nw_info_struct *file,
|
||||
__u32 info_mask,
|
||||
struct nw_modify_dos_info *info);
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name);
|
||||
|
||||
int
|
||||
ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name,
|
||||
int open_create_mode,
|
||||
__u32 create_attributes,
|
||||
int desired_acc_rights,
|
||||
struct nw_file_info *target);
|
||||
|
||||
int
|
||||
ncp_initialize_search(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
struct nw_search_sequence *target);
|
||||
|
||||
int
|
||||
ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_search_sequence *seq,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *old_dir, char *old_name,
|
||||
struct nw_info_struct *new_dir, char *new_name);
|
||||
|
||||
|
||||
#endif /* _NCPLIB_H */
|
||||
@@ -1,572 +0,0 @@
|
||||
/*
|
||||
* linux/fs/ncp/sock.c
|
||||
*
|
||||
* Copyright (C) 1992, 1993 Rick Sladkey
|
||||
*
|
||||
* Modified 1995 by Volker Lendecke to be usable for ncp
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/stat.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_fs_sb.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
|
||||
#define _S(nr) (1<<((nr)-1))
|
||||
static int _recvfrom(struct socket *sock, unsigned char *ubuf,
|
||||
int size, int noblock, unsigned flags,
|
||||
struct sockaddr_ipx *sa, int *addr_len)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
|
||||
iov.iov_base = ubuf;
|
||||
iov.iov_len = size;
|
||||
|
||||
msg.msg_name = (void *)sa;
|
||||
msg.msg_namelen = 0;
|
||||
if (addr_len)
|
||||
msg.msg_namelen = *addr_len;
|
||||
msg.msg_accrights = NULL;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
|
||||
}
|
||||
|
||||
static int _sendto(struct socket *sock, const void *buff,
|
||||
int len, int nonblock, unsigned flags,
|
||||
struct sockaddr_ipx *sa, int addr_len)
|
||||
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
|
||||
iov.iov_base = (void *)buff;
|
||||
iov.iov_len = len;
|
||||
|
||||
msg.msg_name = (void *)sa;
|
||||
msg.msg_namelen = addr_len;
|
||||
msg.msg_accrights = NULL;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
{
|
||||
struct socket *sock = sk->socket;
|
||||
|
||||
if (!sk->dead)
|
||||
{
|
||||
unsigned char packet_buf[2];
|
||||
struct sockaddr_ipx sender;
|
||||
int addr_len = sizeof(struct sockaddr_ipx);
|
||||
int result;
|
||||
unsigned short fs;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, &addr_len);
|
||||
|
||||
if ( (result != 2)
|
||||
|| (packet_buf[1] != '?')
|
||||
/* How to check connection number here? */
|
||||
)
|
||||
{
|
||||
/* Error, throw away the complete packet */
|
||||
_recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, &addr_len);
|
||||
|
||||
printk("ncpfs: got strange packet on watchdog "
|
||||
"socket\n");
|
||||
|
||||
} else {
|
||||
int result;
|
||||
DDPRINTK("ncpfs: got watchdog from:\n");
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
||||
" conn:%02X,type:%c\n",
|
||||
htonl(sender.sipx_network),
|
||||
sender.sipx_node[0], sender.sipx_node[1],
|
||||
sender.sipx_node[2], sender.sipx_node[3],
|
||||
sender.sipx_node[4], sender.sipx_node[5],
|
||||
ntohs(sender.sipx_port),
|
||||
packet_buf[0], packet_buf[1]);
|
||||
|
||||
packet_buf[1] = 'Y';
|
||||
result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, sizeof(sender));
|
||||
DDPRINTK("send result: %d\n", result);
|
||||
}
|
||||
set_fs(fs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncp_catch_watchdog(struct ncp_server *server)
|
||||
{
|
||||
struct file *file;
|
||||
struct inode *inode;
|
||||
struct socket *sock;
|
||||
struct sock *sk;
|
||||
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
printk("ncp_catch_watchdog: did not get valid server!\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
printk("ncp_catch_watchdog: sk == NULL");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n",
|
||||
(unsigned int)(sk->data_ready),
|
||||
(unsigned int)(server->data_ready));
|
||||
|
||||
if (sk->data_ready == ncp_wdog_data_ready) {
|
||||
printk("ncp_catch_watchdog: already done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
server->data_ready = sk->data_ready;
|
||||
sk->data_ready = ncp_wdog_data_ready;
|
||||
sk->allocation = GFP_ATOMIC;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_dont_catch_watchdog(struct ncp_server *server)
|
||||
{
|
||||
struct file *file;
|
||||
struct inode *inode;
|
||||
struct socket *sock;
|
||||
struct sock *sk;
|
||||
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"did not get valid server!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
printk("ncp_dont_catch_watchdog: sk == NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (server->data_ready == NULL) {
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"server->data_ready == NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sk->data_ready != ncp_wdog_data_ready) {
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"sk->data_callback != ncp_data_callback\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
|
||||
(unsigned int)(sk->data_ready),
|
||||
(unsigned int)(server->data_ready));
|
||||
|
||||
sk->data_ready = server->data_ready;
|
||||
sk->allocation = GFP_KERNEL;
|
||||
server->data_ready = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define NCP_SLACK_SPACE 1024
|
||||
|
||||
#define _S(nr) (1<<((nr)-1))
|
||||
|
||||
static int
|
||||
do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
{
|
||||
struct file *file;
|
||||
struct inode *inode;
|
||||
struct socket *sock;
|
||||
unsigned short fs;
|
||||
int result;
|
||||
char *start = server->packet;
|
||||
select_table wait_table;
|
||||
struct select_table_entry entry;
|
||||
int (*select) (struct inode *, struct file *, int, select_table *);
|
||||
int init_timeout, max_timeout;
|
||||
int timeout;
|
||||
int retrans;
|
||||
int major_timeout_seen;
|
||||
char *server_name;
|
||||
int n;
|
||||
int addrlen;
|
||||
unsigned long old_mask;
|
||||
|
||||
/* We have to check the result, so store the complete header */
|
||||
struct ncp_request_header request =
|
||||
*((struct ncp_request_header *)(server->packet));
|
||||
|
||||
struct ncp_reply_header reply;
|
||||
|
||||
|
||||
file = server->ncp_filp;
|
||||
inode = file->f_inode;
|
||||
select = file->f_op->select;
|
||||
sock = &inode->u.socket_i;
|
||||
if (!sock) {
|
||||
printk("ncp_rpc_call: socki_lookup failed\n");
|
||||
return -EBADF;
|
||||
}
|
||||
init_timeout = server->m.time_out;
|
||||
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
|
||||
retrans = server->m.retry_count;
|
||||
major_timeout_seen = 0;
|
||||
server_name = server->m.server_name;
|
||||
old_mask = current->blocked;
|
||||
current->blocked |= ~(_S(SIGKILL)
|
||||
#if 0
|
||||
| _S(SIGSTOP)
|
||||
#endif
|
||||
| ((server->m.flags & NCP_MOUNT_INTR)
|
||||
? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
|
||||
? _S(SIGINT) : 0)
|
||||
| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
|
||||
? _S(SIGQUIT) : 0))
|
||||
: 0));
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
htonl(server->m.serv_addr.sipx_network),
|
||||
server->m.serv_addr.sipx_node[0],
|
||||
server->m.serv_addr.sipx_node[1],
|
||||
server->m.serv_addr.sipx_node[2],
|
||||
server->m.serv_addr.sipx_node[3],
|
||||
server->m.serv_addr.sipx_node[4],
|
||||
server->m.serv_addr.sipx_node[5],
|
||||
ntohs(server->m.serv_addr.sipx_port));
|
||||
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
|
||||
"seq: %d",
|
||||
request.type,
|
||||
(request.conn_high << 8) + request.conn_low,
|
||||
request.sequence);
|
||||
DDPRINTK(" func: %d\n",
|
||||
request.function);
|
||||
|
||||
result = _sendto(sock, (void *) start, size, 0, 0,
|
||||
&(server->m.serv_addr),
|
||||
sizeof(server->m.serv_addr));
|
||||
if (result < 0) {
|
||||
printk("ncp_rpc_call: send error = %d\n", result);
|
||||
break;
|
||||
}
|
||||
re_select:
|
||||
wait_table.nr = 0;
|
||||
wait_table.entry = &entry;
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if ( !select(inode, file, SEL_IN, &wait_table)
|
||||
&& !select(inode, file, SEL_IN, NULL)) {
|
||||
if (timeout > max_timeout) {
|
||||
/* JEJB/JSP 2/7/94
|
||||
* This is useful to see if the system is
|
||||
* hanging */
|
||||
printk("NCP max timeout reached on %s\n",
|
||||
server_name);
|
||||
timeout = max_timeout;
|
||||
}
|
||||
current->timeout = jiffies + timeout;
|
||||
schedule();
|
||||
remove_wait_queue(entry.wait_address, &entry.wait);
|
||||
current->state = TASK_RUNNING;
|
||||
if (current->signal & ~current->blocked) {
|
||||
current->timeout = 0;
|
||||
result = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (!current->timeout) {
|
||||
if (n < retrans)
|
||||
continue;
|
||||
if (server->m.flags & NCP_MOUNT_SOFT) {
|
||||
printk("NCP server %s not responding, "
|
||||
"timed out\n", server_name);
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
n = 0;
|
||||
timeout = init_timeout;
|
||||
init_timeout <<= 1;
|
||||
if (!major_timeout_seen) {
|
||||
printk("NCP server %s not responding, "
|
||||
"still trying\n", server_name);
|
||||
}
|
||||
major_timeout_seen = 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
current->timeout = 0;
|
||||
}
|
||||
else if (wait_table.nr)
|
||||
remove_wait_queue(entry.wait_address, &entry.wait);
|
||||
current->state = TASK_RUNNING;
|
||||
addrlen = 0;
|
||||
|
||||
/* Get the header from the next packet using a peek, so keep it
|
||||
* on the recv queue. If it is wrong, it will be some reply
|
||||
* we don't now need, so discard it */
|
||||
result = _recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, MSG_PEEK,
|
||||
NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
if (result == -EAGAIN) {
|
||||
DPRINTK("ncp_rpc_call: bad select ready\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result == -ECONNREFUSED) {
|
||||
DPRINTK("ncp_rpc_call: server playing coy\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result != -ERESTARTSYS) {
|
||||
printk("ncp_rpc_call: recv error = %d\n",
|
||||
-result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( (result == sizeof(reply))
|
||||
&& (reply.type == NCP_POSITIVE_ACK)) {
|
||||
/* Throw away the packet */
|
||||
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
|
||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
goto re_select;
|
||||
}
|
||||
|
||||
DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
|
||||
"seq: %d\n",
|
||||
reply.type,
|
||||
(reply.conn_high << 8) + reply.conn_low,
|
||||
reply.task,
|
||||
reply.sequence);
|
||||
|
||||
if ( (result >= sizeof(reply))
|
||||
&& (reply.type == NCP_REPLY)
|
||||
&& ( (request.type == NCP_ALLOC_SLOT_REQUEST)
|
||||
|| ( (reply.sequence == request.sequence)
|
||||
&& (reply.conn_low == request.conn_low)
|
||||
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
|
||||
&& (reply.conn_high == request.conn_high)))) {
|
||||
if (major_timeout_seen)
|
||||
printk("NCP server %s OK\n", server_name);
|
||||
break;
|
||||
}
|
||||
/* JEJB/JSP 2/7/94
|
||||
* we have xid mismatch, so discard the packet and start
|
||||
* again. What a hack! but I can't call recvfrom with
|
||||
* a null buffer yet. */
|
||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
|
||||
&addrlen);
|
||||
#if 1
|
||||
printk("ncp_rpc_call: reply mismatch\n");
|
||||
#endif
|
||||
goto re_select;
|
||||
}
|
||||
/*
|
||||
* we have the correct reply, so read into the correct place and
|
||||
* return it
|
||||
*/
|
||||
result = _recvfrom(sock, (void *)start, server->packet_size, 1, 0,
|
||||
NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
printk("NCP: notice message: result=%d\n", result);
|
||||
} else if (result < sizeof(struct ncp_reply_header)) {
|
||||
printk("NCP: just caught a too small read memory size..., "
|
||||
"email to NET channel\n");
|
||||
printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
|
||||
result = -EIO;
|
||||
}
|
||||
|
||||
current->blocked = old_mask;
|
||||
set_fs(fs);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We need the server to be locked here, so check!
|
||||
*/
|
||||
|
||||
static int
|
||||
ncp_do_request(struct ncp_server *server, int size)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
printk("ncpfs: Server not locked!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return do_ncp_rpc_call(server, size);
|
||||
}
|
||||
|
||||
/* ncp_do_request assures that at least a complete reply header is
|
||||
* received. It assumes that server->current_size contains the ncp
|
||||
* request size */
|
||||
int
|
||||
ncp_request(struct ncp_server *server, int function)
|
||||
{
|
||||
struct ncp_request_header *h
|
||||
= (struct ncp_request_header *)(server->packet);
|
||||
struct ncp_reply_header *reply
|
||||
= (struct ncp_reply_header *)(server->packet);
|
||||
|
||||
int request_size = server->current_size
|
||||
- sizeof(struct ncp_request_header);
|
||||
|
||||
int result;
|
||||
|
||||
if (server->has_subfunction != 0) {
|
||||
*(__u16 *)&(h->data[0]) = request_size - 2;
|
||||
}
|
||||
|
||||
h->type = NCP_REQUEST;
|
||||
|
||||
server->sequence += 1;
|
||||
h->sequence = server->sequence;
|
||||
h->conn_low = (server->connection) & 0xff;
|
||||
h->conn_high = ((server->connection) & 0xff00) >> 8;
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = function;
|
||||
|
||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) {
|
||||
DPRINTK("ncp_request_error: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
server->completion = reply->completion_code;
|
||||
server->conn_status = reply->connection_state;
|
||||
server->reply_size = result;
|
||||
server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
|
||||
|
||||
result = reply->completion_code;
|
||||
|
||||
if (result != 0) {
|
||||
DPRINTK("ncp_completion_code: %d\n", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_connect(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_request_header *h
|
||||
= (struct ncp_request_header *)(server->packet);
|
||||
int result;
|
||||
|
||||
h->type = NCP_ALLOC_SLOT_REQUEST;
|
||||
|
||||
server->sequence = 0;
|
||||
h->sequence = server->sequence;
|
||||
h->conn_low = 0xff;
|
||||
h->conn_high = 0xff;
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = 0;
|
||||
|
||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
server->sequence = 0;
|
||||
server->connection = h->conn_low + (h->conn_high * 256);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_disconnect(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_request_header *h
|
||||
= (struct ncp_request_header *)(server->packet);
|
||||
|
||||
h->type = NCP_DEALLOC_SLOT_REQUEST;
|
||||
|
||||
server->sequence += 1;
|
||||
h->sequence = server->sequence;
|
||||
h->conn_low = (server->connection) & 0xff;
|
||||
h->conn_high = ((server->connection) & 0xff00) >> 8;
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = 0;
|
||||
|
||||
return ncp_do_request(server, sizeof(*h));
|
||||
}
|
||||
|
||||
void
|
||||
ncp_lock_server(struct ncp_server *server)
|
||||
{
|
||||
#if 1
|
||||
/* For testing, only 1 process */
|
||||
if (server->lock != 0) {
|
||||
DPRINTK("ncpfs: server locked!!!\n");
|
||||
}
|
||||
#endif
|
||||
while (server->lock)
|
||||
sleep_on(&server->wait);
|
||||
server->lock = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_unlock_server(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock != 1) {
|
||||
printk("ncp_unlock_server: was not locked!\n");
|
||||
}
|
||||
|
||||
server->lock = 0;
|
||||
wake_up(&server->wait);
|
||||
}
|
||||
|
||||
18
kernel-2.0/README
Normal file
18
kernel-2.0/README
Normal file
@@ -0,0 +1,18 @@
|
||||
This directory contains the patch you have to apply to the Linux
|
||||
kernel if you want to use the support for long file names using the
|
||||
OS/2 namespace on the NetWare server. It did not make it into 2.0, but
|
||||
patching your kernel is really no problem.
|
||||
|
||||
To apply this patch, please take a clean Linux kernel. This patch is
|
||||
against Linux 2.0.7, but any later kernel version in the 2.0.x series
|
||||
should also work fine. Please perform the following two steps:
|
||||
|
||||
cd /usr/src/linux
|
||||
patch -p1 </path_to_ncpfs/kernel-2.0/lfn-2.0.7.diff
|
||||
|
||||
Please do not forget the -p1 flag for patch. Here I assumed that your
|
||||
linux kernel resides in /usr/src/linux. After these two steps, you
|
||||
should recompile your kernel the normal way. If anything goes wrong,
|
||||
PLEASE first consult the file /usr/src/linux/README for more
|
||||
information.
|
||||
|
||||
498
kernel-2.0/lfn-2.0.7.diff
Normal file
498
kernel-2.0/lfn-2.0.7.diff
Normal file
@@ -0,0 +1,498 @@
|
||||
diff -urN 2.0.7/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
|
||||
--- 2.0.7/fs/ncpfs/dir.c Mon Jul 8 17:19:03 1996
|
||||
+++ linux/fs/ncpfs/dir.c Tue Jul 16 17:35:07 1996
|
||||
@@ -92,6 +92,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+ncp_namespace(struct inode *i)
|
||||
+{
|
||||
+ struct ncp_server *server = NCP_SERVER(i);
|
||||
+ struct nw_info_struct *info = NCP_ISTRUCT(i);
|
||||
+ return server->name_space[info->volNumber];
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+ncp_preserve_case(struct inode *i)
|
||||
+{
|
||||
+ return (ncp_namespace(i) == NW_NS_OS2);
|
||||
+}
|
||||
+
|
||||
static struct file_operations ncp_dir_operations = {
|
||||
NULL, /* lseek - default */
|
||||
ncp_dir_read, /* read - bad */
|
||||
@@ -128,7 +142,7 @@
|
||||
/* Here we encapsulate the inode number handling that depends upon the
|
||||
* mount mode: When we mount a complete server, the memory address of
|
||||
* the ncp_inode_info is used as the inode number. When only a single
|
||||
- * volume is mounted, then the DosDirNum is used as the inode
|
||||
+ * volume is mounted, then the dirEntNum is used as the inode
|
||||
* number. As this is unique for the complete volume, this should
|
||||
* enable the NFS exportability of a ncpfs-mounted volume.
|
||||
*/
|
||||
@@ -143,7 +157,7 @@
|
||||
ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info)
|
||||
{
|
||||
return ncp_single_volume(server)
|
||||
- ? info->finfo.i.DosDirNum : (ino_t)info;
|
||||
+ ? info->finfo.i.dirEntNum : (ino_t)info;
|
||||
}
|
||||
|
||||
static inline int
|
||||
@@ -177,8 +191,6 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-
|
||||
-
|
||||
static int
|
||||
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||
{
|
||||
@@ -326,9 +338,12 @@
|
||||
c_last_returned_index = 0;
|
||||
index = 0;
|
||||
|
||||
- for (i = 0; i < c_size; i++)
|
||||
+ if (!ncp_preserve_case(inode))
|
||||
{
|
||||
- str_lower(c_entry[i].i.entryName);
|
||||
+ for (i = 0; i < c_size; i++)
|
||||
+ {
|
||||
+ str_lower(c_entry[i].i.entryName);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,7 +360,7 @@
|
||||
|
||||
if (ncp_single_volume(server))
|
||||
{
|
||||
- ino = (ino_t)(entry->i.DosDirNum);
|
||||
+ ino = (ino_t)(entry->i.dirEntNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -652,7 +667,7 @@
|
||||
root->finfo.opened = 0;
|
||||
i->attributes = aDIR;
|
||||
i->dataStreamSize = 1024;
|
||||
- i->DosDirNum = 0;
|
||||
+ i->dirEntNum = i->DosDirNum = 0;
|
||||
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
|
||||
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
|
||||
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
|
||||
@@ -729,7 +744,7 @@
|
||||
|
||||
do
|
||||
{
|
||||
- if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
|
||||
+ if ( (result->dir->finfo.i.dirEntNum == dir_info->dirEntNum)
|
||||
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
|
||||
&& (strcmp(result->finfo.i.entryName, name) == 0)
|
||||
/* The root dir is never looked up using this
|
||||
@@ -757,6 +772,7 @@
|
||||
struct ncp_server *server;
|
||||
struct ncp_inode_info *result_info;
|
||||
int found_in_cache;
|
||||
+ int down_case = 0;
|
||||
char name[len+1];
|
||||
|
||||
*result = NULL;
|
||||
@@ -867,20 +883,26 @@
|
||||
if (found_in_cache == 0)
|
||||
{
|
||||
int res;
|
||||
- str_upper(name);
|
||||
|
||||
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
||||
NCP_ISTRUCT(dir)->entryName, name);
|
||||
|
||||
if (ncp_is_server_root(dir))
|
||||
{
|
||||
+ str_upper(name);
|
||||
+ down_case = 1;
|
||||
res = ncp_lookup_volume(server, name, &(finfo.i));
|
||||
}
|
||||
else
|
||||
{
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_upper(name);
|
||||
+ down_case = 1;
|
||||
+ }
|
||||
res = ncp_obtain_info(server,
|
||||
NCP_ISTRUCT(dir)->volNumber,
|
||||
- NCP_ISTRUCT(dir)->DosDirNum,
|
||||
+ NCP_ISTRUCT(dir)->dirEntNum,
|
||||
name, &(finfo.i));
|
||||
}
|
||||
if (res != 0)
|
||||
@@ -892,7 +914,11 @@
|
||||
}
|
||||
|
||||
finfo.opened = 0;
|
||||
- str_lower(finfo.i.entryName);
|
||||
+
|
||||
+ if (down_case != 0)
|
||||
+ {
|
||||
+ str_lower(finfo.i.entryName);
|
||||
+ }
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo)))
|
||||
{
|
||||
@@ -929,7 +955,11 @@
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
- str_upper(_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_upper(_name);
|
||||
+ }
|
||||
|
||||
lock_super(dir->i_sb);
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||
@@ -946,7 +976,11 @@
|
||||
|
||||
ncp_invalid_dir_cache(dir);
|
||||
|
||||
- str_lower(finfo.i.entryName);
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_lower(finfo.i.entryName);
|
||||
+ }
|
||||
+
|
||||
finfo.access = O_RDWR;
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo)) < 0)
|
||||
@@ -980,7 +1014,11 @@
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
- str_upper(_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_upper(_name);
|
||||
+ }
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
@@ -1038,7 +1076,11 @@
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
- str_upper(_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_upper(_name);
|
||||
+ }
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
@@ -1081,7 +1123,11 @@
|
||||
{
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
- str_upper(_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(dir))
|
||||
+ {
|
||||
+ str_upper(_name);
|
||||
+ }
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
@@ -1136,11 +1182,19 @@
|
||||
|
||||
strncpy(_old_name, old_name, old_len);
|
||||
_old_name[old_len] = '\0';
|
||||
- str_upper(_old_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(old_dir))
|
||||
+ {
|
||||
+ str_upper(_old_name);
|
||||
+ }
|
||||
|
||||
strncpy(_new_name, new_name, new_len);
|
||||
_new_name[new_len] = '\0';
|
||||
- str_upper(_new_name);
|
||||
+
|
||||
+ if (!ncp_preserve_case(new_dir))
|
||||
+ {
|
||||
+ str_upper(_new_name);
|
||||
+ }
|
||||
|
||||
res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
|
||||
NCP_ISTRUCT(old_dir), _old_name,
|
||||
diff -urN 2.0.7/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
|
||||
--- 2.0.7/fs/ncpfs/ncplib_kernel.c Thu Apr 18 08:40:28 1996
|
||||
+++ linux/fs/ncpfs/ncplib_kernel.c Tue Jul 16 10:52:33 1996
|
||||
@@ -190,25 +190,6 @@
|
||||
}
|
||||
|
||||
int
|
||||
-ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
|
||||
-{
|
||||
- int result;
|
||||
-
|
||||
- ncp_init_request_s(server, 5);
|
||||
- ncp_add_pstring(server, name);
|
||||
-
|
||||
- if ((result = ncp_request(server, 22)) != 0)
|
||||
- {
|
||||
- ncp_unlock_server(server);
|
||||
- return result;
|
||||
- }
|
||||
-
|
||||
- *target = ncp_reply_byte(server, 0);
|
||||
- ncp_unlock_server(server);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int
|
||||
ncp_close_file(struct ncp_server *server, const char *file_id)
|
||||
{
|
||||
int result;
|
||||
@@ -278,8 +259,8 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 6); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
- ncp_add_byte(server, 0); /* dos name space as dest */
|
||||
+ ncp_add_byte(server, server->name_space[vol_num]);
|
||||
+ ncp_add_byte(server, server->name_space[vol_num]);
|
||||
ncp_add_word(server, 0xff); /* get all */
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
|
||||
@@ -295,20 +276,57 @@
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+ncp_has_os2_namespace(struct ncp_server *server, __u8 volume)
|
||||
+{
|
||||
+ int result;
|
||||
+ __u8 *namespace;
|
||||
+ __u16 no_namespaces;
|
||||
+
|
||||
+ ncp_init_request(server);
|
||||
+ ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
|
||||
+ ncp_add_word(server, 0);
|
||||
+ ncp_add_byte(server, volume);
|
||||
+
|
||||
+ if ((result = ncp_request(server, 87)) != 0)
|
||||
+ {
|
||||
+ ncp_unlock_server(server);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ no_namespaces = ncp_reply_word(server, 0);
|
||||
+ namespace = ncp_reply_data(server, 2);
|
||||
+
|
||||
+ while (no_namespaces > 0)
|
||||
+ {
|
||||
+ DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume);
|
||||
+
|
||||
+ if (*namespace == 4)
|
||||
+ {
|
||||
+ DPRINTK("get_namespaces: found OS2\n");
|
||||
+ ncp_unlock_server(server);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ namespace += 1;
|
||||
+ no_namespaces -= 1;
|
||||
+ }
|
||||
+ ncp_unlock_server(server);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
int result;
|
||||
- __u8 vol_num;
|
||||
- __u32 dir_base;
|
||||
+ int volnum;
|
||||
|
||||
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
||||
- ncp_add_byte(server, 0); /* DOS name space */
|
||||
+ ncp_add_byte(server, 0); /* DOS namespace */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
@@ -325,20 +343,19 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
- dir_base = ncp_reply_dword(server, 4);
|
||||
- vol_num = ncp_reply_byte(server, 8);
|
||||
+ memset(target, 0, sizeof(*target));
|
||||
+ target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
|
||||
+ target->volNumber = volnum = ncp_reply_byte(server, 8);
|
||||
ncp_unlock_server(server);
|
||||
|
||||
- if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
|
||||
- target)) != 0)
|
||||
- {
|
||||
- return result;
|
||||
- }
|
||||
+ server->name_space[volnum] = ncp_has_os2_namespace(server,volnum)?4:0;
|
||||
|
||||
- DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
|
||||
+ DPRINTK("lookup_vol: namespace[%d] = %d\n",
|
||||
+ volnum, server->name_space[volnum]);
|
||||
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
+ target->attributes = aDIR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -352,14 +369,14 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 7); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[file->volNumber]);
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||
|
||||
ncp_add_dword(server, info_mask);
|
||||
ncp_add_mem(server, info, sizeof(*info));
|
||||
ncp_add_handle_path(server, file->volNumber,
|
||||
- file->DosDirNum, 1, NULL);
|
||||
+ file->dirEntNum, 1, NULL);
|
||||
|
||||
result = ncp_request(server, 87);
|
||||
ncp_unlock_server(server);
|
||||
@@ -374,11 +391,11 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 8); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[dir->volNumber]);
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
- dir->DosDirNum, 1, name);
|
||||
+ dir->dirEntNum, 1, name);
|
||||
|
||||
result = ncp_request(server, 87);
|
||||
ncp_unlock_server(server);
|
||||
@@ -406,15 +423,16 @@
|
||||
{
|
||||
int result;
|
||||
__u16 search_attribs = 0x0006;
|
||||
+ __u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
|
||||
|
||||
if ((create_attributes & aDIR) != 0)
|
||||
{
|
||||
- search_attribs |= 0x8000;
|
||||
- }
|
||||
+ search_attribs |= 0x8000;
|
||||
+}
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 1); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[volume]);
|
||||
ncp_add_byte(server, open_create_mode);
|
||||
ncp_add_word(server, search_attribs);
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
@@ -425,13 +443,11 @@
|
||||
|
||||
if (dir != NULL)
|
||||
{
|
||||
- ncp_add_handle_path(server, dir->volNumber,
|
||||
- dir->DosDirNum, 1, name);
|
||||
+ ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
- ncp_add_handle_path(server,
|
||||
- target->i.volNumber, target->i.DosDirNum,
|
||||
+ ncp_add_handle_path(server, volume, target->i.dirEntNum,
|
||||
1, NULL);
|
||||
}
|
||||
|
||||
@@ -467,9 +483,9 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 2); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[dir->volNumber]);
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
- ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
|
||||
+ ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
@@ -493,7 +509,7 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 3); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[seq->volNumber]);
|
||||
ncp_add_byte(server, 0); /* data stream (???) */
|
||||
ncp_add_word(server, 0xffff); /* Search attribs */
|
||||
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
||||
@@ -528,19 +544,19 @@
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 4); /* subfunction */
|
||||
- ncp_add_byte(server, 0); /* dos name space */
|
||||
+ ncp_add_byte(server, server->name_space[old_dir->volNumber]);
|
||||
ncp_add_byte(server, 1); /* rename flag */
|
||||
ncp_add_word(server, 0x8006); /* search attributes */
|
||||
|
||||
/* source Handle Path */
|
||||
ncp_add_byte(server, old_dir->volNumber);
|
||||
- ncp_add_dword(server, old_dir->DosDirNum);
|
||||
+ ncp_add_dword(server, old_dir->dirEntNum);
|
||||
ncp_add_byte(server, 1);
|
||||
ncp_add_byte(server, 1); /* 1 source component */
|
||||
|
||||
/* dest Handle Path */
|
||||
ncp_add_byte(server, new_dir->volNumber);
|
||||
- ncp_add_dword(server, new_dir->DosDirNum);
|
||||
+ ncp_add_dword(server, new_dir->dirEntNum);
|
||||
ncp_add_byte(server, 1);
|
||||
ncp_add_byte(server, 1); /* 1 destination component */
|
||||
|
||||
diff -urN 2.0.7/include/linux/ncp.h linux/include/linux/ncp.h
|
||||
--- 2.0.7/include/linux/ncp.h Thu Apr 18 08:40:36 1996
|
||||
+++ linux/include/linux/ncp.h Tue Jul 16 17:27:45 1996
|
||||
@@ -116,6 +116,12 @@
|
||||
__u16 update_time;
|
||||
};
|
||||
|
||||
+/* Defines for Name Spaces */
|
||||
+#define NW_NS_DOS 0
|
||||
+#define NW_NS_MAC 1
|
||||
+#define NW_NS_NFS 2
|
||||
+#define NW_NS_FTAM 3
|
||||
+#define NW_NS_OS2 4
|
||||
|
||||
/* Defines for ReturnInformationMask */
|
||||
#define RIM_NAME (0x0001L)
|
||||
diff -urN 2.0.7/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
|
||||
--- 2.0.7/include/linux/ncp_fs_sb.h Thu Apr 18 08:40:36 1996
|
||||
+++ linux/include/linux/ncp_fs_sb.h Tue Jul 16 17:35:17 1996
|
||||
@@ -21,6 +21,8 @@
|
||||
interest for us later, so we store
|
||||
it completely. */
|
||||
|
||||
+ __u8 name_space[NCP_NUMBER_OF_VOLUMES];
|
||||
+
|
||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||
struct file *msg_filp; /* File pointer to message socket */
|
||||
20
man/Makefile
Normal file
20
man/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
MAN1= slist nprint pqlist nsend pserver ncopy npasswd
|
||||
MAN1 += nwbols nwboprops nwbpvalues
|
||||
MAN5= nwclient
|
||||
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \
|
||||
ipx_route nwmsg
|
||||
MAN8 += nwbocreate nwborm nwbpadd nwbpcreate nwbprm
|
||||
MAN8 += nwgrant nwrevoke
|
||||
|
||||
|
||||
|
||||
all:
|
||||
|
||||
dep:
|
||||
|
||||
install:
|
||||
for i in $(MAN1); do install $$i.1 -m 755 /usr/local/man/man1; done
|
||||
for i in $(MAN5); do install $$i.5 -m 755 /usr/local/man/man5; done
|
||||
for i in $(MAN8); do install $$i.8 -m 755 /usr/local/man/man8; done
|
||||
|
||||
clean:
|
||||
67
man/ipx_interface.8
Normal file
67
man/ipx_interface.8
Normal file
@@ -0,0 +1,67 @@
|
||||
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_interface \- add, delete, or display an IPX interface
|
||||
.SH SYNOPSIS
|
||||
.B ipx_interface
|
||||
add [-p] device frame_type [network number]
|
||||
.LP
|
||||
.B ipx_interface
|
||||
del device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
delall
|
||||
.LP
|
||||
.B ipx_interface
|
||||
check device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
help
|
||||
.SH DESCRIPTION
|
||||
.B ipx_interface
|
||||
adds, deletes, or displays IPX interfaces depending on the option selected.
|
||||
.P
|
||||
An IPX interface is the item to which IPX sockets are bound.
|
||||
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||
to a physical device and frame type. A sample IPX Interface would be:
|
||||
.LP
|
||||
Network Number: 0x00ABCDEF
|
||||
.LP
|
||||
Device: Eth0
|
||||
.LP
|
||||
Frame Type: 802.2.
|
||||
.P
|
||||
There is a special IPX interface per host known as the
|
||||
.B PRIMARY
|
||||
or default interface.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to create an IPX interface. If the
|
||||
.B -p
|
||||
flag is used, the interface is made
|
||||
.B
|
||||
PRIMARY.
|
||||
The network number can be optionally assigned. If it is not assigned, it
|
||||
is set to 0 which indicates it should be detected from the traffic on the
|
||||
network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete an IPX interface.
|
||||
.TP
|
||||
.I delall
|
||||
This option is used to delete all IPX interfaces.
|
||||
.TP
|
||||
.I check
|
||||
This option is used to display the device, frame type, and network number
|
||||
of an IPX interface.
|
||||
.TP
|
||||
.I help
|
||||
This option displays information about the utility.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH BUGS
|
||||
This functionality really belongs in
|
||||
.B
|
||||
ifconfig(8).
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
32
man/ipx_internal_net.8
Normal file
32
man/ipx_internal_net.8
Normal file
@@ -0,0 +1,32 @@
|
||||
.TH IPX_INTERNAL_NET 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_internal_net \- add or delete the IPX internal network
|
||||
.SH SYNOPSIS
|
||||
.B ipx_internal_net
|
||||
add network_number node_number
|
||||
.LP
|
||||
.B ipx_internal_net
|
||||
del
|
||||
.SH DESCRIPTION
|
||||
.B ipx_internal_net
|
||||
adds or deletes the IPX internal network.
|
||||
An IPX internal network is a special kind of IPX interface that does
|
||||
not have a physical device or frame type. It is used to provide
|
||||
a route-independent address for service providers. Internal networks
|
||||
are optional; however, when one is present it is also the
|
||||
Primary Interface. There can only be one internal network per host.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to create the IPX internal network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete the IPX internal network.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH BUGS
|
||||
This functionality really belongs in
|
||||
.B
|
||||
ifconfig(8).
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
24
man/ipx_route.8
Normal file
24
man/ipx_route.8
Normal file
@@ -0,0 +1,24 @@
|
||||
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_route \- add or delete IPX route
|
||||
.SH SYNOPSIS
|
||||
.B ipx_route
|
||||
add target_network router_network router_node
|
||||
.LP
|
||||
.B ipx_route
|
||||
del target_network
|
||||
.SH DESCRIPTION
|
||||
.B ipx_route
|
||||
adds or deletes an IPX route.
|
||||
The kernel IPX stores only one route per target network at a time.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to set up the route to a target network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete the route to a target network.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
96
man/ncopy.1
Normal file
96
man/ncopy.1
Normal file
@@ -0,0 +1,96 @@
|
||||
.\"
|
||||
.\" Man page for the ncopy program
|
||||
.\"
|
||||
.TH NCOPY 1 17/03/1996 ncopy ncopy
|
||||
.SH NAME
|
||||
ncopy \- NetWare file copy
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B ncopy -V
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file destinationfile|directory
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file1
|
||||
[
|
||||
.B file2 ...
|
||||
]
|
||||
.B directory
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B ncopy
|
||||
you can copy files to different locations on a single NetWare file
|
||||
server without generating excess network traffic. The program uses
|
||||
a NetWare function to do the copy rather than transferring the file
|
||||
across the network for both the read and write.
|
||||
|
||||
If the last argument is a directory,
|
||||
.B ncopy
|
||||
will copy the source file(s) into the directory. If only two files
|
||||
are given and the last argument is not a directory, it will copy the
|
||||
source file to the destination file.
|
||||
|
||||
If the source and destination files are not on the same NetWare server
|
||||
(or are not on NetWare servers at all),
|
||||
.B ncopy
|
||||
will do a normal file copy.
|
||||
.SH OPTIONS
|
||||
.B -V
|
||||
.RS 3
|
||||
Show version number and exit
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
Verbose copy. Will show current file and percentage completion.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
Nice NetWare copy. Will sleep for a second between copying blocks on
|
||||
the NetWare server. Gives other people a chance to do some work on
|
||||
the NetWare server when you are copying large files. This has no
|
||||
effect if you are not copying on a NetWare server.
|
||||
.RE
|
||||
|
||||
.B -s
|
||||
.I amount
|
||||
.RS 3
|
||||
Nice time slice factor. Used in conjunction with the
|
||||
.B -n
|
||||
option, this specifies the number of 100K blocks to copy before sleeping.
|
||||
Default is 10. (1 Megabyte)
|
||||
.RE
|
||||
|
||||
.SH BUGS
|
||||
.B ncopy
|
||||
cannot recurse into directories.
|
||||
Does not work on NetWare volumes mounted with the
|
||||
.I -V
|
||||
option to
|
||||
.B ncpmount.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.B ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncopy was written by Brian G. Reid (breid@tim.com) and
|
||||
Tom C. Henderson (thenderson@tim.com).
|
||||
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
|
||||
and ncplib which made ncopy possible.
|
||||
221
man/ncpmount.8
221
man/ncpmount.8
@@ -1,29 +1,27 @@
|
||||
.TH NCPMOUNT 8 25/11/1995 ncpmount ncpmount
|
||||
.TH NCPMOUNT 8 12/27/1995 ncpmount ncpmount
|
||||
.SH NAME
|
||||
ncpmount \- mount program for ncpfs
|
||||
ncpmount \- mount all volumes of a specified Novell fileserver.
|
||||
.SH SYNOPSIS
|
||||
.B ncpmount
|
||||
.B server mount-point
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -n
|
||||
.I
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -s
|
||||
.I server name
|
||||
] [
|
||||
.B -c
|
||||
.I client name
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -c
|
||||
.I client name
|
||||
] [
|
||||
.B -u
|
||||
.I uid
|
||||
] [
|
||||
@@ -35,31 +33,50 @@ ncpmount \- mount program for ncpfs
|
||||
] [
|
||||
.B -d
|
||||
.I dir mode
|
||||
]
|
||||
] [
|
||||
.B -V
|
||||
.I volume
|
||||
] [
|
||||
.B -t
|
||||
.I time_out
|
||||
] [
|
||||
.B -r
|
||||
.I retry_count
|
||||
] [
|
||||
.B -v
|
||||
]
|
||||
mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
This program is an interface to the NCP filesystem.
|
||||
This program is used to mount all volumes of the specified NetWare Fileserver
|
||||
under the specified mount point.
|
||||
|
||||
.B ncpfs
|
||||
is a filesystem which understands the NCP protocol. This is the
|
||||
is a linux filesystem which understands the NCP protocol. This is the
|
||||
protocol Novell NetWare clients use to talk to NetWare servers. ncpfs
|
||||
was inspired by
|
||||
.B lwared,
|
||||
a free NetWare emulator for Linux written by Ales Dryak. See
|
||||
ftp://klokan.sh.cvut.cz/pub/linux for this very intersting program.
|
||||
|
||||
.SH OPTIONS
|
||||
.B server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use on the server.
|
||||
.RE
|
||||
.B ncpmount
|
||||
when invoked with all appropriate arguments attaches, logs in and
|
||||
mounts all of the volumes associated with the specified fileserver that are
|
||||
readable by the user id under the specified mount point.
|
||||
.B ncpmount
|
||||
when invoked without any arguments specifying the fileserver, user id and
|
||||
password checks the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password to use for the
|
||||
specified mount point. See nwclient(5) for more information. Please note
|
||||
that the access permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
.B mount-point
|
||||
.RS 3
|
||||
.B mount-point
|
||||
is the directory you want to mount the filesystem over. It's the same
|
||||
as in the normal mount command.
|
||||
is the directory you want to mount the filesystem over. Its function is the
|
||||
the same as for a normal mount command.
|
||||
|
||||
If the real uid of the caller is not root,
|
||||
.B ncpmount
|
||||
@@ -72,6 +89,13 @@ ncpmount. So
|
||||
can check whether the caller is allowed to unmount the filesystem.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
@@ -80,42 +104,40 @@ is used to print out a short help text.
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
By default passwords are converted to uppercase before they are sent
|
||||
to the server because most servers require this. This option disables this
|
||||
feature ensuring that passwords are sent without any case conversion.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given to mount shares which do not require a password to log in.
|
||||
must be specified for logins that do not have a password configured.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
You may want to give the password required by the server on the
|
||||
command line. You should be careful to use passwords in scripts.
|
||||
specifies the password to use for the Netware user id.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor
|
||||
nor the
|
||||
.B -P
|
||||
are given, ncpmount prompts for a password. This makes it difficult to
|
||||
use in scripts such as /etc/rc. But that's not ncpmount's fault, but a
|
||||
general problem with the fact that you need a password on every
|
||||
login. If anybody has a satisfying solution to this problem, please
|
||||
tell me.
|
||||
arguments are specified ncpmount will prompt for a password. This
|
||||
makes it difficult to use in scripts such as /etc/rc. If you want to
|
||||
have ncpmount work automatically from a script you must include the
|
||||
appropriate option and be very careful to ensure that appopriate file
|
||||
permissions are set for the script that includes your password to
|
||||
ensure that others can not read it.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
If the user name your NetWare administrator gave to you differs
|
||||
from your unix user-id, you should use
|
||||
.B -U
|
||||
to tell the server about you NetWare user name.
|
||||
Specifies the Netware user id to use when logging in to the fileserver. If
|
||||
this option is not specified then ncpmount will attempt to login to the
|
||||
fileserver using the Linux login id of the user invoking ncpmount.
|
||||
.RE
|
||||
|
||||
.B -u
|
||||
@@ -123,18 +145,37 @@ to tell the server about you NetWare user name.
|
||||
.B -g
|
||||
.I gid
|
||||
.RS 3
|
||||
Currently I did not implement a mapping from NetWare users/groups to
|
||||
unix users/groups. Unix requires that each file has an owner
|
||||
and a group it belongs to. With
|
||||
ncpmount does not yet implement a scheme for mapping NetWare users/groups
|
||||
to Linux users/groups. Linux requires that each file has an owner and group id.
|
||||
With
|
||||
.B -u
|
||||
and
|
||||
.B -g
|
||||
you can tell ncpmount which id's it should assign to the files in the
|
||||
mounted direcory.
|
||||
mounted directory.
|
||||
|
||||
The defaults for these values are the current uid and gid.
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I user name
|
||||
.RS 3
|
||||
.B -c
|
||||
names the user who is the
|
||||
.I owner
|
||||
of the connection, where owner does not refer to file ownership (that
|
||||
"owner" is set by the -u argument), but the owner of the mount, ie: who
|
||||
is allowed to call ncpumount on this mount. The default owner of the
|
||||
connection and the mount is the user who called ncpmount. This option
|
||||
allows you to specify that some other user should be set as the owner.
|
||||
|
||||
In this this way it is possible to mount a public read-only directory,
|
||||
but to allow the lp daemon to print on NetWare queues. This is
|
||||
possible because only users who have write permissions on a directory
|
||||
may issue ncp requests over a connection. The exception to this rule
|
||||
is the 'mount owner', who is also granted 'request permission'.
|
||||
.RE
|
||||
|
||||
.B -f
|
||||
.I file mode,
|
||||
.B -d
|
||||
@@ -144,14 +185,11 @@ Like
|
||||
.B -u
|
||||
and
|
||||
.B -g,
|
||||
these options are also used to cover deficiencies in the
|
||||
implementation of ncpfs. I did not implement a scheme to map NetWare
|
||||
permissions to unix permissions. So ncpmount has to be told which
|
||||
permissions it should assign to the mounted files and direcories. The
|
||||
values have to be given as octal numbers. The default values are taken
|
||||
from the current umask, where the file mode is the current umask, and
|
||||
the dir mode adds execute permissions where the file mode gives read
|
||||
permissions.
|
||||
these options are used to determine what permissions should be assigned
|
||||
files and directories of the mounted volumes. The values must be specified
|
||||
as octal numbers. The default values are taken from the current umask, where
|
||||
the file mode is the current umask, and the dir mode adds execute permissions
|
||||
where the file mode gives read permissions.
|
||||
|
||||
Note that these permissions can differ from the rights the server
|
||||
gives to us. If you do not have write permissions on the server, you
|
||||
@@ -159,8 +197,75 @@ can very well choose a file mode that tells that you have. This
|
||||
certainly cannot override the restrictions imposed by the server.
|
||||
.RE
|
||||
|
||||
.B -V
|
||||
.I volume
|
||||
.RS 3
|
||||
There are 2 general ways you can mount a NetWare server's disk space:
|
||||
Either you can mount all volumes under one directory, or you can mount
|
||||
only a single volume.
|
||||
|
||||
When you choose to mount the complete disk space at once, you have the
|
||||
advantage that only one Linux mount point and only one
|
||||
NetWare connection is used for all the volumes of this server. Both of
|
||||
these are limited resources. (Although raising the number of Linux
|
||||
mount points is significantly cheaper than raising the number of
|
||||
available NetWare connections ;-))
|
||||
|
||||
When you specify to mount a single volume by using the option
|
||||
.B -V
|
||||
.I volume,
|
||||
you have the big advantage that nfsd is able to re-export this mounted
|
||||
directory. You must invoke
|
||||
.B nfsd
|
||||
and
|
||||
.B mountd
|
||||
with the option
|
||||
.I --re-export
|
||||
to make nfsd re-export ncpfs mounted directories. This uses one Linux
|
||||
mount point and one NetWare connection per mounted volume. Maybe
|
||||
sometime in the future I will make it possible to mount all volumes on
|
||||
different mount points, using only one connection.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I time_out
|
||||
.RS 3
|
||||
With
|
||||
.B -t
|
||||
you can adjust the time ncpfs waits for the server to answer a request
|
||||
it sent. Use the option to raise the timeout value when your ncpfs
|
||||
connections seem to be unstable although your servers are well
|
||||
up. This can happen when you have very busy servers, or servers that
|
||||
are very far away.
|
||||
|
||||
.I time_out
|
||||
is specified in 1/100s, the current default value is 60.
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I retry_count
|
||||
.RS 3
|
||||
As
|
||||
.B -t, -r
|
||||
can be used to tune the ncpfs connection to the server. With
|
||||
retry_count you can specify how many times ncpfs will attempt to send
|
||||
a packet to the server before it decides the connection is dead. The
|
||||
current default value is 5.
|
||||
|
||||
Currently ncpfs is not too clever when trying to find out that
|
||||
connections are dead. If anybody knows how to do that correctly, as it
|
||||
is done by commercial workstations, please tell me.
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
Print ncpfs version number
|
||||
.RE
|
||||
|
||||
.SH NOTES
|
||||
If you have difficulties in mounting, please make sure that you have configured your ipx subsystem correctly. It is especially important that there is a route to the internal network of your server.
|
||||
You must configure the IPX subsystem before ncpmount will work.
|
||||
It is especially important that there is a route to the internal network
|
||||
of your server.
|
||||
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.B USER / LOGNAME
|
||||
@@ -176,7 +281,7 @@ Most diagnostics issued by ncpfs are logged by syslogd. Normally
|
||||
nothing is printed, only error situations are logged there.
|
||||
|
||||
.SH SEE ALSO
|
||||
.B syslogd(8), ncpumount(8)
|
||||
.B syslogd(8), ncpumount(8), nfsd(8), mountd(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncpfs would not have been possible without lwared, written by Ales
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
.TH NCPUMOUNT 8 25/11/1995 ncpumount ncpumount
|
||||
.TH NCPUMOUNT 8 12/27/1995 ncpumount ncpumount
|
||||
.SH NAME
|
||||
ncpumount \- umount for normal users
|
||||
ncpumount \- unmount a NetWare filesystem mounted with ncpmount.
|
||||
.SH SYNOPSIS
|
||||
.B ncpumount
|
||||
.B mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
With this program, normal users can unmount ncp-filesystems, provided
|
||||
that it is suid root.
|
||||
This utility unmounts a NetWare filesystem that was previously mounted
|
||||
with the ncpmount utility. If the this utility is made suid root then
|
||||
non-root users will also be able to make use of it.
|
||||
|
||||
.B ncpumount
|
||||
has been written to give normal linux-users more control over their
|
||||
|
||||
55
man/npasswd.1
Normal file
55
man/npasswd.1
Normal file
@@ -0,0 +1,55 @@
|
||||
.TH NPASSWD 1 06/22/1996 npasswd npasswd
|
||||
.SH NAME
|
||||
npasswd \- Change a user's password
|
||||
.SH SYNOPSIS
|
||||
.B npasswd
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
]
|
||||
.B -t
|
||||
.I object type
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B npasswd,
|
||||
you can change your password on a NetWare server.
|
||||
.B npasswd
|
||||
asks for the old password and twice for the new password. Then it
|
||||
changes the password on the server.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
With -h npasswd prints a little help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
is the name of the bindery object whose password is to be changed.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
is the bindery object type of the object whose password is to be
|
||||
changed.
|
||||
.RE
|
||||
|
||||
.SH CREDITS
|
||||
npasswd would not have been possible without the work of Guntram
|
||||
Blom. Look at nwcrypt.c for his work.
|
||||
222
man/nprint.1
Normal file
222
man/nprint.1
Normal file
@@ -0,0 +1,222 @@
|
||||
.TH NPRINT 1 12/27/1995 nprint nprint
|
||||
.SH NAME
|
||||
nprint \- NetWare print client
|
||||
.SH SYNOPSIS
|
||||
.B nprint
|
||||
[
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -h
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -q
|
||||
.I queue name
|
||||
] [
|
||||
.B -d
|
||||
.I job description
|
||||
] [
|
||||
.B -p
|
||||
.I path name
|
||||
] [
|
||||
.B -b
|
||||
.I banner name
|
||||
] [
|
||||
.B -f
|
||||
.I file name in banner
|
||||
] [
|
||||
.B -l
|
||||
.I lines
|
||||
] [
|
||||
.B -r
|
||||
.I rows
|
||||
] [
|
||||
.B -c
|
||||
.I copies
|
||||
] [
|
||||
.B -t
|
||||
.I tab size
|
||||
] [
|
||||
.B -T
|
||||
] [
|
||||
.B -N
|
||||
] [
|
||||
.B -F
|
||||
.I form number
|
||||
]
|
||||
.B file
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B nprint,
|
||||
you can print files on print queues of a NetWare file server.
|
||||
|
||||
There are a lot of options, so you should probably wrap some default
|
||||
configurations into some shell scripts.
|
||||
|
||||
.B nprint
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
.B file
|
||||
.RS 3
|
||||
.B file
|
||||
is the name of the file you want to print. If file is '-', or no
|
||||
filename is given, standard input is used.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for the print request at the server.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for the print request at the server. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nprint
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the print request.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -q
|
||||
.I queue name
|
||||
.RS 3
|
||||
.B queue name
|
||||
is the name of the print queue to use at the print server. At
|
||||
present, you must specify it in upper case characters.
|
||||
.RE
|
||||
|
||||
.B -d
|
||||
.I job description
|
||||
.RS 3
|
||||
.B job description
|
||||
is the string that appears in pconsole when you list the jobs for the
|
||||
print queue. It is also printed somewhere on the top of the banner
|
||||
page.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I pathname
|
||||
.RS 3
|
||||
.B pathname
|
||||
is the string you want to be printed on the banner page in the field
|
||||
'path'.
|
||||
.RE
|
||||
|
||||
.B -b
|
||||
.I bannername
|
||||
.RS 3
|
||||
.B bannername
|
||||
is the string (up to 12 characters) you want to appear on the lower
|
||||
part of the banner page.
|
||||
.RE
|
||||
|
||||
.B -f
|
||||
.I filename
|
||||
.RS 3
|
||||
.B filename
|
||||
is the string (up to 12 characters) you want to appear on the upper
|
||||
part of the banner page. Default: the name of the file that is
|
||||
printed, or 'stdin'.
|
||||
.RE
|
||||
|
||||
.B -l
|
||||
.I lines
|
||||
.RS 3
|
||||
.B lines
|
||||
is the number of lines to put on one page. Default: 66
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I rows
|
||||
.RS 3
|
||||
.B rows
|
||||
is the number of rows to put on one page. Default: 80
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I copies
|
||||
.RS 3
|
||||
.B copies
|
||||
tells the print server to the specified number of copies. Default: 1
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I tabs
|
||||
.RS 3
|
||||
.B tabs
|
||||
is the number of spaces to print for a Tab-Character. Default: 8
|
||||
.RE
|
||||
|
||||
.B -T
|
||||
.RS 3
|
||||
tells the print server to expand Tab-Character and use 8 spaces
|
||||
.RE
|
||||
|
||||
.B -N
|
||||
.RS 3
|
||||
tells the print server
|
||||
.B not
|
||||
to use Form Feeds
|
||||
.RE
|
||||
|
||||
.B -F
|
||||
.I form number
|
||||
.RS 3
|
||||
.B form number
|
||||
is the the number of the form to be put into the printer. If it's
|
||||
different from the one currently in the printer, your job is only
|
||||
printed if a printer operator has put in the correct form.
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
nprint was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
108
man/nsend.1
Normal file
108
man/nsend.1
Normal file
@@ -0,0 +1,108 @@
|
||||
.TH NSEND 1 03/21/1996 nsend nsend
|
||||
.SH NAME
|
||||
nsend \- Send messages to users
|
||||
.SH SYNOPSIS
|
||||
.B nsend
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
]
|
||||
.I user message
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B nsend,
|
||||
you can send messages to the user's workstations.
|
||||
|
||||
.B nsend
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B user
|
||||
.RS 3
|
||||
.B user
|
||||
is the NetWare User-ID of the user to receive the message.
|
||||
.RE
|
||||
|
||||
.B message
|
||||
.RS 3
|
||||
.B message
|
||||
is the message to be sent. Please note that this has to be a single
|
||||
command line argument. If you want to send a message that contains
|
||||
spaces, you have to quote them on the command line. For example, to
|
||||
annoy your system administrator, you should try
|
||||
|
||||
nsend supervisor 'I know how this works!'
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
If the user name your NetWare administrator gave to you differs
|
||||
from your unix user-id, you should use
|
||||
.B -U
|
||||
to tell the server about you NetWare user name.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
You may want to give the password required by the server on the
|
||||
command line. You should be careful to use passwords in scripts.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given to mount shares which do not require a password to log in.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, nsend prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.SH BUGS
|
||||
nsend only supports servers with up to 255 connections. I do not know
|
||||
the NCP functions for larger servers. If anybody knows them, please
|
||||
tell me!
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
nsend was written by looking at mars_nwe's message handling. Thanks to
|
||||
Martin Stover <mstover@freeway.de>
|
||||
133
man/nwbocreate.8
Normal file
133
man/nwbocreate.8
Normal file
@@ -0,0 +1,133 @@
|
||||
.TH NWBOCREATE 8 7/9/1996 nwbocreate nwbocreate
|
||||
.SH NAME
|
||||
nwbocreate \- Create a NetWare Bindery Object
|
||||
.SH SYNOPSIS
|
||||
.B nwbocreate
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -r
|
||||
.I read-flag
|
||||
] [
|
||||
.B -w
|
||||
.I write-flag
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbocreate
|
||||
creates the specified NetWare Bindery Object.
|
||||
|
||||
.B nwbocreate
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbocreate
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be created.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I read-flag
|
||||
|
||||
.B -w
|
||||
.I write-flag
|
||||
.RS 3
|
||||
|
||||
Read security and write security may each have one of the following values:
|
||||
|
||||
ANYONE: Anyone may access the object
|
||||
LOGGED: Anyone who is logged in may access the
|
||||
object
|
||||
OBJECT: Anyone who is logged in as the object or
|
||||
SUPERVISOR equivalent may access the
|
||||
object
|
||||
SUPERVISOR: Anyone who is logged in as SUPERVISOR
|
||||
equivalent may access the object
|
||||
NETWARE: Only the Bindery may access the object
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwbocreate was written by Volker Lendecke with the corresponding
|
||||
Caldera utility in mind. See the Changes file of ncpfs for other
|
||||
contributors.
|
||||
117
man/nwbols.1
Normal file
117
man/nwbols.1
Normal file
@@ -0,0 +1,117 @@
|
||||
.TH NWBOLS 1 7/9/1996 nwbols nwbols
|
||||
.SH NAME
|
||||
nwbols \- List NetWare Bindery Objects
|
||||
.SH SYNOPSIS
|
||||
.B nwbols
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -v
|
||||
] [
|
||||
.B pattern
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbols
|
||||
lists the specified NetWare Bindery Objects visible for the user.
|
||||
|
||||
.B nwbols
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbols
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I type
|
||||
.RS 3
|
||||
You can restrict the objects listed by specifying the type of the
|
||||
objects to be listed.
|
||||
.I type
|
||||
must be given as a decimal number.
|
||||
.RE
|
||||
|
||||
.B pattern
|
||||
.RS 3
|
||||
Specifying a pattern is another way to restrict the objects
|
||||
listed. Please note that this pattern is evaluated by the NetWare
|
||||
server. grep would be a better candidate for complex patterns.
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
By default, the object's name, its ID and its type are listed by
|
||||
.B nwbols.
|
||||
In the verbose mode, activated by
|
||||
.B -v,
|
||||
the object flags, its security byte and the properties flag is also
|
||||
listed.
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwbols was written by Volker Lendecke. See the Changes file of ncpfs
|
||||
for other contributors.
|
||||
118
man/nwboprops.1
Normal file
118
man/nwboprops.1
Normal file
@@ -0,0 +1,118 @@
|
||||
.TH NWBOPROPS 1 7/9/1996 nwboprops nwboprops
|
||||
.SH NAME
|
||||
nwboprops \- List properies of a NetWare Bindery Object
|
||||
.SH SYNOPSIS
|
||||
.B nwboprops
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -v
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwboprops
|
||||
lists all the properties of the specified NetWare Bindery Objects.
|
||||
|
||||
.B nwboprops
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwboprops
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be inspected.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
By default, only the property name is listed. In verbose mode,
|
||||
activated by
|
||||
.B -v,
|
||||
the property flag, the property security byte and the value flag are
|
||||
also listed.
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwboprops was written by Volker Lendecke with the corresponding
|
||||
Caldera utility in mind. See the Changes file of ncpfs for other
|
||||
contributors.
|
||||
106
man/nwborm.8
Normal file
106
man/nwborm.8
Normal file
@@ -0,0 +1,106 @@
|
||||
.TH NWBORM 8 7/9/1996 nwborm nwborm
|
||||
.SH NAME
|
||||
nwborm \- Remove a NetWare Bindery Object
|
||||
.SH SYNOPSIS
|
||||
.B nwborm
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwborm
|
||||
removes the specified NetWare Bindery Objects.
|
||||
|
||||
.B nwborm
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwborm
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be deleted.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwborm was written by Volker Lendecke with the corresponding Caldera
|
||||
utility in mind. See the Changes file of ncpfs for other contributors.
|
||||
145
man/nwbpadd.8
Normal file
145
man/nwbpadd.8
Normal file
@@ -0,0 +1,145 @@
|
||||
.TH NWBPADD 8 7/9/1996 nwbpadd nwbpadd
|
||||
.SH NAME
|
||||
nwbpadd \- Set the value of a NetWare Bindery Property
|
||||
.SH SYNOPSIS
|
||||
.B nwbpadd
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -p
|
||||
.I property
|
||||
]
|
||||
.B value
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbpadd
|
||||
sets the value of a ITEM type property, and adds bindery objects to a
|
||||
SET type property.
|
||||
|
||||
.B nwbpadd
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbpadd
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be touched.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I property
|
||||
.RS 3
|
||||
The name of the property to be set.
|
||||
.RE
|
||||
|
||||
.B value
|
||||
.RS 3
|
||||
If property is of type SET, value is an object id in hexadecimal
|
||||
notation. Otherwise, value is either a string value to be written, or
|
||||
a count of bytes to be written. The latter is assumed if more than one
|
||||
value argument is given. The count is decimal, and the following
|
||||
arguments are interpreted as bytes in hexadecimal notation.
|
||||
|
||||
Examples:
|
||||
|
||||
All these examples assume the existence of the file
|
||||
$HOME/.nwclient. Otherwise, the server and user would have to be
|
||||
specified.
|
||||
|
||||
nwbpadd -o linus -t 1 -p groups_i\\'m_in os_hackers
|
||||
|
||||
In this example, user linus is added to the group os_hackers. Please
|
||||
note that the ' has to be quoted.
|
||||
|
||||
nwbpadd -o linus -t 1 -p identification "Linus Torvalds"
|
||||
|
||||
User linus is given his real name :-).
|
||||
|
||||
nwbpadd -o linus -t 1 -p revision -v 04 00 00 01 0b
|
||||
|
||||
A new 4-byte binary value 0x0000010b (hi-lo order, no byte-swapping) is added
|
||||
to the "REVISION" property of the user "linus".
|
||||
|
||||
.SH AUTHORS
|
||||
nwbpadd was written by Volker Lendecke with the corresponding Caldera
|
||||
utility in mind. See the Changes file of ncpfs for other contributors.
|
||||
154
man/nwbpcreate.8
Normal file
154
man/nwbpcreate.8
Normal file
@@ -0,0 +1,154 @@
|
||||
.TH NWBPCREATE 8 7/9/1996 nwbpcreate nwbpcreate
|
||||
.SH NAME
|
||||
nwbpcreate \- Create a NetWare Bindery Propery
|
||||
.SH SYNOPSIS
|
||||
.B nwbpcreate
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -p
|
||||
.I property
|
||||
] [
|
||||
.B -s
|
||||
] [
|
||||
.B -r
|
||||
.I read-flag
|
||||
] [
|
||||
.B -w
|
||||
.I write-flag
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbpcreate
|
||||
creates the specified NetWare Bindery Propery.
|
||||
|
||||
.B nwbpcreate
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbpcreate
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be touched.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I property
|
||||
.RS 3
|
||||
The name of the property to be created.
|
||||
.RE
|
||||
|
||||
.B -s
|
||||
.RS 3
|
||||
By default,
|
||||
.B nwbpcreate
|
||||
creates properties of type ITEM. If you want to create a property of
|
||||
type SET, such as groups_i\\'m_in, you must use the
|
||||
.B -s
|
||||
option.
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I read-flag
|
||||
|
||||
.B -w
|
||||
.I write-flag
|
||||
.RS 3
|
||||
|
||||
Read security and write security may each have one of the following values:
|
||||
|
||||
ANYONE: Anyone may access the property
|
||||
LOGGED: Anyone who is logged in may access the
|
||||
property
|
||||
OBJECT: Anyone who is logged in as the object or
|
||||
SUPERVISOR equivalent may access the
|
||||
property
|
||||
SUPERVISOR: Anyone who is logged in as SUPERVISOR
|
||||
equivalent may access the property
|
||||
NETWARE: Only the Bindery may access the property
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwbpcreate was written by Volker Lendecke with the corresponding
|
||||
Caldera utility in mind. See the Changes file of ncpfs for other
|
||||
contributors.
|
||||
116
man/nwbprm.8
Normal file
116
man/nwbprm.8
Normal file
@@ -0,0 +1,116 @@
|
||||
.TH NWBPRM 8 7/9/1996 nwbprm nwbprm
|
||||
.SH NAME
|
||||
nwbprm \- Remove a NetWare Bindery Propery
|
||||
.SH SYNOPSIS
|
||||
.B nwbprm
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -p
|
||||
.I property
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbprm
|
||||
removes the specified NetWare Bindery Propery.
|
||||
|
||||
.B nwbprm
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbprm
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be touched.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I property
|
||||
.RS 3
|
||||
The name of the property to be removed.
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwbprm was written by Volker Lendecke with the corresponding
|
||||
Caldera utility in mind. See the Changes file of ncpfs for other
|
||||
contributors.
|
||||
128
man/nwbpvalues.1
Normal file
128
man/nwbpvalues.1
Normal file
@@ -0,0 +1,128 @@
|
||||
.TH NWBPVALUES 8 7/9/1996 nwbpvalues nwbpvalues
|
||||
.SH NAME
|
||||
nwbpvalues \- Print a NetWare Bindery Propery's contents
|
||||
.SH SYNOPSIS
|
||||
.B nwbpvalues
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -p
|
||||
.I property
|
||||
] [
|
||||
.B -v
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwbpvalues
|
||||
prints the contents of a SET property.
|
||||
|
||||
.B nwbpvalues
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwbpvalues
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be looked up.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I property
|
||||
.RS 3
|
||||
The name of the property to be printed.
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
By default, the object's name, its ID and its type are listed by
|
||||
.B nwbols.
|
||||
In the verbose mode, activated by
|
||||
.B -v,
|
||||
the object flags, its security byte and the properties flag is also
|
||||
listed.
|
||||
.RE
|
||||
|
||||
.SH AUTHORS
|
||||
nwbpvalues was written by Volker Lendecke with the corresponding
|
||||
Caldera utility in mind. See the Changes file of ncpfs for other
|
||||
contributors.
|
||||
55
man/nwclient.5
Normal file
55
man/nwclient.5
Normal file
@@ -0,0 +1,55 @@
|
||||
.TH NWCLIENT 5 12/27/1995 nwmount nwmount
|
||||
.SH NAME
|
||||
nwclient \- configuration file for NWClient program suite
|
||||
.SH DESCRIPTION
|
||||
This manual page describes the rather simple format of the file
|
||||
.B $HOME/.nwclient,
|
||||
the configuration file for the NWClient program suite.
|
||||
.SH FILE FORMAT
|
||||
The file
|
||||
.B $HOME/.nwclient
|
||||
consists of several lines, each describing a NWClient
|
||||
connection. Lines beginning with # and empty lines are ignored as
|
||||
comments.
|
||||
|
||||
Because you can store passwords in .nwclient, the user programs will
|
||||
only scan .nwclient when only the file owner has access rights to
|
||||
the file. The file must be have permissions 0600.
|
||||
|
||||
To specify a NWClient connection, the name of the file server, the
|
||||
user name to be used and a password is necessary. The server name and
|
||||
the user name are specified as SERVER/USER, and the password is
|
||||
separated by a blank. The password field can be omitted. In this case
|
||||
the user programs will ask you for a password. If you specify the
|
||||
password to be just a dash, then no password is used.
|
||||
|
||||
The first valid specification has a special meaning: If the user does
|
||||
not name a server on the command line, the first specification is used
|
||||
as a 'preferred connection'.
|
||||
|
||||
An example might be the following:
|
||||
|
||||
# The preferred connection, the user is asked
|
||||
# for a password
|
||||
FS311/ME
|
||||
# And a passwordless account on another server
|
||||
CD-SERV/GUEST -
|
||||
|
||||
With these lines in $HOME/.nwclient, calling 'nwmount /mnt' will mount
|
||||
the the file server FS311 with user name ME on /mnt after asking the
|
||||
user for a password.
|
||||
|
||||
\'nwmount -S cd-serv /cd' will silently mount the server cd-serv on /cd.
|
||||
|
||||
.B nprint
|
||||
,
|
||||
.B pqlist
|
||||
and other user programs that require a valid login also look up
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password.
|
||||
|
||||
Please note that the access permissions of .nwclient MUST be 600, for
|
||||
security reasons.
|
||||
|
||||
.SH SEE ALSO
|
||||
.B ncpmount(8), ncpumount(8), slist(1), pqlist(1), nprint(1)
|
||||
148
man/nwgrant.8
Normal file
148
man/nwgrant.8
Normal file
@@ -0,0 +1,148 @@
|
||||
.TH NWGRANT 8 7/9/1996 nwgrant nwgrant
|
||||
.SH NAME
|
||||
nwgrant \- Add Trustee Rights to a directory
|
||||
.SH SYNOPSIS
|
||||
.B nwgrant
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -r
|
||||
.I rights
|
||||
]
|
||||
.B directory
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwgrant
|
||||
adds the specified bindery object with the corresponding trustee
|
||||
rights to the directory.
|
||||
|
||||
.B nwgrant
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwgrant
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be added as trustee.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I rights
|
||||
.RS 3
|
||||
You must tell
|
||||
.B nwgrant
|
||||
which rights it should grant to the bindery object.
|
||||
The new rights for the object is specified by
|
||||
.I rights,
|
||||
which is the sum of the following hexadecimal individual rights values:
|
||||
|
||||
00 = no access
|
||||
01 = read access
|
||||
02 = write access
|
||||
04 = open access
|
||||
08 = create access
|
||||
10 = delete access
|
||||
20 = ownership access
|
||||
40 = search access
|
||||
80 = modify access
|
||||
|
||||
for a possible total of "ff" for all rights.
|
||||
.RE
|
||||
|
||||
.B directory
|
||||
.RS 3
|
||||
You must specify the directory to which to add the object as
|
||||
trustee. This has to be done in fully qualified NetWare notation.
|
||||
|
||||
Example:
|
||||
|
||||
nwgrant -o linus -t 1 -r ff 'data:home\\linus'
|
||||
|
||||
With this example, user linus is given all rights to his home
|
||||
directory on the data volume. This example assumes the existence of
|
||||
the file $HOME/.nwclient.
|
||||
|
||||
.SH AUTHORS
|
||||
nwgrant was written by Volker Lendecke with the corresponding NetWare
|
||||
utility in mind. See the Changes file of ncpfs for other contributors.
|
||||
|
||||
33
man/nwmsg.8
Normal file
33
man/nwmsg.8
Normal file
@@ -0,0 +1,33 @@
|
||||
.TH NWMSG 8 02/29/1996 nwmsg nwmsg
|
||||
.SH NAME
|
||||
nwmsg \- Deliver NetWare user broadcast messages
|
||||
.SH SYNOPSIS
|
||||
.B nwmsg
|
||||
.I mount-point
|
||||
.SH DESCRIPTION
|
||||
.B nwmsg
|
||||
is called by kerneld when a broadcast message arrives from a NetWare
|
||||
server.
|
||||
.B nwmsg
|
||||
fetches this message via the mount point and delivers it to
|
||||
the user using the same way write(1) uses.
|
||||
|
||||
Please note that
|
||||
.I kerneld
|
||||
must run when broadcast messages should be delivered to users.
|
||||
|
||||
NetWare servers can send asynchronous broadcast messages to users,
|
||||
either on explicit request by another user, or when the server is
|
||||
shutdown. The client workstation is informed about this event by an
|
||||
IPX packet on a special socket, the message socket.
|
||||
|
||||
This can happen at any time, so the user has to be informed about this
|
||||
event whenever it appears. I chose to use the kerneld feature of the
|
||||
Linux kernel to call the program nwmsg. For nwmsg, I used the relevant
|
||||
parts of the
|
||||
.I write
|
||||
program, so you can expect the NetWare broadcast
|
||||
messages to appear where user messages would appear.
|
||||
|
||||
.SH SEE ALSO
|
||||
ncpmount(8), kerneld(8), write(1)
|
||||
124
man/nwrevoke.8
Normal file
124
man/nwrevoke.8
Normal file
@@ -0,0 +1,124 @@
|
||||
.TH NWREVOKE 8 7/9/1996 nwrevoke nwrevoke
|
||||
.SH NAME
|
||||
nwrevoke \- Revoke a Trustee Right from a directory
|
||||
.SH SYNOPSIS
|
||||
.B nwrevoke
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -o
|
||||
.I object name
|
||||
] [
|
||||
.B -t
|
||||
.I type
|
||||
] [
|
||||
.B -r
|
||||
.I rights
|
||||
]
|
||||
.B directory
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B nwrevoke
|
||||
revokes the specified bindery object with the corresponding trustee
|
||||
rights from the directory.
|
||||
|
||||
.B nwrevoke
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of $HOME/.nwclient MUST be 600 for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for login.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for login. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nwrevoke
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the login.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -o
|
||||
.I object name
|
||||
.RS 3
|
||||
The name of the object to be added as trustee.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I object type
|
||||
.RS 3
|
||||
The type of the object.
|
||||
.I Object type
|
||||
must be specified as a decimal value. Common values are 1 for user
|
||||
objects, 2 for group objects and 3 for print queues. Other values are
|
||||
allowed, but are usually used for specialized applications.
|
||||
.RE
|
||||
|
||||
.B directory
|
||||
.RS 3
|
||||
You must specify the directory from which to remove the object as
|
||||
trustee. This has to be done in fully qualified NetWare notation.
|
||||
|
||||
Example:
|
||||
|
||||
nwrevoke -o linus -t 1 'src:bsd_src'
|
||||
|
||||
With this example, user linus is removed as trustee from the bsd_src
|
||||
directory on the src volume.
|
||||
|
||||
.SH AUTHORS
|
||||
nwrevoke was written by Volker Lendecke with the corresponding NetWare
|
||||
utility in mind. See the Changes file of ncpfs for other contributors.
|
||||
|
||||
105
man/pqlist.1
Normal file
105
man/pqlist.1
Normal file
@@ -0,0 +1,105 @@
|
||||
.TH PQLIST 1 01/10/1996 pqlist pqlist
|
||||
.SH NAME
|
||||
pqlist \- List available NetWare print queues
|
||||
.SH SYNOPSIS
|
||||
.B pqlist
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.I pattern
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B pqlist
|
||||
lists all the NetWare print queues available to you on some server.
|
||||
If you are already connected to some server, this one is used.
|
||||
|
||||
If pqlist does not print to a tty, the decorative header line is
|
||||
not printed, so that you can count the printing queue available
|
||||
on your server by doing
|
||||
|
||||
pqlist -S server | wc -l
|
||||
|
||||
.B pqlist
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B pattern
|
||||
.RS 3
|
||||
.B pattern
|
||||
is used to list only selected queues. You can use wildcards in the
|
||||
pattern, but you have to be careful to prevent shell interpretation of
|
||||
wildcards like '*'.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
If the user name your NetWare administrator gave to you differs
|
||||
from your unix user-id, you should use
|
||||
.B -U
|
||||
to tell the server about you NetWare user name.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
You may want to give the password required by the server on the
|
||||
command line. You should be careful to use passwords in scripts.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given to mount shares which do not require a password to log in.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, pqlist prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
pqlist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
142
man/pserver.1
Normal file
142
man/pserver.1
Normal file
@@ -0,0 +1,142 @@
|
||||
.TH PSERVER 1 02/10/1996 pserver pserver
|
||||
.SH NAME
|
||||
pserver \- NetWare print server
|
||||
.SH SYNOPSIS
|
||||
.B pserver
|
||||
[
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -h
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -q
|
||||
.I queue name
|
||||
] [
|
||||
.B -c
|
||||
.I command
|
||||
] [
|
||||
.B -j
|
||||
.I job type
|
||||
] [
|
||||
.B -t
|
||||
.I timeout
|
||||
] [
|
||||
.B -d
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B pserver
|
||||
is a program that connects to print queues on NetWare servers and
|
||||
feeds incoming print jobs to the Linux printing system.
|
||||
|
||||
.SH OPTIONS
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the print server name at the server.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for the print server at the server. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, pserver
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if the print server does not require a password.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -q
|
||||
.I queue name
|
||||
.RS 3
|
||||
.B queue name
|
||||
is the name of the print queue you want to service.
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I command
|
||||
.RS 3
|
||||
When a job is received from the print queue, pserver forks off a new
|
||||
process, and feeds the job file to stdin.
|
||||
.I command
|
||||
is the printing command that is executed for each job. The default
|
||||
command is 'lpr'.
|
||||
.RE
|
||||
|
||||
.B -j
|
||||
.I job type
|
||||
.RS 3
|
||||
Each job in a NetWare print queue has a job type. For print jobs, this
|
||||
corresponds to the number of the form the job should be printed
|
||||
on. You can tell pserver that it should only receive jobs for one
|
||||
specific form from the queue. The default is -1, which means that
|
||||
everything is received.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I timeout
|
||||
.RS 3
|
||||
Pserver is not informed by NetWare servers when new jobs arrive. So a
|
||||
polling scheme has to be used. When there are no jobs to service,
|
||||
.I timeout
|
||||
tells pserver how long to wait between two requests. The default is 30
|
||||
seconds. When a job is finished, pserver asks the NetWare server
|
||||
immediately for a new job, and does not wait
|
||||
.I timeout
|
||||
seconds.
|
||||
.RE
|
||||
|
||||
.B -d
|
||||
.RS 3
|
||||
Normally, pserver daemonizes itself.
|
||||
.B -d
|
||||
tells it not to do so. This is useful if you want to see the
|
||||
diagnostic messages that are printed when a error occurs.
|
||||
.RE
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
pserver was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
43
man/slist.1
Normal file
43
man/slist.1
Normal file
@@ -0,0 +1,43 @@
|
||||
.TH SLIST 1 01/07/1996 slist slist
|
||||
.SH NAME
|
||||
slist \- Lists available NetWare Servers
|
||||
.SH SYNOPSIS
|
||||
.B slist
|
||||
[
|
||||
.I pattern
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B slist
|
||||
lists all NetWare Servers available in your network.
|
||||
|
||||
If slist does not print to a tty, the decorative header line is not
|
||||
printed, so that you can count the servers on your network by doing
|
||||
|
||||
slist | wc -l
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
.B pattern
|
||||
.RS 3
|
||||
.B pattern
|
||||
is used to list only servers whose names match the specified pattern. For a
|
||||
server to be listed, the pattern must match the full server name. You can use
|
||||
wildcards for the pattern, but you must protect these wildcards from any
|
||||
command line expansion by quoting. Case doesn't matter.
|
||||
.RE
|
||||
|
||||
.SH EXAMPLE
|
||||
.TP
|
||||
slist "I*"
|
||||
.TP
|
||||
or
|
||||
.TP
|
||||
slist "i*"
|
||||
List all available Netware servers on your Network, that begin with an "I".
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.B ncpmount(8), ncpumount(8), pqlist(1), nprint(1)
|
||||
|
||||
.SH CREDITS
|
||||
slist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
@@ -1,14 +0,0 @@
|
||||
Begin3
|
||||
Title: ncpfs
|
||||
Version: 0.8
|
||||
Entered-date: 28. November 1995
|
||||
Description: With ncpfs you can mount volumes of your novell
|
||||
server under Linux.
|
||||
Keywords: filesystem kernel ncp novell netware
|
||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
||||
~80k ncpfs-0.8.tgz
|
||||
~ 1k ncpfs-0.8.lsm
|
||||
Copying-policy: GPL
|
||||
End
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user