Compare commits

..

7 Commits
v0.6 ... v0.13

Author SHA1 Message Date
ncpfs archive import
d31ec2ab61 Import ncpfs 0.13 2026-04-28 20:39:57 +02:00
ncpfs archive import
1ee60bade6 Import ncpfs 0.12 2026-04-28 20:39:57 +02:00
ncpfs archive import
20589ca203 Import ncpfs 0.11 2026-04-28 20:39:57 +02:00
ncpfs archive import
517e207709 Import ncpfs 0.10 2026-04-28 20:39:57 +02:00
ncpfs archive import
5d4b23a5c1 Import ncpfs 0.9 2026-04-28 20:39:57 +02:00
ncpfs archive import
c6124785a9 Import ncpfs 0.8 2026-04-28 20:39:57 +02:00
ncpfs archive import
f2bcb2c71e Import ncpfs 0.7 2026-04-28 20:39:57 +02:00
64 changed files with 6479 additions and 3516 deletions

BIN
.downloads/ncpfs-0.10.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.11.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.12.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.13.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.7.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.8.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.9.tgz Normal file

Binary file not shown.

9
Changes Normal file
View File

@@ -0,0 +1,9 @@
I only began this file with ncpfs-0.12. If you're interested in older
versions, you can find them on linux01.gwdg.de:/pub/ncpfs/old.
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.

View File

@@ -2,36 +2,47 @@
# Makefile for the linux ncp-filesystem routines.
#
KERNEL = 1.3
# KERNEL = 1.2
INCLUDES = -I/usr/src/linux/include -Ikernel
BINDIR = ./bin
TOPDIR = $(shell pwd)
CFLAGS = -Wall $(INCLUDES)
CC = gcc
BINDIR = /usr/local/bin
INTERM_BINDIR = $(TOPDIR)/bin
SUBDIRS = util ipx-0.75 man
all: kernel
make -C util
make -C kernel/src ncpfs.o
cp kernel/src/ncpfs.o bin
#
# The following 2 lines are for those who use Kernel version 1.2.x.
# If you have a kernel later than 1.3.53, please comment out the
# the following lines. You have to recompile your kernel
# and say 'y' when 'make config' asks you for IPX and ncpfs.
#
SUBDIRS += kernel-1.2/src
INCLUDES = -I$(TOPDIR)/kernel-1.2
kernel:
rm -f kernel
ln -s kernel-$(KERNEL) kernel
# If you are using kerneld to autoload ncp support,
# uncomment this (kerneld is in linux since about 1.3.57):
# KERNELD = -DHAVE_KERNELD
export INCLUDES BINDIR INTERM_BINDIR KERNELD
all:
for i in $(SUBDIRS); do make -C $$i; 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 util/mnt
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
make -C util realclean
modules: ncpfs.o
@@ -40,7 +51,11 @@ SRCPATH=$(shell pwd)
SRCDIR=$(shell basename $(SRCPATH))
DISTFILE=$(SRCDIR).tgz
dist: realclean
dist: tgz
make dep
make all
tgz: realclean
(cd ..; \
tar cvf - $(SRCDIR) | \
gzip -9 > $(DISTFILE); \

69
README
View File

@@ -1,11 +1,34 @@
This is version 0.6 of ncpfs, a free NetWare client for Linux. You
need at least kernel 1.3.44 for this version. It does NOT work with
any lower one, especially not with version 1.2.x.
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.
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
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.54. ncpfs does NOT work with any earlier 1.3.x kernel, especially
not with 1.3.53, although this one has a fs/ncpfs/ subdirectory.
If you use Kernel 1.3.54 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.
With Kernel 1.3.54 or later you also have to modify the Makefile in the
directory you found this README in. Please see the Makefile for the
necessary modifications. Then typing 'make' should work with no
problem.
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
@@ -19,8 +42,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,
@@ -30,7 +53,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
@@ -40,6 +63,21 @@ 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.
LIMITATIONS (compare these with smbfs :-)
The limitations ncpfs has are the natural limitations of the NCP
@@ -61,3 +99,14 @@ 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.
Those who looked at the kernel code a bit closer will have found out
that the last section is a little white lie. As I found out after the
first version of ncpfs, NetWare does indeed offer something like inode
numbers, although are only unique per volume. So one way to make ncpfs
re-exportable by nfs is to allocate a superblock per volume and show
the inode numbers to the user. I was just too lazy to do this
yet. Maybe once we will force Novell to make NetWare NFS
affordable... ;-)
Have fun with ncpfs!

30
ipx-0.75/Makefile Normal file
View 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) -s -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
$(CC) -s -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
$(CC) -s -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
$(INTERM_BINDIR)/ipx_route: ipx_route.o
$(CC) -s -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 --strip $$i $(BINDIR); \
done

65
ipx-0.75/README Normal file
View 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:
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.

303
ipx-0.75/ipx_interface.c Normal file
View File

@@ -0,0 +1,303 @@
#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>
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 check device frame_type\n", progname, progname, progname);
exit(-1);
}
struct frame_type {
char *ft_name;
unsigned char ft_val;
} frame_types[] = {
{"802.2", IPX_FRAME_8022},
{"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) {
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
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_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;
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], "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;
}

195
ipx-0.75/ipx_internal_net.c Normal file
View File

@@ -0,0 +1,195 @@
#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;
}

215
ipx-0.75/ipx_route.c Normal file
View File

@@ -0,0 +1,215 @@
#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;
}

52
ipx-0.75/ipxrcv.c Normal file
View 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-0.75/ipxsend.c Normal file
View 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-0.75/rip.c Normal file
View 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[4], 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-0.75/sap.c Normal file
View 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++;
}
}
}

View File

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

View File

@@ -26,9 +26,26 @@ struct ncp_ioctl_request {
char *data;
};
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! */
/* Not used yet, but here some day the namespace numbers will be
stored. */
int volume_number;
__u32 directory_id;
};
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
#define NCP_GET_FS_INFO_VERSION (1)
#define NCP_IOC_GET_FS_INFO _IOWR('i', 1, unsigned char *)
/*
* The packet size to allocate. One page should be enough.
*/
@@ -58,10 +75,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>

View File

@@ -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
};
/*

View File

@@ -2,11 +2,9 @@
# 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=2 -DDEBUG_NCP_MALLOC
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
# -DDEBUG_NCP_MALLOC
CC = gcc -D__KERNEL__ -I.
@@ -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:

View File

@@ -5,7 +5,11 @@
*
*/
/* #include <linux/module.h>*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#include <linux/sched.h>
#include <linux/errno.h>
@@ -16,7 +20,7 @@
#include <linux/ncp_fs.h>
#include <asm/segment.h>
#include <linux/errno.h>
#include "ncplib.h"
#include "ncplib_kernel.h"
struct ncp_dirent {
struct nw_info_struct i;
@@ -29,7 +33,8 @@ 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);
struct dirent *dirent, int count);
static int
ncp_read_volume_list(struct ncp_server *server, int start_with,
int cache_size);
@@ -68,9 +73,12 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
static inline void
str_upper(char *name)
{
while (*name) {
while (*name)
{
if (*name >= 'a' && *name <= 'z')
{
*name -= ('a' - 'A');
}
name++;
}
}
@@ -78,9 +86,12 @@ str_upper(char *name)
static inline void
str_lower(char *name)
{
while (*name) {
while (*name)
{
if (*name >= 'A' && *name <= 'Z')
{
*name += ('a' - 'A');
}
name ++;
}
}
@@ -92,7 +103,7 @@ static struct file_operations ncp_dir_operations = {
ncp_readdir, /* readdir */
NULL, /* select - default */
ncp_ioctl, /* ioctl - default */
NULL, /* mmap */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* fsync */
@@ -124,6 +135,9 @@ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
return -EISDIR;
}
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
#define ROUND_UP(x) (((x)+3) & ~3)
/* 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. */
@@ -136,7 +150,7 @@ static struct ncp_dirent* c_entry = NULL;
static int
ncp_readdir(struct inode *inode, struct file *filp,
void *dirent, filldir_t filldir)
struct dirent *dirent, int count)
{
int result, i = 0;
int index = 0;
@@ -144,11 +158,24 @@ ncp_readdir(struct inode *inode, struct file *filp,
struct ncp_server *server = NCP_SERVER(inode);
struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
int filldir(struct dirent *dirent,
const char *name, int len,
int f_pos, ino_t ino)
{
memcpy_tofs(dirent->d_name, name, len);
put_fs_byte(0, &(dirent->d_name[len]));
put_fs_long(ino, &dirent->d_ino);
put_fs_word(len, &dirent->d_reclen);
put_fs_word(f_pos, &dirent->d_off);
return 1;
}
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)) {
if (!inode || !S_ISDIR(inode->i_mode))
{
printk("ncp_readdir: inode is NULL or not a directory\n");
return -EBADF;
}
@@ -157,32 +184,40 @@ ncp_readdir(struct inode *inode, struct file *filp,
{
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
if (c_entry == NULL) {
if (c_entry == NULL)
{
printk("ncp_readdir: no MEMORY for cache\n");
return -ENOMEM;
}
}
if (filp->f_pos == 0) {
if (filp->f_pos == 0)
{
ncp_invalid_dir_cache(inode->i_ino);
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0) {
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
{
return 0;
}
filp->f_pos += 1;
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
}
if (filp->f_pos == 1) {
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0) {
if (filp->f_pos == 1)
{
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
{
return 0;
}
filp->f_pos += 1;
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
}
if (inode->i_ino == c_ino) {
for (i = 0; i < c_size; i++) {
if (filp->f_pos == c_entry[i].f_pos) {
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;
@@ -190,33 +225,38 @@ ncp_readdir(struct inode *inode, struct file *filp,
}
}
if ((entry == NULL) && c_seen_eof)
{
return 0;
}
}
if (entry == NULL) {
DPRINTK("ncp_readdir: Not found in cache.\n");
if (inode->i_ino == (int)&(server->root)) {
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 {
}
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) {
if (result < 0)
{
c_ino = 0;
return result;
}
if (result > 0) {
if (result > 0)
{
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
c_ino = inode->i_ino;
c_size = result;
@@ -224,19 +264,21 @@ ncp_readdir(struct inode *inode, struct file *filp,
c_last_returned_index = 0;
index = 0;
for (i = 0; i < c_size; i++) {
for (i = 0; i < c_size; i++)
{
str_lower(c_entry[i].i.entryName);
}
}
}
if (entry == NULL) {
if (entry == NULL)
{
/* Nothing found, even from a ncp call */
return 0;
}
while (index < c_size) {
if (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
@@ -244,12 +286,12 @@ ncp_readdir(struct inode *inode, struct file *filp,
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) {
if (ino_info == NULL)
{
ino_info = (struct ncp_inode_info *) 1;
}
@@ -257,19 +299,15 @@ ncp_readdir(struct inode *inode, struct file *filp,
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;
entry->f_pos, (ino_t)ino_info) < 0)
{
return 0;
}
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 ROUND_UP(NAME_OFFSET(dirent)+i+1);
}
return 0;
}
@@ -283,33 +321,42 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
int i;
#if 1
if (fpos < 2) {
if (fpos < 2)
{
printk("OOPS, we expect fpos >= 2");
fpos = 2;
}
fpos = 2;
#endif
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++) {
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) {
if (ncp_get_volume_info_with_number(server, i, &info) != 0)
{
return total_count;
}
if (strlen(info.volume_name) > 0) {
if (total_count < fpos) {
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) {
}
else if (total_count >= fpos + cache_size)
{
return (total_count - fpos);
} else {
}
else
{
DPRINTK("ncp_read_volumes: found vol: %s\n",
info.volume_name);
if (ncp_do_lookup(server, NULL,
info.volume_name,
&(entry->i)) != 0) {
&(entry->i)) != 0)
{
printk("ncpfs: could not lookup vol "
"%s\n", info.volume_name);
continue;
@@ -321,7 +368,6 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
total_count += 1;
}
}
return (total_count - fpos);
}
@@ -329,41 +375,63 @@ static int
ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
int cache_size, struct ncp_dirent *entry)
{
struct nw_search_sequence seq;
int total_count = 2;
static struct nw_search_sequence seq;
static struct inode *last_dir;
static int total_count;
#if 1
if (fpos < 2) {
if (fpos < 2)
{
printk("OOPS, we expect fpos >= 2");
fpos = 2;
}
fpos = 2;
#endif
DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq) != 0) {
DPRINTK("ncp_init_search failed\n");
return total_count - fpos;
if (fpos == 2)
{
last_dir = NULL;
total_count = 2;
}
while (total_count < fpos + cache_size) {
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) {
&(entry->i)) != 0)
{
return total_count - fpos;
}
if (total_count < fpos) {
if (total_count < fpos)
{
DPRINTK("ncp_do_readdir: skipped file: %s\n",
entry->i.entryName);
} else {
DPRINTK("ncp_do_readdir: found 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);
}
@@ -377,7 +445,8 @@ ncp_init_dir_cache(void)
void
ncp_invalid_dir_cache(unsigned long ino)
{
if (ino == c_ino) {
if (ino == c_ino)
{
c_ino = 0;
c_seen_eof = 0;
}
@@ -389,7 +458,9 @@ 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);
@@ -406,12 +477,14 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
struct ncp_inode_info *new_inode_info;
struct ncp_inode_info *root;
if (!dir) {
if (dir == NULL)
{
printk("ncp_iget: dir is NULL\n");
return NULL;
}
if (!finfo) {
if (finfo == NULL)
{
printk("ncp_iget: finfo is NULL\n");
return NULL;
}
@@ -419,13 +492,14 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
GFP_KERNEL);
if (new_inode_info == NULL) {
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->state = NCP_INODE_LOOKED_UP;
new_inode_info->nused = 0;
new_inode_info->dir = NCP_INOP(dir);
new_inode_info->finfo = *finfo;
@@ -443,7 +517,8 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
root->next->prev = new_inode_info;
root->next = new_inode_info;
if (!(inode = iget(dir->i_sb, (int)new_inode_info))) {
if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
{
printk("ncp_iget: iget failed!");
return NULL;
}
@@ -454,13 +529,15 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
void
ncp_free_inode_info(struct ncp_inode_info *i)
{
if (i == NULL) {
if (i == NULL)
{
printk("ncp_free_inode: i == NULL\n");
return;
}
i->state = INODE_CACHED;
while ((i->nused == 0) && (i->state == INODE_CACHED)) {
i->state = NCP_INODE_CACHED;
while ((i->nused == 0) && (i->state == NCP_INODE_CACHED))
{
struct ncp_inode_info *dir = i->dir;
i->next->prev = i->prev;
@@ -485,19 +562,19 @@ ncp_init_root(struct ncp_server *server)
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;
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));
ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
i->nameLen = 0;
i->entryName[0] = '\0';
root->state = INODE_LOOKED_UP;
root->state = NCP_INODE_LOOKED_UP;
root->nused = 1;
root->dir = root;
root->next = root->prev = root;
@@ -513,11 +590,13 @@ ncp_free_all_inodes(struct ncp_server *server)
#if 1
struct ncp_inode_info *root = &(server->root);
if (root->next != root) {
if (root->next != root)
{
printk("ncp_free_all_inodes: INODES LEFT!!!\n");
}
while (root->next != root) {
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.. */
@@ -538,17 +617,23 @@ ncp_find_inode(struct inode *dir, const char *name)
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
struct ncp_inode_info *result = &(server->root);
if (name == NULL) {
if (name == NULL)
{
return NULL;
}
do {
if ( (result->finfo.i.DosDirNum == dir_info->DosDirNum)
do
{
if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
&& (strcmp(result->finfo.i.entryName, name) == 0))
{
return result;
}
result = result->next;
} while (result != &(server->root));
}
while (result != &(server->root));
return NULL;
}
@@ -562,9 +647,12 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
struct ncp_inode_info *result_info;
int found_in_cache;
char name[len+1];
*result = NULL;
if (!dir || !S_ISDIR(dir->i_mode)) {
if (!dir || !S_ISDIR(dir->i_mode))
{
printk("ncp_lookup: inode is NULL or not a directory.\n");
iput(dir);
return -ENOENT;
@@ -575,27 +663,45 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
server = NCP_SERVER(dir);
/* Fast cheat for . */
if (len == 0 || (len == 1 && __name[0] == '.')) {
if (len == 0 || (len == 1 && __name[0] == '.'))
{
*result = dir;
return 0;
}
/* ..and for .. */
if (len == 2 && __name[0] == '.' && __name[1] == '.') {
*result = iget(dir->i_sb, (int)(NCP_INOP(dir)->dir));
if (len == 2 && __name[0] == '.' && __name[1] == '.')
{
struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
if (parent->state == NCP_INODE_CACHED)
{
parent->state = NCP_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);
memcpy(name, __name, len);
name[len] = 0;
if (result_info != 0) {
result_info = ncp_find_inode(dir, name);
if (result_info->state == INODE_CACHED)
result_info->state = INODE_LOOKED_UP;
if (result_info != 0)
{
if (result_info->state == NCP_INODE_CACHED)
{
result_info->state = NCP_INODE_LOOKED_UP;
}
/* Here we convert the inode_info address into an
inode number */
@@ -603,7 +709,8 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
*result = iget(dir->i_sb, (int)result_info);
iput(dir);
if (*result == NULL) {
if (*result == NULL)
{
return -EACCES;
}
@@ -615,40 +722,41 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
found_in_cache = 0;
if (dir->i_ino == c_ino) {
if (dir->i_ino == c_ino)
{
int first = c_last_returned_index;
int i;
i = first;
do {
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) {
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);
}
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);
if (found_in_cache == 0)
{
str_upper(name);
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
NCP_ISTRUCT(dir)->entryName, this_name);
NCP_ISTRUCT(dir)->entryName, name);
if (ncp_do_lookup(server,
dir->i_ino == (int)&(NCP_SERVER(dir)->root)
? NULL : NCP_ISTRUCT(dir),
this_name,
&(finfo.i)) != 0) {
name, &(finfo.i)) != 0)
{
iput(dir);
return -ENOENT;
}
@@ -657,7 +765,8 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
finfo.opened = 0;
str_lower(finfo.i.entryName);
if (!(*result = ncp_iget(dir, &finfo))) {
if (!(*result = ncp_iget(dir, &finfo)))
{
iput(dir);
return -EACCES;
}
@@ -675,7 +784,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
*result = NULL;
if (!dir || !S_ISDIR(dir->i_mode)) {
if (!dir || !S_ISDIR(dir->i_mode))
{
printk("ncp_create: inode is NULL or not a directory\n");
iput(dir);
return -ENOENT;
@@ -689,7 +799,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
NCP_ISTRUCT(dir), _name,
OC_MODE_CREATE|OC_MODE_OPEN,
0, AR_READ|AR_WRITE,
&finfo) != 0) {
&finfo) != 0)
{
iput(dir);
return -EACCES;
}
@@ -699,7 +810,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
str_lower(finfo.i.entryName);
finfo.access = O_RDWR;
if (!(*result = ncp_iget(dir, &finfo)) < 0) {
if (!(*result = ncp_iget(dir, &finfo)) < 0)
{
ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
iput(dir);
return -EINVAL;
@@ -716,11 +828,20 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
struct nw_file_info new_dir;
__u8 _name[len+1];
if ( (name[0] == '.')
&& ( (len == 1)
|| ( (len == 2)
&& (name[1] == '.'))))
{
return -EEXIST;
}
strncpy(_name, name, len);
_name[len] = '\0';
str_upper(_name);
if (!dir || !S_ISDIR(dir->i_mode)) {
if (!dir || !S_ISDIR(dir->i_mode))
{
printk("ncp_mkdir: inode is NULL or not a directory\n");
iput(dir);
return -ENOENT;
@@ -729,9 +850,12 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
NCP_ISTRUCT(dir), _name,
OC_MODE_CREATE, aDIR, 0xffff,
&new_dir) != 0) {
&new_dir) != 0)
{
error = -EACCES;
} else {
}
else
{
error = 0;
ncp_invalid_dir_cache(dir->i_ino);
}
@@ -746,12 +870,14 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
int error;
__u8 _name[len+1];
if (!dir || !S_ISDIR(dir->i_mode)) {
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) {
if (ncp_find_inode(dir, name) != NULL)
{
error = -EBUSY;
}
else
@@ -763,7 +889,8 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
NCP_ISTRUCT(dir),
_name)) == 0) {
_name)) == 0)
{
ncp_invalid_dir_cache(dir->i_ino);
}
else
@@ -781,24 +908,26 @@ ncp_unlink(struct inode *dir, const char *name, int len)
int error;
__u8 _name[len+1];
if (!dir || !S_ISDIR(dir->i_mode)) {
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) {
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) {
_name)) == 0)
{
ncp_invalid_dir_cache(dir->i_ino);
}
else
@@ -818,20 +947,23 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
char _old_name[old_len+1];
char _new_name[new_len+1];
if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
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)) {
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)) {
|| (ncp_find_inode(new_dir, new_name) != NULL))
{
res = -EBUSY;
goto finished;
}
@@ -841,14 +973,15 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
str_upper(_old_name);
strncpy(_new_name, new_name, new_len);
_new_name[old_len] = '\0';
_new_name[new_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) {
if (res == 0)
{
ncp_invalid_dir_cache(old_dir->i_ino);
ncp_invalid_dir_cache(new_dir->i_ino);
}

View File

@@ -5,7 +5,11 @@
*
*/
/* #include <linux/module.h>*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#include <asm/segment.h>
#include <asm/system.h>
@@ -17,9 +21,14 @@
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/ncp_fs.h>
#include "ncplib.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)
{
@@ -31,7 +40,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;
}
@@ -40,23 +50,27 @@ ncp_make_open(struct inode *i, int right)
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
if (finfo->opened == 0) {
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) == 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 {
}
else
{
return -EACCES;
}
}
@@ -74,18 +88,20 @@ 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 (!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;
@@ -94,33 +110,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.. */
}
@@ -128,14 +145,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);
@@ -144,19 +166,21 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
}
static int
ncp_file_write(struct inode *inode, struct file *file, const char *buf,
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 (!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;
@@ -165,33 +189,35 @@ ncp_file_write(struct inode *inode, struct file *file, const 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;
}
@@ -199,7 +225,8 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
buf += written_this_time;
already_written += written_this_time;
if (written_this_time < to_write) {
if (written_this_time < to_write)
{
break;
}
}
@@ -209,7 +236,8 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
file->f_pos = pos;
if (pos > inode->i_size) {
if (pos > inode->i_size)
{
inode->i_size = pos;
}
@@ -225,7 +253,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 */

View File

@@ -5,7 +5,14 @@
*
*/
#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/system.h>
#include <asm/segment.h>
@@ -20,14 +27,14 @@
#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);
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 void ncp_statfs(struct super_block *sb, struct statfs *stat);
static int ncp_notify_change(struct inode *inode, struct iattr *attr);
static struct super_operations ncp_sops = {
@@ -39,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,20 +68,25 @@ ncp_read_inode(struct inode *inode)
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) {
do
{
if (inode_info == check_info)
{
if (check_info->state == NCP_INODE_LOOKED_UP)
{
DDPRINTK("ncp_read_inode: found it!\n");
goto good;
}
else {
else
{
printk("ncp_read_inode: "
"state != INODE_LOOKED_UP\n");
"state != NCP_INODE_LOOKED_UP\n");
goto good;
}
}
check_info = check_info->next;
} while (check_info != root);
}
while (check_info != root);
/* Ok, now we're in trouble. The inode info is not there. What
should we do now??? */
@@ -85,17 +97,18 @@ ncp_read_inode(struct inode *inode)
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;
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
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;
@@ -108,11 +121,16 @@ ncp_read_inode(struct inode *inode)
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);
@@ -122,12 +140,17 @@ 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
@@ -135,19 +158,24 @@ 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) {
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)) {
DPRINTK("ncp_put_inode: put directory %ld\n",
inode->i_ino);
if (S_ISDIR(inode->i_mode))
{
DDPRINTK("ncp_put_inode: put directory %ld\n",
inode->i_ino);
ncp_invalid_dir_cache(inode->i_ino);
}
@@ -161,25 +189,27 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
struct ncp_server *server;
struct file *ncp_filp;
struct file *wdog_filp;
kdev_t dev = sb->s_dev;
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");
}
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;
@@ -187,7 +217,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;
@@ -197,7 +228,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,7 +263,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);
@@ -244,7 +277,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);
@@ -256,7 +290,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);
@@ -267,14 +302,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, (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) {
&(server->buffer_size)) != 0)
{
sb->s_dev = 0;
printk("ncp_read_super: could not get bufsize\n");
goto disconnect;
@@ -282,14 +319,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;
@@ -336,7 +365,7 @@ ncp_put_super(struct super_block *sb)
}
static void
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
ncp_statfs(struct super_block *sb, struct statfs *stat)
{
struct statfs tmp;
@@ -354,7 +383,7 @@ ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
tmp.f_files = -1;
tmp.f_ffree = -1;
tmp.f_namelen = 12;
memcpy_tofs(buf, &tmp, bufsiz);
memcpy_tofs(stat, &tmp, sizeof(tmp));
}
static int
@@ -383,43 +412,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;
}
@@ -447,6 +492,8 @@ int ncp_current_malloced;
#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
static struct file_system_type ncp_fs_type = {
ncp_read_super, "ncpfs", 0, NULL
};

134
kernel-1.2/src/ioctl.c Normal file
View File

@@ -0,0 +1,134 @@
/*
* ioctl.c
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#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_fs_info info;
struct ncp_server *server = NCP_SERVER(inode);
switch(cmd) {
case NCP_IOC_NCPREQUEST:
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)
{
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;
}
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;
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);
ncp_unlock_server(server);
return server->reply_size;
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;
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)
{
return result;
}
put_fs_word(server->m.mounted_uid, (uid_t*) arg);
return 0;
default:
return -EINVAL;
}
return -EINVAL;
}

152
kernel-1.2/src/mmap.c Normal file
View File

@@ -0,0 +1,152 @@
/*
* 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");
/* 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;
}

View File

@@ -1,13 +1,25 @@
#include "ncplib.h"
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#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");
}
}
@@ -62,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;
}
@@ -117,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;
}
@@ -145,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;
}
@@ -161,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;
@@ -180,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;
}
@@ -199,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;
}
@@ -216,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);
}
@@ -257,11 +279,13 @@ ncp_do_lookup(struct ncp_server *server,
int result;
char *volname = NULL;
if (target == NULL) {
if (target == NULL)
{
return -EINVAL;
}
if (dir == NULL) {
if (dir == NULL)
{
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
@@ -275,7 +299,8 @@ ncp_do_lookup(struct ncp_server *server,
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
path);
if ((result = ncp_request(server, 87)) != 0) {
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
@@ -301,14 +326,16 @@ ncp_do_lookup(struct ncp_server *server,
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);
if (volname != NULL) {
if (volname != NULL)
{
target->nameLen = strlen(volname);
strcpy(target->entryName, volname);
}
@@ -336,7 +363,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;
}
@@ -359,7 +387,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;
}
@@ -400,16 +429,20 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
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;
}
@@ -418,7 +451,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));
}
@@ -443,7 +477,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;
}
@@ -473,7 +508,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;
}
@@ -539,14 +575,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;
@@ -566,7 +603,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;
}

View File

@@ -7,7 +7,11 @@
*
*/
/* #include <linux/module.h> */
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#include <linux/version.h>
#endif
#include <linux/sched.h>
#include <linux/ncp_fs.h>
@@ -25,52 +29,10 @@
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ncp_fs_sb.h>
#include <net/sock.h>
#include "/usr/src/linux/net/inet/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)
{
@@ -80,15 +42,16 @@ ncp_wdog_data_ready(struct sock *sk, int len)
{
unsigned char packet_buf[2];
struct sockaddr_ipx sender;
int addr_len;
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);
result = sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
(struct sockaddr *)&sender,
&addr_len);
if ( (result != 2)
|| (packet_buf[1] != '?')
@@ -96,16 +59,19 @@ ncp_wdog_data_ready(struct sock *sk, int len)
)
{
/* Error, throw away the complete packet */
_recvfrom(sock, (void *)packet_buf, 2, 1, 0,
&sender, &addr_len);
sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
(struct sockaddr *)&sender,
&addr_len);
printk("ncpfs: got strange packet on watchdog "
"socket\n");
} else {
}
else
{
int result;
DPRINTK("ncpfs: got watchdog from:\n");
DPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
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],
@@ -115,9 +81,11 @@ ncp_wdog_data_ready(struct sock *sk, int len)
packet_buf[0], packet_buf[1]);
packet_buf[1] = 'Y';
result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
&sender, sizeof(sender));
DPRINTK("send result: %d\n", result);
result = sock->ops->sendto(sock, (void *)packet_buf,
2, 1, 0,
(struct sockaddr *)&sender,
sizeof(sender));
DDPRINTK("send result: %d\n", result);
}
set_fs(fs);
}
@@ -135,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;
@@ -144,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;
@@ -152,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;
@@ -162,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;
}
@@ -183,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;
@@ -192,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;
@@ -247,7 +222,6 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
int timeout;
int retrans;
int major_timeout_seen;
char *server_name;
int n;
int addrlen;
unsigned long old_mask;
@@ -263,7 +237,8 @@ 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;
}
@@ -271,22 +246,22 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
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
? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
? _S(SIGINT) : 0)
| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
| (current->sigaction[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",
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],
@@ -294,7 +269,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
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));*/
ntohs(server->m.serv_addr.sipx_port));
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
"seq: %d",
request.type,
@@ -303,10 +278,12 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
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) {
result = sock->ops->sendto(sock, (void *) start, size, 0, 0,
(struct sockaddr *)
&(server->m.serv_addr),
sizeof(server->m.serv_addr));
if (result < 0)
{
printk("ncp_rpc_call: send error = %d\n", result);
break;
}
@@ -315,39 +292,42 @@ 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) {
&& !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);
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;
@@ -363,30 +343,36 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
/* 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) {
result = sock->ops->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) {
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");
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
NULL, &addrlen);
sock->ops->recvfrom(sock, (void *)&reply,
sizeof(reply), 1, 0,
NULL, &addrlen);
goto re_select;
}
@@ -403,17 +389,18 @@ 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
* 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);
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
NULL, &addrlen);
#if 1
printk("ncp_rpc_call: reply mismatch\n");
#endif
@@ -423,11 +410,14 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
* 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) {
result = sock->ops->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)) {
}
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);
@@ -447,7 +437,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;
}
@@ -471,7 +462,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;
}
@@ -484,7 +476,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;
}
@@ -496,7 +489,8 @@ ncp_request(struct ncp_server *server, int function)
result = reply->completion_code;
if (result != 0) {
if (result != 0)
{
DPRINTK("ncp_completion_code: %d\n", result);
}
return result;
@@ -518,7 +512,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;
}
@@ -548,9 +543,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
@@ -562,7 +558,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");
}

View File

@@ -1,89 +0,0 @@
/*
* ioctl.c
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
/* #include <linux/module.h>*/
#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;
}

16
man/Makefile Normal file
View File

@@ -0,0 +1,16 @@
MAN1= slist nprint pqlist
MAN5= nwclient
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net ipx_route
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:

61
man/ipx_interface.8 Normal file
View File

@@ -0,0 +1,61 @@
.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
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 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
View 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
View 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>

View File

@@ -1,23 +1,21 @@
.TH NCPMOUNT 8 25/11/1995 ncpmount ncpmount
.TH NCPMOUNT 8 12/27/1995 ncpmount ncpmount
.SH NAME
ncpmount \- mount program for ncpfs
.SH SYNOPSIS
.B ncpmount
.B server mount-point
[
.B -S
.I server
] [
.B -h
] [
.B -n
.I
] [
.B -P
.I password
] [
.B -C
] [
.B -s
.I server name
] [
.B -c
.I client name
] [
@@ -36,6 +34,7 @@ ncpmount \- mount program for ncpfs
.B -d
.I dir mode
]
mount-point
.SH DESCRIPTION
This program is an interface to the NCP filesystem.
@@ -48,13 +47,14 @@ was inspired by
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
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 mount-point
.RS 3
.B mount-point
@@ -72,6 +72,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
@@ -130,11 +137,29 @@ and a group it belongs to. With
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
This option is only makes sense if root mounts the directory. root can
mount directories on behalf of other users.
.B -c
names the user who is the
.I owner
of the connection, where owner is not meant in the unix sense (that
"owner" is set by -u), but as the one who has mounted the directory.
This way it could be 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. An exception is the owner
(in the sense mentioned above), who is also given 'request
permission'.
.RE
.B -f
.I file mode,
.B -d
@@ -147,7 +172,7 @@ and
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
permissions it should assign to the mounted files and directories. 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

View File

@@ -1,4 +1,4 @@
.TH NCPUMOUNT 8 25/11/1995 ncpumount ncpumount
.TH NCPUMOUNT 8 12/27/1995 ncpumount ncpumount
.SH NAME
ncpumount \- umount for normal users
.SH SYNOPSIS

192
man/nprint.1 Normal file
View File

@@ -0,0 +1,192 @@
.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 -n
] [
.B -C
] [
.B -U
.I user name
] [
.B -P
.I password
] [
.B -n
] [
.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.
.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 -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 -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 give 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 -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

42
man/nwclient.5 Normal file
View File

@@ -0,0 +1,42 @@
.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 if ONLY the file owner has any access rights to
the file.
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.

39
man/pqlist.1 Normal file
View File

@@ -0,0 +1,39 @@
.TH PQLIST 1 01/10/1996 pqlist pqlist
.SH NAME
pqlist \- List available NetWare print queues
.SH SYNOPSIS
.B pqlist
[
.B -S
.I server
] [
.B -U
.I user name
] [
.B -n
] [
.B -P
.I password
] [
.I pattern
]
.SH DESCRIPTION
With
.B pqlist,
you can list the NetWare print queues available to you on some
server. If you are already connected to some server, this one is
used.
.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
See ncpmount(8) for an explanation of the other options. They are
necessary because you might have to login into a server before it
tells you where you may print.

36
man/slist.1 Normal file
View File

@@ -0,0 +1,36 @@
.TH SLIST 1 01/07/1996 slist slist
.SH NAME
slist \- List available NetWare Servers
.SH SYNOPSIS
.B slist
[
.I pattern
]
.SH DESCRIPTION
With
.B slist,
you can get a list of 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 selected servers. 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".

View File

@@ -1,14 +1,17 @@
Begin3
Title: ncpfs
Version: 0.6
Entered-date: 25. November 1995
Version: 0.13
Entered-date: 14. January 1996
Description: With ncpfs you can mount volumes of your novell
server under Linux.
server under Linux. You need kernel 1.2.x or
1.3.54 and above. ncpfs does NOT work with any 1.3.x
kernel below 1.3.54.
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
~59k ncpfs-0.6.tgz
~ 1k ncpfs-0.6.lsm
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
~67k ncpfs-0.13.tgz
~ 1k ncpfs-0.13.lsm
Copying-policy: GPL
End

View File

@@ -2,38 +2,37 @@
# Makefile for the linux ncp-filesystem routines.
#
INCLUDES = -I/usr/src/linux/include -I../kernel
BINDIR = ../bin
UTILS = ncpmount ncpumount ncptest ipx_configure
UTIL_EXECS = ncpmount ncpumount nprint slist pqlist
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
UIDUTILS = ncpmount ncpumount
CFLAGS = -Wall $(INCLUDES) -g
CFLAGS = -Wall $(INCLUDES) -O2 $(KERNELD)
CC = gcc
all: $(UTILS)
all: $(UTILS) ncptest
ncpmount: ncpmount.o ncplib_user.o nwcrypt.o
$(CC) -o ncpmount ncpmount.o ncplib_user.o nwcrypt.o
cp ncpmount $(BINDIR)
install: all
for i in $(UTIL_EXECS); \
do install --strip $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
for i in $(UIDUTILS); do chmod 4755 $(BINDIR)/$$i; done
ncpumount: ncpumount.o ncplib_user.o nwcrypt.o
$(CC) -o ncpumount ncpumount.o ncplib_user.o nwcrypt.o
cp ncpumount $(BINDIR)
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) ncplib.o
$(CC) -s -o $@ $(addsuffix .o,$(notdir $@)) ncplib.o
ipx_configure: ipx_configure.c
$(CC) $(CFLAGS) ipx_configure.c -o ipx_configure
cp ipx_configure $(BINDIR)
ncplib.o: ncplib.c ncplib.h
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
ncptest: ncptest.o ncplib_user.o nwcrypt.o
$(CC) -o ncptest ncptest.o ncplib_user.o nwcrypt.o
test: test.o ncplib.o
$(CC) -o test test.o ncplib.o
nwcrypt.o: nwcrypt.c
$(CC) -c -O3 -Wall nwcrypt.c
ncptest: ncptest.o ncplib.o
$(CC) -o ncptest ncptest.o ncplib.o
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
rm -f *.o *~
rm -f *.o *~ slist test ncptest
realclean: clean
rm -f $(UTILS) .depend $(DISTFILE)
@@ -44,3 +43,4 @@ realclean: clean
ifeq (.depend,$(wildcard .depend))
include .depend
endif

46
util/fsinfo.c Normal file
View File

@@ -0,0 +1,46 @@
/*
* fsinfo.c
*
* Print the info strings of a server, maybe sometime more.
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <stdio.h>
#include "ncplib.h"
int
main(int argc, char **argv)
{
struct ncp_conn conn;
char strings[512];
char *s;
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
{
perror("Could not open connection");
return 1;
}
if (ncp_get_file_server_description_strings(&conn, strings) != 0)
{
perror("could not get strings");
ncp_close(&conn);
return 1;
}
s = strings;
while (s < strings+512)
{
if (strlen(s) == 0)
{
break;
}
puts(s);
s += strlen(s)+1;
}
ncp_close(&conn);
return 0;
}

Binary file not shown.

93
util/ipxlib.h Normal file
View File

@@ -0,0 +1,93 @@
/*
* ipxlib.h
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
#ifndef _IPXLIB_H
#define _IPXLIB_H
#include <linux/types.h>
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ipx.h>
#include <stdio.h>
typedef unsigned long IPXNet;
typedef unsigned short IPXPort;
typedef unsigned char IPXNode[IPX_NODE_LEN];
#define IPX_USER_PTYPE (0x00)
#define IPX_RIP_PTYPE (0x01)
#define IPX_SAP_PTYPE (0x04)
#define IPX_AUTO_PORT (0x0000)
#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)
struct sap_query {
unsigned short query_type; /* net order */
unsigned short server_type; /* net order */
};
struct sap_server_ident {
unsigned short server_type __attribute__ ((packed));
char server_name[48] __attribute__ ((packed));
IPXNet server_network __attribute__ ((packed));
IPXNode server_node __attribute__ ((packed));
IPXPort server_port __attribute__ ((packed));
unsigned short intermediate_network __attribute__ ((packed));
};
#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")
#define IPX_THIS_NET (0)
#ifndef IPX_NODE_LEN
#define IPX_NODE_LEN (6)
#endif
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);
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, unsigned char node[IPX_NODE_LEN]);
void
ipx_assign_node(IPXNode dest, IPXNode src);
int
ipx_node_equal(IPXNode n1,IPXNode n2);
#endif /* _IPXLIB_H */

View File

@@ -1,72 +0,0 @@
/*
IPX support library
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
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.
*/
#ifndef __IPXUTIL_H__
#define __IPXUTIL_H__
#include <string.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"
typedef unsigned long IPXNet;
typedef unsigned short IPXPort;
typedef unsigned char IPXNode[IPX_NODE_LEN];
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);
}
#endif

2535
util/ncplib.c Normal file

File diff suppressed because it is too large Load Diff

289
util/ncplib.h Normal file
View File

@@ -0,0 +1,289 @@
/*
* ncplib.h
*
* Copyright (C) 1995, 1996 by Volker Lendecke
*
*/
#ifndef _NCPLIB_H
#define _NCPLIB_H
#include <linux/types.h>
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ipx.h>
#include <sys/param.h>
#include <stdio.h>
#include "ipxlib.h"
#ifndef memzero
#define memzero(object) memset(&(object), 0, sizeof(object))
#endif
enum connect_state {
NOT_CONNECTED = 0,
CONN_PERMANENT,
CONN_TEMPORARY
};
struct ncp_conn {
enum connect_state is_connected;
char server[NCP_BINDERY_NAME_LEN];
char user [NCP_BINDERY_NAME_LEN];
struct ncp_fs_info i;
/* Fields for use with permanent connections */
int mount_fid;
char mount_point[MAXPATHLEN];
/* Fields for use with temporary connections */
int ncp_sock;
int wdog_sock;
int wdog_pid;
__u8 sequence;
int completion;
int conn_status;
int reply_size;
/* Fields used to setup ncp requests */
int current_size;
int has_subfunction;
int verbose;
int ncp_reply_size;
int lock;
char packet[NCP_PACKET_SIZE];
};
struct ncp_conn_spec {
char server[NCP_BINDERY_NAME_LEN];
char user[NCP_BINDERY_NAME_LEN];
uid_t uid;
char password[NCP_BINDERY_NAME_LEN];
};
struct ncp_search_seq {
struct nw_search_sequence s;
int namespace;
};
/* ncp_initialize is the main entry point for user programs which want
to connect to a NetWare Server. It looks for -S, -U, -P and -n in
the argument list, opens the connection and removes the arguments
from the list. It was designed after the X Windows init
functions. */
int
ncp_initialize(struct ncp_conn *conn,
int *argc, char **argv,
int login_necessary);
/* Open an existing permanent connection */
int
ncp_open(struct ncp_conn *conn,
const struct ncp_conn_spec *spec);
/* Open a connection on an existing mount point */
int
ncp_open_mount(struct ncp_conn *conn,
const char *mount_point);
/* Detach from and destroy a permanent connection */
int
ncp_destroy_permanent(struct ncp_conn *conn);
/* Create a temporary connection */
int
ncp_open_temporary(struct ncp_conn *conn,
const struct ncp_conn_spec *spec);
/* Detach from a permanent connection or destroy a temporary
connection */
int
ncp_close(struct ncp_conn *conn);
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
connections */
struct ncp_conn_ent {
char server[NCP_BINDERY_NAME_LEN];
char user[NCP_BINDERY_NAME_LEN];
uid_t uid;
char mount_point[MAXPATHLEN];
};
struct ncp_conn_ent *
ncp_get_conn_ent(FILE *filep);
#define NWCLIENT (".nwclient")
#define NWC_NOPASSWORD ("-")
/* find an appropriate connection */
struct ncp_conn_spec *
ncp_find_conn_spec(const char *server, const char *user, const char *password,
uid_t uid);
int
ncp_get_file_server_description_strings(struct ncp_conn *conn,
char target[512]);
int
ncp_get_encryption_key(struct ncp_conn *conn,
char *target);
int
ncp_get_bindery_object_id(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
struct ncp_bindery_object *target);
int
ncp_scan_bindery_object(struct ncp_conn *conn,
__u32 last_id, __u16 object_type, char *search_string,
struct ncp_bindery_object *target);
int
ncp_read_property_value(struct ncp_conn *conn,
int object_type, const char *object_name,
int segment, const char *prop_name,
struct nw_property *target);
int
ncp_login_encrypted(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *passwd);
int
ncp_login_user(struct ncp_conn *conn,
const unsigned char *username,
const unsigned char *password);
int
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
struct ncp_volume_info *target);
int
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
int *target);
int
ncp_file_search_init(struct ncp_conn *conn,
int dir_handle, const char *path,
struct ncp_filesearch_info *target);
int
ncp_file_search_continue(struct ncp_conn *conn,
struct ncp_filesearch_info *fsinfo,
int attributes, const char *path,
struct ncp_file_info *target);
int
ncp_get_finfo(struct ncp_conn *conn,
int dir_handle, const char *path, const char *name,
struct ncp_file_info *target);
int
ncp_open_file(struct ncp_conn *conn,
int dir_handle, const char *path,
int attr, int access,
struct ncp_file_info *target);
int
ncp_close_file(struct ncp_conn *conn, const char *file_id);
int
ncp_create_newfile(struct ncp_conn *conn,
int dir_handle, const char *path,
int attr,
struct ncp_file_info *target);
int
ncp_create_file(struct ncp_conn *conn,
int dir_handle, const char *path,
int attr,
struct ncp_file_info *target);
int
ncp_erase_file(struct ncp_conn *conn,
int dir_handle, const char *path,
int attr);
int
ncp_rename_file(struct ncp_conn *conn,
int old_handle, const char *old_path,
int attr,
int new_handle, const char *new_path);
int
ncp_create_directory(struct ncp_conn *conn,
int dir_handle, const char *path,
int inherit_mask);
int
ncp_delete_directory(struct ncp_conn *conn,
int dir_handle, const char *path);
int
ncp_rename_directory(struct ncp_conn *conn,
int dir_handle,
const char *old_path, const char *new_path);
int
ncp_read(struct ncp_conn *conn, const char *file_id,
off_t offset, size_t count, char *target);
int
ncp_write(struct ncp_conn *conn, const char *file_id,
off_t offset, size_t count, const char *source);
int
ncp_do_lookup(struct ncp_conn *conn,
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_conn *conn,
struct nw_info_struct *file,
__u32 info_mask,
struct nw_modify_dos_info *info);
int
ncp_del_file_or_subdir(struct ncp_conn *conn,
struct nw_info_struct *dir, char *name);
int
ncp_open_create_file_or_subdir(struct ncp_conn *conn,
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_conn *conn,
const struct nw_info_struct *dir,
int namespace,
struct ncp_search_seq *target);
int
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
struct ncp_search_seq *seq,
struct nw_info_struct *target);
int
ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn,
struct nw_info_struct *old_dir, char *old_name,
struct nw_info_struct *new_dir, char *new_name);
int
ncp_create_queue_job_and_file(struct ncp_conn *conn,
__u32 queue_id,
struct queue_job *job);
int
ncp_close_file_and_start_job(struct ncp_conn *conn,
__u32 queue_id,
struct queue_job *job);
#endif /* _NCPLIB_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,204 +0,0 @@
#ifndef _NCPLIB_H
#define _NCPLIB_H
#include <linux/types.h>
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ipx.h>
enum connect_state {
NOT_CONNECTED = 0,
CONN_MOUNTED,
CONN_SOCKET
};
struct ncp_server {
int current_size;
int has_subfunction;
int silent;
int ncp_reply_size;
char *packet;
int lock;
enum connect_state is_connected;
int mount_fid;
struct sockaddr_ipx addr;
int ncp_sock;
int wdog_sock;
int wdog_pid;
__u8 sequence;
__u16 connection;
int completion;
int conn_status;
int reply_size;
char ncp_data[NCP_PACKET_SIZE];
};
#include <linux/ncp.h>
int
ncp_connect_mount(struct ncp_server *server, const char *mount_point);
int
ncp_connect(struct ncp_server *server);
int
ncp_disconnect(struct ncp_server *server);
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_read_property_value(struct ncp_server *server,
int object_type, char *object_name,
int segment, char *prop_name,
struct nw_property *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);
int
ncp_create_queue_job_and_file(struct ncp_server *server,
__u32 queue_id,
struct queue_job *job);
int
ncp_close_file_and_start_job(struct ncp_server *server,
__u32 queue_id,
struct queue_job *job);
#endif /* _NCPLIB_H */

File diff suppressed because it is too large Load Diff

View File

@@ -35,424 +35,99 @@ extern pid_t waitpid(pid_t, int *, int);
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ncp_mount.h>
#include "ncplib_user.h"
#include "ipxutil.h"
static char *progname;
static void
str_upper(char *name)
{
while (*name) {
*name = toupper(*name);
name = name + 1;
}
}
struct sap_query {
unsigned short query_type; /* net order */
unsigned short server_type; /* net order */
};
struct sap_server_ident {
unsigned short server_type __attribute__ ((packed));
char server_name[48] __attribute__ ((packed));
IPXNet server_network __attribute__ ((packed));
IPXNode server_node __attribute__ ((packed));
IPXPort server_port __attribute__ ((packed));
unsigned short intermediate_network __attribute__ ((packed));
};
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",ntohl(net));
}
void
ipx_fprint_port(FILE* file,IPXPort port)
{
fprintf(file,"%04X",ntohs(port));
}
void
ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx)
{
ipx_fprint_network(file,sipx->sipx_network);
fprintf(file,":");
ipx_fprint_node(file,sipx->sipx_node);
fprintf(file,":");
ipx_fprint_port(file,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);
}
int
ipx_sap_find_server(char *_name, int server_type, int timeout,
struct sockaddr_ipx *result)
{
struct sockaddr_ipx ipxs;
char data[1024];
int sock;
int opt;
int res = -1;
char name[strlen(_name)+1];
int name_len = strlen(_name);
fd_set rd, wr, ex;
struct timeval tv;
int packets;
if (name_len > 48) {
return -1;
}
strcpy(name, _name);
str_upper(name);
sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
if (sock==-1) {
return -1;
}
opt=1;
/* Permit broadcast output */
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
{
perror("setsockopt");
goto finished;
}
memset(&ipxs, 0, sizeof(ipxs));
ipxs.sipx_family=AF_IPX;
ipxs.sipx_network=htonl(0x0);
ipxs.sipx_port=htons(0x0);
ipxs.sipx_type=IPX_SAP_PTYPE;
if(bind(sock,(struct sockaddr*)&ipxs,sizeof(ipxs))==-1)
{
perror("bind");
goto finished;
}
*(unsigned short *)data = htons(0x0001);
*(unsigned short *)&(data[2]) = htons(server_type);
memset(&ipxs, 0, sizeof(ipxs));
ipxs.sipx_family=AF_IPX;
ipxs.sipx_network=htonl(0x0);
ipx_assign_node(ipxs.sipx_node, IPX_BROADCAST_NODE);
ipxs.sipx_port=htons(IPX_SAP_PORT);
ipxs.sipx_type=IPX_SAP_PTYPE;
if (sendto(sock, data, 4, 0,
(struct sockaddr *)&ipxs, sizeof(ipxs)) < 0) {
perror("sendto");
goto finished;
}
packets = 10;
while (packets > 0) {
packets -= 1;
FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex);
FD_SET(sock, &rd);
tv.tv_sec = timeout;
tv.tv_usec = 0;
if (select(sock+1, &rd, &wr, &ex, &tv) == -1) {
perror("select");
goto finished;
}
if (FD_ISSET(sock, &rd)) {
int len = recv(sock, data, 1024, 0);
int i;
struct sap_server_ident *ident;
for (i = 2; i < len; i += 64) {
ident = (struct sap_server_ident *)(data+i);
if ( (strncmp(name,ident->server_name,
name_len)==0)
&& (name_len < 48)
&& (ident->server_name[name_len] == '\0'))
{
result->sipx_family = AF_IPX;
result->sipx_network =
ident->server_network;
result->sipx_port = ident->server_port;
ipx_assign_node(result->sipx_node,
ident->server_node);
res = 0;
goto finished;
}
}
}
else
{
printf("nobody answered, server %s not found\n",
name);
exit(1);
}
}
finished:
close(sock);
return res;
}
int
ipx_sscanf_node(char *buf, unsigned char node[6])
{
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 i;
}
for (i=0; i<6; i++) {
node[i] = n[i];
}
return 6;
}
#include "ncplib.h"
void
test_filesearch(struct ncp_server *server)
test_print(struct ncp_conn *conn)
{
struct ncp_filesearch_info fsinfo;
struct ncp_file_info finfo;
if (ncp_file_search_init(server, 0, "sys:\\public", &fsinfo) != 0) {
printf("could not fs init\n");
return;
}
while (ncp_file_search_continue(server, &fsinfo,
0,
"*", &finfo) == 0) {
printf("name: %s\n", finfo.file_name);
}
return;
}
void
test_getfinfo(struct ncp_server *server)
{
struct ncp_file_info finfo;
ncp_get_finfo(server, 0, "sys:", "public", &finfo);
ncp_get_finfo(server, 0, "sys:login", "login.exe", &finfo);
}
void
testopen(struct ncp_server *server)
{
struct ncp_file_info finfo;
char buf[1025];
int bytes_read;
ncp_open_file(server, 0, "sys:\\etc\\samples\\protocol", 0,
AR_READ|AR_WRITE,
&finfo);
if (ncp_read(server, finfo.file_id, 0, 1024, buf, &bytes_read) == 0) {
printf("bytes: %d\n", bytes_read);
buf[bytes_read]=0;
puts(buf);
}
ncp_close_file(server, finfo.file_id);
}
void
testcreate(struct ncp_server *server)
{
if (ncp_rename_file(server, 0, "sys:\\me\\blub.txt", 0,
0, "sys:\\me\\blub1.txt") != 0) {
printf("create war nix\n");
}
if (ncp_create_directory(server, 0, "sys:\\me\\blubdir", 0xff) != 0) {
printf("mkdir war nix\n");
}
if (ncp_rename_directory(server, 0, "sys:\\me\\blubdir",
"\\me\\blubneu") != 0) {
printf("mvdir war nix\n");
return;
}
if (ncp_delete_directory(server, 0, "sys:\\me\\blubneu") != 0) {
printf("rmdir war nix\n");
return;
}
}
void
test_lookup(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
struct nw_file_info blub;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_open_create_file_or_subdir(server, &me, "BLUB.TXT",
OC_MODE_CREATE, 0, 0xffff,
&blub) != 0) {
printf("open error\n");
return;
}
return;
}
void
test_trunc(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
struct nw_file_info blub;
struct ncp_bindery_object q;
struct queue_job j;
struct print_job_record pj;
int written;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &me, "BLUB.TXT", &(blub.i)) != 0) {
printf("lookup error\n");
return;
}
if (ncp_open_create_file_or_subdir(server, &(blub.i), NULL,
OC_MODE_OPEN, 0, AR_READ | AR_WRITE,
&blub) != 0) {
printf("open error\n");
if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE,
"Q_DJ500", &q) != 0) {
printf("get oid error\n");
return;
}
if (ncp_write(server, blub.file_handle, 4, 0, "", &written) != 0) {
printf("trunc error\n");
memset(&j, 0, sizeof(j));
j.j.TargetServerID = 0xffffffff; /* any server */
/* at once */
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime));
j.j.JobType = htons(0);
strcpy(j.j.JobTextDescription, "Test Job");
memset(&pj, 0, sizeof(pj));
pj.Version = 0;
pj.TabSize = 8;
pj.Copies = htons(1);
pj.CtrlFlags = 0;
pj.Lines = htons(66);
pj.Rows = htons(80);
strcpy(pj.FormName, "test");
strcpy(pj.BannerName, "BannerName");
strcpy(pj.FnameBanner, "BannerFile");
strcpy(pj.FnameHeader, "HeaderName");
strcpy(pj.Path, "");
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0) {
printf("create error\n");
return;
}
if (ncp_close_file(server, blub.file_handle) != 0) {
if ((written = ncp_write(conn, j.file_handle, 0, 15,
"hallo, wie geht's?")) < 0) {
printf("write error\n");
return;
}
if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) {
printf("close error\n");
return;
}
}
return;
}
void
test_touch(struct ncp_server *server)
test_ls(struct ncp_conn *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
struct nw_info_struct blub;
int info_mask;
struct nw_modify_dos_info info;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &me, "BLUB.TXT", &blub) != 0) {
printf("lookup error\n");
return;
}
info_mask = 0;
memset(&info, 0, sizeof(info));
info_mask |= DM_MODIFY_DATE;
info_mask |= DM_MODIFY_TIME;
if (ncp_modify_file_or_subdir_dos_info(server, &blub, info_mask,
&info) != 0) {
printf("modify error\n");
return;
}
return;
}
void
test_ls(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_search_sequence seq;
struct nw_info_struct public;
struct ncp_search_seq seq;
struct nw_info_struct found;
int res;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0)
{
printf("lookup error\n");
return;
}
if (ncp_initialize_search(server, &sys, &seq) != 0) {
if (ncp_do_lookup(server, &sys, "PUBLIC", &public) != 0)
{
printf("lookup public error\n");
return;
}
if (ncp_initialize_search(server, &public, 4, &seq) != 0)
{
printf("init error\n");
return;
}
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0) {
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0)
{
printf("found %s: %s\n",
(found.attributes & aDIR) ? "dir " : "file",
found.entryName);
}
if (res == 0xfe) {
if (res == 0xfe)
{
printf("result: no more files\n");
}
else
@@ -462,178 +137,19 @@ test_ls(struct ncp_server *server)
return;
}
void
test_ren(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_ren_or_mov_file_or_subdir(server, &me, "BLUB.TXT",
&me, "BLUB1.TXT") != 0) {
printf("ren error\n");
return;
}
}
void
test_rm(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_del_file_or_subdir(server, &me, "BLUB1.TXT") != 0) {
printf("ren error\n");
return;
}
}
void
test_mkdir(struct ncp_server *server)
{
struct nw_info_struct sys;
struct nw_info_struct me;
struct nw_file_info dir1;
struct nw_file_info dir2;
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
printf("lookup error\n");
return;
}
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
printf("lookup error\n");
return;
}
if (ncp_open_create_file_or_subdir(server, &me, "DIR1",
OC_MODE_CREATE, aDIR, 0xffff, &dir1)
!= 0) {
printf("mkdir1 error\n");
return;
}
if (ncp_open_create_file_or_subdir(server, &me, "DIR2",
OC_MODE_CREATE, aDIR, 0xffff, &dir2)
!= 0) {
printf("mkdir2 error\n");
return;
}
if (ncp_del_file_or_subdir(server, &me, "DIR1") != 0) {
printf("rmdir error\n");
return;
}
}
void
test_print(struct ncp_server *server)
{
struct ncp_bindery_object q;
struct queue_job j;
struct print_job_record pj;
int written;
if (ncp_get_bindery_object_id(server, NCP_BINDERY_PQUEUE,
"Q_DJ500", &q) != 0) {
printf("get oid error\n");
return;
}
memset(&j, 0, sizeof(j));
j.j.TargetServerID = 0xffffffff; /* any server */
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime)); /* at once */
j.j.JobType = 0xffff;
strcpy(j.j.JobTextDescription, "Test Job");
memset(&pj, 0, sizeof(pj));
pj.Version = 0;
pj.TabSize = 0;
pj.Copies = 1;
pj.CtrlFlags = 0;
pj.Lines = 0;
pj.Rows = 0;
strcpy(pj.FormName, "");
strcpy(pj.Banner, "");
strcpy(pj.FnameBanner, "");
strcpy(pj.FnameHeader, "");
strcpy(pj.Path, "");
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
if (ncp_create_queue_job_and_file(server, q.object_id, &j) != 0) {
printf("create error\n");
return;
}
if (ncp_write(server, j.file_handle, 0, 5, "hallo", &written) != 0) {
printf("write error\n");
return;
}
if (ncp_close_file_and_start_job(server, q.object_id, &j) != 0) {
printf("close error\n");
return;
}
return;
}
int
main(int argc, char **argv)
main(int argc, char *argv[])
{
struct ncp_server serv;
struct ncp_server *server = &serv;
struct ncp_conn conn;
progname = argv[0];
if (argc != 2) {
printf("usage: %s server\n", argv[0]);
exit(1);
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
{
perror("ncp_initialize");
return 1;
}
if (ipx_sap_find_server(argv[1], IPX_SAP_FILE_SERVER,
3, &(serv.addr)) != 0) {
printf("could not find server %s\n", argv[1]);
exit(1);
}
if (ncp_connect(server) != 0) {
printf("could not connect\n");
exit(1);
}
if (ncp_login_user(server, "me", "ME") != 0) {
printf("login error\n");
exit(1);
}
test_touch(server);
ncp_disconnect(server);
test_ls(&conn);
ncp_close(&conn);
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* ncpumount.c
* nwumount.c
*
* Copyright (C) 1995 by Volker Lendecke
*

312
util/nprint.c Normal file
View File

@@ -0,0 +1,312 @@
/*
* nwprint.c
*
* Send data to a NetWare print queue.
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <ctype.h>
#include "ncplib.h"
static char *progname;
static void
usage(void);
static void
str_upper(char *name);
void
main(int argc, char *argv[])
{
struct ncp_conn conn;
char default_queue[] = "*";
char *queue = default_queue;
int opt;
struct ncp_bindery_object q;
struct queue_job j;
struct print_job_record pj;
int written, read_this_time;
char buf[8192];
char *file_name;
int file;
progname = argv[0];
memzero(j); memzero(pj); memzero(q); memzero(conn);
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
{
perror("Could not open connection");
exit(1);
}
/*
* Fill in default values for print job
*/
j.j.TargetServerID = 0xffffffff; /* any server */
/* at once */
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime));
j.j.JobType = htons(0);
strcpy(j.j.JobTextDescription, "No Description");
pj.Version = 0;
pj.TabSize = 8;
pj.Copies = htons(1);
pj.CtrlFlags = 0;
pj.Lines = htons(66);
pj.Rows = htons(80);
strcpy(pj.FnameHeader, "stdin");
while ((opt = getopt(argc, argv, "q:d:p:b:f:l:r:c:t:F:TN"))!=EOF)
{
switch (opt) {
case 'p':
/* Path */
pj.CtrlFlags |= PRINT_BANNER;
if (strlen(optarg) >= sizeof(pj.Path))
{
strncpy(pj.Path, optarg,
sizeof(pj.Path));
}
else
{
strcpy(pj.Path, optarg);
}
break;
case 'b':
/* Banner Name */
pj.CtrlFlags |= PRINT_BANNER;
if (strlen(optarg) >= sizeof(pj.BannerName))
{
strncpy(pj.BannerName, optarg,
sizeof(pj.BannerName));
}
else
{
strcpy(pj.BannerName, optarg);
}
break;
case 'f':
/* File Name in Banner */
pj.CtrlFlags |= PRINT_BANNER;
if (strlen(optarg) >= sizeof(pj.FnameBanner))
{
strncpy(pj.FnameBanner, optarg,
sizeof(pj.FnameBanner));
}
else
{
strcpy(pj.FnameBanner, optarg);
}
break;
case 'l':
/* lines, default: 66 */
if ((atoi(optarg) < 0) || (atoi(optarg) > 65535))
{
fprintf(stderr,
"invalid line number: %s\n", optarg);
break;
}
pj.Lines = htons(atoi(optarg));
pj.CtrlFlags |= EXPAND_TABS;
break;
case 'r':
/* rows, default: 80 */
if ((atoi(optarg) < 0) || (atoi(optarg) > 65535))
{
fprintf(stderr,
"invalid row number: %s\n", optarg);
break;
}
pj.Rows = htons(atoi(optarg));
pj.CtrlFlags |= EXPAND_TABS;
break;
case 'c':
/* copies, default: 1 */
if ((atoi(optarg) < 0) || (atoi(optarg) > 65000))
{
fprintf(stderr,
"invalid copies: %s\n", optarg);
break;
}
pj.Copies = htons(atoi(optarg));
pj.CtrlFlags |= EXPAND_TABS;
break;
case 't':
/* tab size, default: 8 */
if ((atoi(optarg) < 0) || (atoi(optarg) > 255))
{
fprintf(stderr,
"invalid tab size: %s\n", optarg);
break;
}
pj.TabSize = atoi(optarg);
pj.CtrlFlags |= EXPAND_TABS;
break;
case 'T':
/* expand tabs, default tabsize: 8 */
pj.CtrlFlags |= EXPAND_TABS;
break;
case 'N':
/* no form feed */
pj.CtrlFlags |= NO_FORM_FEED;
break;
case 'F':
/* Form number, default: 0 */
if ((atoi(optarg) < 0) || (atoi(optarg) > 255))
{
fprintf(stderr,
"invalid form number: %s\n", optarg);
break;
}
j.j.JobType = htons(atoi(optarg));
break;
case 'q':
/* Queue name to print on, default: '*' */
if (strlen(optarg) >= NCP_BINDERY_NAME_LEN)
{
printf("queue name too long: %s\n",
optarg);
exit(1);
}
queue = optarg;
break;
case 'd':
/* Job Description */
pj.CtrlFlags |= PRINT_BANNER;
if (strlen(optarg) >= sizeof(j.j.JobTextDescription))
{
strncpy(j.j.JobTextDescription, optarg,
sizeof(j.j.JobTextDescription));
}
else
{
strcpy(j.j.JobTextDescription, optarg);
}
break;
default:
usage();
exit(1);
}
}
if (optind != argc-1)
{
usage();
exit(1);
}
file_name = argv[optind];
if (strcmp(file_name, "-") == 0)
{
file = 0; /* stdin */
}
else
{
file = open(file_name, O_RDONLY, 0);
if (file < 0)
{
perror("could not open file");
exit(1);
}
if (strlen(file_name) >= sizeof(pj.FnameHeader))
{
strncpy(pj.FnameHeader, file_name,
sizeof(pj.FnameHeader));
}
else
{
strcpy(pj.FnameHeader, file_name);
}
if (strlen(pj.FnameBanner) == 0)
{
if (strlen(file_name) >= sizeof(pj.FnameBanner))
{
strncpy(pj.FnameBanner, file_name,
sizeof(pj.FnameBanner));
}
else
{
strcpy(pj.FnameBanner, file_name);
}
}
}
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
str_upper(queue);
if (ncp_scan_bindery_object(&conn, 0xffffffff, NCP_BINDERY_PQUEUE,
queue, &q) != 0)
{
printf("could not find queue %s\n", queue);
return;
}
if (ncp_create_queue_job_and_file(&conn, q.object_id, &j) != 0)
{
printf("create error\n");
return;
}
written = 0;
do
{
read_this_time = read(file, buf, sizeof(buf));
if (read_this_time < 0)
{
break;
}
if (ncp_write(&conn, j.file_handle,
written, read_this_time, buf) < read_this_time)
{
break;
}
written += read_this_time;
} while (read_this_time > 0);
close(file);
if (ncp_close_file_and_start_job(&conn, q.object_id, &j) != 0) {
printf("close error\n");
return;
}
ncp_close(&conn);
}
static void
usage(void)
{
fprintf(stderr, "usage: %s [options] file\n", progname);
exit(1);
}
static void
str_upper(char *name)
{
while (*name) {
*name = toupper(*name);
name = name + 1;
}
}

View File

@@ -89,9 +89,8 @@ typedef unsigned char buf32[32];
typedef unsigned char buf16[16];
typedef unsigned char buf8[8];
typedef unsigned char buf4[4];
typedef unsigned char u8;
static u8 encrypttable[256] =
static unsigned char encrypttable[256] =
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
@@ -142,8 +141,8 @@ shuffle1(buf32 temp, unsigned char *target)
}
void
shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
static void
shuffle(const unsigned char *lon, const unsigned char *buf, int buflen,
unsigned char *target)
{
int b2, d, s;
@@ -191,8 +190,10 @@ shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
}
void
nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til)
static void
nw_encrypt(const unsigned char *fra,
const unsigned char *buf,
unsigned char *til)
{
buf32 k;
int s;

View File

@@ -1,5 +0,0 @@
void
shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
unsigned char *target);
void
nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til);

75
util/pqlist.c Normal file
View File

@@ -0,0 +1,75 @@
/*
* pqlist.c
*
* List all print queues on a server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include "ncplib.h"
int
main(int argc, char **argv)
{
struct ncp_conn conn;
struct ncp_bindery_object q;
int found = 0;
char default_pattern[] = "*";
char *pattern = default_pattern;
char *p;
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
{
perror("Could not open connection");
return 1;
}
if (argc > 2)
{
fprintf(stderr, "usage: %s [options] [pattern]\n", argv[0]);
return 1;
}
if (argc == 2)
{
pattern = argv[1];
}
for (p = pattern; *p != '\0'; p++)
{
*p = toupper(*p);
}
if (isatty(1))
{
printf("\nServer: %s\n", conn.server);
printf("%-52s%-10s\n"
"-----------------------------------------------"
"-------------\n",
"Print queue name",
"Queue ID");
}
q.object_id = 0xffffffff;
while (ncp_scan_bindery_object(&conn, q.object_id,
NCP_BINDERY_PQUEUE, "*", &q) == 0)
{
found = 1;
printf("%-52s", q.object_name);
printf("%08lx\n", q.object_id);
}
if ((found == 0) && (isatty(1)))
{
printf("No queues found\n");
}
ncp_close(&conn);
return 0;
}

91
util/slist.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* slist.c
*
* List all file server that are known in the IPX network.
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
void
main(int argc, char *argv[])
{
struct ncp_conn conn;
struct ncp_bindery_object obj;
int found = 0;
char default_pattern[] = "*";
char *pattern = default_pattern;
char *p;
if (argc > 2)
{
printf("usage: %s [pattern]\n", argv[0]);
exit(1);
}
if (argc == 2)
{
pattern = argv[1];
}
for (p = pattern; *p != '\0'; p++)
{
*p = toupper(*p);
}
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
{
perror("ncp_connect");
exit(1);
}
if (isatty(1))
{
printf("\n%-52s%-10s%-12s\n"
"-----------------------------------------------"
"---------------------------\n",
"Known NetWare File Servers",
"Network",
"Node Address");
}
obj.object_id = 0xffffffff;
while (ncp_scan_bindery_object(&conn, obj.object_id,
NCP_BINDERY_FSERVER, pattern,
&obj) == 0)
{
struct nw_property prop;
struct prop_net_address *naddr
= (struct prop_net_address *)&prop;
found = 1;
printf("%-52s", obj.object_name);
if (ncp_read_property_value(&conn, NCP_BINDERY_FSERVER,
obj.object_name, 1, "NET_ADDRESS",
&prop) == 0)
{
ipx_print_network(naddr->network);
printf(" ");
ipx_print_node(naddr->node);
}
printf("\n");
}
if ((found == 0) && (isatty(1)))
{
printf("No servers found\n");
}
ncp_close(&conn);
}

View File

@@ -3,6 +3,5 @@
# abcd is my ipx network number and 1234 my server's internal network number.
# 00001b038b11 is the server's node number.
#
ipx_interface add -p eth0 EtherII 10
ipx_route add 1992 10 00001b3bc0c9
ipx_route add 1234 10 00001b038b11
ipx_interface add -p eth0 EtherII 1234
ipx_route add 10 1234 00001b039949