Compare commits

..

8 Commits

Author SHA1 Message Date
ncpfs archive import
7179281575 Import ncpfs 2.0.2 2026-04-28 20:39:58 +02:00
ncpfs archive import
b8d830f9a3 Import ncpfs 2.0.1 2026-04-28 20:39:58 +02:00
ncpfs archive import
b36a27bedb Import ncpfs 2.0.0 2026-04-28 20:39:58 +02:00
ncpfs archive import
7d0e3d011b Import ncpfs 0.24 2026-04-28 20:39:58 +02:00
ncpfs archive import
84cb1f167d Import ncpfs 0.23 2026-04-28 20:39:58 +02:00
ncpfs archive import
64f006632a Import ncpfs 0.22 2026-04-28 20:39:58 +02:00
ncpfs archive import
92f749a943 Import ncpfs 0.21 2026-04-28 20:39:58 +02:00
ncpfs archive import
6cb56005ea Import ncpfs 0.20 2026-04-28 20:39:58 +02:00
62 changed files with 5802 additions and 293 deletions

BIN
.downloads/ncpfs-0.20.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.21.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.22.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.23.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.24.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.0.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.1.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.2.tgz Normal file

Binary file not shown.

66
Changes
View File

@@ -1,5 +1,69 @@
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.
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
ncpfs-2.0.1 -> ncpfs-2.0.2
- Added some values to ipxparse.
- Added a patch against 2.0.7 for long file names support. I did not
apply this change to the 1.2-module. Please upgrade to 2.0.7 if you
want to use long file names.
- nwbpvalues can print ITEM properties
ncpfs-2.0.0 -> ncpfs-2.0.1
- Added some values to ipxparse.
- Added the little bindery utilities. Maybe someone has the time to
write a shellscript named 'nwadduser' ?
- Fixed a bug that made the __255 message reappear. Many thanks to
Guntram Blom for his detailed bug report.
- Fixed a bug that made ncpfs incompatible with W95's server
capabilities. Thanks to Tomasz Babczynski
<faster@dino.ict.pwr.wroc.pl> for this one.
ncpfs-0.24 -> ncpfs-2.0.0
- Changed the numbering scheme :-).
- Added npasswd. Many thanks to Guntram Blom for his work!
- Hopefully improved error messages a bit
- Hopefully made slist a bit more robust
ncpfs-0.23 -> ncpfs-0.24
- Fixed a bug that made it impossible to umount a filesystem after you
tried 'mkdir .' or 'mkdir ..'.
- Fixed a bad race condition when opening files.
- Made the default timeout values more robust.
ncpfs-0.22 -> ncpfs-0.23
- Fixed a memory allocation problem in nwmsg.c. Thanks to
Andrew Ross <anr1001@hermes.cam.ac.uk>
- slist hopefully does not ask for a password anymore.
- cleaned up error messages a bit.
- ncpmount now calls modprobe instead of insmod.
ncpfs-0.21 -> ncpfs-0.22
- removed a bad race condition in kernel-1.2/src/dir.c.
- handle 0x9999-responses from the ncp server correctly.
- Bindery functions in ncplib.c by Brian G. Reid (breid@tim.com)
- set blocksize to 512 to satisfy 'du -k'
ncpfs-0.20 -> ncpfs-0.21
- Included two bugfixes in ncplib.c found by Jeff Buhrt
<buhrt@iquest.net>.
- Included a bugfix in kernel code that could only show for servers
that do not support namespace calls. I should have tried ncpfs
against lwared... Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for
this fix.
ncpfs-0.19 -> ncpfs-0.20
- Changed the home site for ncpfs from linux01.gwdg.de:/pub/ncpfs
to ftp.gwdg.de:/pub/linux/misc/ncpfs. linux01 will remain available,
but we would like to reduce the load on that machine. Sites
mirroring linux01 please redirect your mirror software to
ftp.gwdg.de. Thanks.
- Removed a bug in ncplib.c that made slist require a full
login. Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for the hint.
- The first real user contribution: ncopy by Brian G. Reid
(breid@tim.com) and Tom C. Henderson (thenderson@tim.com). Many
thanks to you! If you find bugs in ncopy, tell them, not me ;-)
- Handle expired passwords. Thanks to "Mathew Lim" <M.Lim@sp.ac.sg>
for the hint.
ncpfs-0.18 -> ncpfs-0.19

37
FAQ
View File

@@ -4,10 +4,43 @@ enough.
-------------------------------------------------------------------------------
Q: The ncpfs utilities like slist or ncpmount tell me that they can
not find a server, although I'm sure there are servers on my
net. What's wrong?
You probably used
ipx_configure --auto_interface=on --auto_primary=on
and you have Windows (95?) workstations on your network. Windows 95
makes Linux configure IPX interfaces for non-existent frame types. To
solve this problem, you have to configure your IPX interface manually
with the command
ipx_interface add -p <device> <frame>
For <device> use eth0, eth1 or whatever you network adapter is
called. The value for <frame> must match the frame type used on your
network. Possible values are 802.2, 802.3, SNAP and EtherII.
-------------------------------------------------------------------------------
Q: I have difficulties with NetWare 4.1. What can I do?
To be honest, I do not really know. Currently my only test equipment
is a NetWare 3.11 server. You should make your 4.1 Server as
3.x-compatible as it can be. As I do not know 4.1, you are on your own
doing this.
A promising hint that has already helped some people is to switch off
packet signatures on the 4.1 server, as ncpfs does not support them.
-------------------------------------------------------------------------------
Q: Does ncpfs support long file names, using the OS/2 namespace?
No. Not yet. I still have to sort out how that really works. But it should
certainly be possible.
Yes. But you will have to patch your kernel. Look at the file
kernel-2.0/README for more information.
-------------------------------------------------------------------------------

View File

@@ -2,31 +2,29 @@
# Makefile for the linux ncp-filesystem routines.
#
VERSION = 0.19
TOPDIR = $(shell pwd)
BINDIR = /usr/local/bin
SBINDIR = /sbin
INTERM_BINDIR = $(TOPDIR)/bin
SUBDIRS = util ipx-1.0 man
#
# 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
VERSION = 2.0.2
# If you are using kerneld to autoload ncp support,
# uncomment this (kerneld is in linux since about 1.3.57):
#KERNELD = -DHAVE_KERNELD
TOPDIR = $(shell pwd)
BINDIR = /usr/local/bin
SBINDIR = /sbin
INTERM_BINDIR = $(TOPDIR)/bin
SUBDIRS = util ipx-1.0 man
KVERSION=$(shell uname -r | cut -b1-3)
ifeq ($(KVERSION),1.2)
SUBDIRS += kernel-1.2/src
INCLUDES = -I$(TOPDIR)/kernel-1.2
endif
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
all:
for i in $(SUBDIRS); do make -C $$i; done
for i in $(SUBDIRS); do make -C $$i all; done
dep:
for i in $(SUBDIRS); do make -C $$i dep; done
@@ -44,6 +42,7 @@ clean:
mrproper: clean
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
make -C util mrproper
make -C ipxdump mrproper
modules: ncpfs.o
@@ -51,7 +50,11 @@ SRCPATH=$(shell pwd)
SRCDIR=$(shell basename $(SRCPATH))
DISTFILE=$(SRCDIR).tgz
dist: tgz
dist: mrproper
(cd ..; \
tar cvf - $(SRCDIR) | \
gzip -9 > $(DISTFILE); \
mv $(DISTFILE) $(SRCDIR))
make dep
make all

21
README
View File

@@ -3,8 +3,22 @@ some little utilities it also contains nprint, which enables you to
print on NetWare print queues. The opposite side, pserver, is also
provided.
I'm planning major changes in the structure of ncpfs for Linux 2.1.x
which will break the binary compatibility. So I changed the numbering
scheme for ncpfs. ncpfs-2.0.x will be the version to be used with
Linux 2.0.0 and older kernels, and ncpfs-2.1.x will be the version for
the development kernels.
INSTALLATION
Before you start the installation, make sure that your kernel has IPX
support compiled in. When 'make config' asks you for
The IPX protocol (CONFIG_IPX) [N/y/m/?]
simply answer 'y'. Probably you do not need the full internal net that
you are asked for next.
The installation of ncpfs depends on the kernel version you are
using. For kernel 1.2, you should simply type 'make' and look at
what's in the bin/ directory after that. Please be sure that your
@@ -22,11 +36,8 @@ 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.71 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.
If you are running kerneld, please uncomment the corresponding line in
the Makefile to reflect this.
HELP

5
TODO
View File

@@ -1,9 +1,6 @@
Here's a list of things I want to do. Feel free to send suggestions,
or even help me ;-).
- little utilities for bindery access, such as nwlsobj, nwlsprop,
nwcreateobj and so on.
- Add flags to pserver's command line, so that the print command can
find out the name of user who printed the job.
@@ -15,6 +12,4 @@ or even help me ;-).
a single NCP connection. This should make the trade-off mentioned in
ncpmount.8 unnecessary.
- long file names
- Do some kind of mapping of NCP uid's to unix uid's

View File

@@ -12,6 +12,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
struct option options[] = {
{ "auto_primary", required_argument, NULL, 1 },
@@ -66,8 +67,14 @@ main(int argc, char **argv)
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
int old_errno = errno;
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
if (old_errno == -EINVAL)
{
fprintf(stderr, "Probably you have no IPX support in "
"your kernel\n");
}
exit(-1);
}

View File

@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
static struct ifreq id;
static char *progname;
@@ -118,8 +119,14 @@ ipx_add_interface(int argc, char **argv)
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
int old_errno = errno;
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
if (old_errno == -EINVAL)
{
fprintf(stderr, "Probably you have no IPX support in "
"your kernel\n");
}
exit(-1);
}

View File

@@ -236,7 +236,7 @@ handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
switch( packet_type )
{
case __constant_ntohs(ETH_P_IPX):
handle_ipx("EtherII ", &(buf[sizeof(struct ethhdr)]));
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
break;
default:
handle_other(buf, length, saddr);

View File

@@ -89,10 +89,31 @@ struct ncp_reply_header {
__u8 data[0] __attribute__ ((packed));
};
#define NCP_BURST_PACKET (0x7777)
struct ncp_burst_header {
__u16 type __attribute__ ((packed));
__u8 system_flags __attribute__ ((packed));
__u8 stream_type __attribute__ ((packed));
__u32 source_conn __attribute__ ((packed));
__u32 dest_conn __attribute__ ((packed));
__u32 packet_sequence __attribute__ ((packed));
__u32 send_delay __attribute__ ((packed));
__u16 burst_sequence __attribute__ ((packed));
__u16 ack_sequence __attribute__ ((packed));
__u32 burst_length __attribute__ ((packed));
__u32 data_offset __attribute__ ((packed));
__u16 data_bytes __attribute__ ((packed));
__u16 missing_frags __attribute__ ((packed));
};
void handle_ipx (unsigned char *buf, int length, char *frame, int no);
void handle_ncp (struct sockaddr_ipx *source,
struct sockaddr_ipx *target,
unsigned char *buf, int length, int no);
int handle_burst(struct sockaddr_ipx *source,
struct sockaddr_ipx *target,
unsigned char *buf, int length, int no);
#define SAP_MAX_SERVER_NAME_LENGTH 48 /* in network packets */
#define SAP_MAX_SAPS_PER_PACKET 7
@@ -165,6 +186,12 @@ handle_ipx (unsigned char *buf, int length, char *frame, int no)
ipx_print_saddr(&d_addr);
printf("\n");
if (handle_burst(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
length - sizeof(struct ipx_packet), no) != 0)
{
return;
}
if ( (ntohs(s_addr.sipx_port) == 0x451)
|| (ntohs(d_addr.sipx_port) == 0x451))
{
@@ -253,6 +280,55 @@ handle_ipx (unsigned char *buf, int length, char *frame, int no)
}
int handle_burst(struct sockaddr_ipx *source,
struct sockaddr_ipx *target,
unsigned char *buf, int length, int no)
{
struct ncp_burst_header *rq = (struct ncp_burst_header *)buf;
if (rq->type != NCP_BURST_PACKET)
{
return 0;
}
printf("Burst Packet\n");
printf("Stream Type: %02X, System Flags: %02X\n",
rq->stream_type, rq->system_flags);
printf("Source Conn: %08X, Dest Conn: %08X, Packet Seq: %08X\n",
rq->source_conn, rq->dest_conn,
(unsigned int)ntohl(rq->packet_sequence));
printf("Send Delay: %08X, Burst Seq: %04X, Ack Seq: %04X\n",
(unsigned int)ntohl(rq->send_delay), ntohs(rq->burst_sequence),
ntohs(rq->ack_sequence));
printf("Burst Length: %08X\n", (unsigned int)ntohl(rq->burst_length));
printf("Data Offset: %08X, Data Bytes: %04X, Missing Frags: %04X\n",
(unsigned int)ntohl(rq->data_offset), ntohs(rq->data_bytes),
ntohs(rq->missing_frags));
if (ntohs(rq->data_bytes) == 24)
{
struct ncp_burst_request
{
struct ncp_burst_header h __attribute__ ((packed));
__u32 function __attribute__ ((packed));
__u32 file_handle __attribute__ ((packed));
__u8 reserved[8] __attribute__ ((packed));
__u32 file_offset __attribute__ ((packed));
__u32 number_of_bytes __attribute__ ((packed));
} *brq = (struct ncp_burst_request *)rq;
printf("Assuming Burst Request:\n");
printf("%s: Handle %08X, Offset %08X, Bytes %08X\n",
brq->function == 1 ? "Read " : "Write",
brq->file_handle,
(unsigned int)ntohl(brq->file_offset),
(unsigned int)ntohl(brq->number_of_bytes));
}
printf("\n");
return 1;
}
void handle_ncp (struct sockaddr_ipx *source,
struct sockaddr_ipx *target,
unsigned char *buf, int length, int no)
@@ -275,6 +351,143 @@ void handle_ncp (struct sockaddr_ipx *source,
switch(rq->function)
{
case 20:
printf("fn: %-3d\n", rq->function);
printf("Get File Server Date and Time\n");
break;
case 21:
printf("fn: %-3d, subfn: %-3d\n",
rq->function, data[2]);
switch(data[2])
{
case 0:
printf("Send Broadcast Message\n");
break;
case 1:
printf("Get Broadcast Message\n");
break;
}
data += 3;
data_length -= 3;
break;
case 22:
printf("fn: %-3d, subfn: %-3d\n",
rq->function, data[2]);
switch(data[2])
{
case 00:
printf("Set Directory Handle\n");
break;
case 01:
printf("Get Directory Path\n");
break;
case 03:
printf("Get Effective Directory Rights\n");
break;
case 05:
printf("Get Volume Number\n");
break;
case 06:
printf("Get Volume Name\n");
break;
case 18:
printf("Allocate Permanent Dir Handle\n");
break;
case 20:
printf("Deallocate Directory Handle\n");
break;
case 21:
printf("Get Volume Info with handle\n");
break;
case 48:
printf("Get Name Space Directory Entry\n");
break;
}
data += 3;
data_length -= 3;
break;
case 23:
printf("fn: %-3d, subfn: %-3d\n", rq->function,
data[2]);
switch(data[2])
{
case 17:
printf("Get Fileserver Information\n");
break;
case 22:
printf("Get Station's logged Info (old)\n");
break;
case 23:
printf("Get Crypt Key\n");
break;
case 24:
printf("Encrypted Login\n");
break;
case 28:
printf("Get Connection Information\n");
break;
case 53:
printf("Get Bindery Object ID\n");
break;
case 55:
printf("Scan Bindery Object\n");
break;
case 61:
printf("Read Property Value\n");
break;
case 62:
printf("Write Property Value\n");
break;
case 70:
printf("Get Bindery Access Level\n");
break;
}
data += 3;
data_length -= 3;
break;
case 24:
printf("fn: %-3d\n", rq->function);
printf("End of Job\n");
break;
case 33:
printf("fn: %-3d\n", rq->function);
printf("Negotiate Buffer size\n");
break;
case 34:
printf("fn: %-3d, subfn: %-3d\n", rq->function,
data[2]);
data += 3;
data_length -= 3;
break;
case 62:
printf("fn: %-3d\n", rq->function);
printf("File Search Initialize\n");
break;
case 63:
printf("fn: %-3d\n", rq->function);
printf("File Search Continue\n");
break;
case 64:
printf("fn: %-3d\n", rq->function);
printf("Search for a file\n");
break;
case 66:
printf("fn: %-3d\n", rq->function);
printf("Close File\n");
break;
case 72:
printf("fn: %-3d\n", rq->function);
printf("Read from File\n");
break;
case 73:
printf("fn: %-3d\n", rq->function);
printf("Write to File\n");
break;
case 75:
printf("fn: %-3d\n", rq->function);
printf("Set File Time Date Stamp\n");
break;
case 87:
printf("fn: %-3d, subfn: %-3d\n",
rq->function, data[0]);
@@ -307,89 +520,20 @@ void handle_ncp (struct sockaddr_ipx *source,
case 8:
printf("Delete a File Or Subdirectory\n");
break;
case 12:
printf("Allocate Short Directory Handle\n");
break;
}
data += 1;
data_length -= 1;
break;
case 21:
printf("fn: %-3d, subfn: %-3d\n",
rq->function, data[2]);
switch(data[2])
{
case 0:
printf("Send Broadcast Message\n");
break;
case 1:
printf("Get Broadcast Message\n");
break;
}
data += 3;
data_length -= 3;
break;
case 22:
printf("fn: %-3d, subfn: %-3d\n",
rq->function, data[2]);
switch(data[2])
{
case 21:
printf("Get Volume Info with handle\n");
break;
}
data += 3;
data_length -= 3;
break;
case 23:
printf("fn: %-3d, subfn: %-3d\n", rq->function,
data[2]);
switch(data[2])
{
case 17:
printf("Get Fileserver Information\n");
break;
case 28:
printf("Get Connection Information\n");
break;
case 55:
printf("Scan Bindery Object\n");
break;
}
data += 3;
data_length -= 3;
break;
case 24:
case 97:
printf("fn: %-3d\n", rq->function);
printf("End of Job\n");
printf("Get Big Packet NCP Max Packet Size\n");
break;
case 34:
printf("fn: %-3d, subfn: %-3d\n", rq->function,
data[2]);
data += 3;
data_length -= 3;
break;
case 62:
case 101:
printf("fn: %-3d\n", rq->function);
printf("File Search Initialize\n");
break;
case 63:
printf("fn: %-3d\n", rq->function);
printf("File Search Continue\n");
break;
case 64:
printf("fn: %-3d\n", rq->function);
printf("Search for a file\n");
break;
case 66:
printf("fn: %-3d\n", rq->function);
printf("Close File\n");
break;
case 73:
printf("fn: %-3d\n", rq->function);
printf("Write to File\n");
break;
case 75:
printf("fn: %-3d\n", rq->function);
printf("Set File Time Date Stamp\n");
printf("Packet Burst Connection Request\n");
break;
default:
printf("fn: %-3d\n", rq->function);

View File

@@ -61,7 +61,7 @@ struct ncp_fs_info {
#define NCP_READDIR_CACHE_SIZE 64
#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
#define NCP_MAX_RPC_TIMEOUT (6*HZ)
/* Guess, what 0x564c is :-) */
#define NCP_SUPER_MAGIC 0x564c

View File

@@ -20,6 +20,7 @@
#include <linux/ncp_fs.h>
#include <asm/segment.h>
#include <linux/errno.h>
#include <linux/locks.h>
#include "ncplib_kernel.h"
struct ncp_dirent {
@@ -200,12 +201,30 @@ static int c_size;
static int c_seen_eof;
static int c_last_returned_index;
static struct ncp_dirent* c_entry = NULL;
static int c_lock = 0;
static struct wait_queue *c_wait = NULL;
static inline void
ncp_lock_dircache(void)
{
while (c_lock)
sleep_on(&c_wait);
c_lock = 1;
}
static inline void
ncp_unlock_dircache(void)
{
c_lock = 0;
wake_up(&c_wait);
}
static int
ncp_readdir(struct inode *inode, struct file *filp,
struct dirent *dirent, int count)
{
int result, i = 0;
int result = 0;
int i = 0;
int index = 0;
struct ncp_dirent *entry = NULL;
struct ncp_server *server = NCP_SERVER(inode);
@@ -238,6 +257,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
return -EIO;
}
ncp_lock_dircache();
if (c_entry == NULL)
{
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
@@ -245,7 +265,8 @@ ncp_readdir(struct inode *inode, struct file *filp,
if (c_entry == NULL)
{
printk("ncp_readdir: no MEMORY for cache\n");
return -ENOMEM;
result = -ENOMEM;
goto finished;
}
}
@@ -255,10 +276,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
if (filldir(dirent,".",1, filp->f_pos,
ncp_info_ino(server, dir)) < 0)
{
return 0;
goto finished;
}
filp->f_pos += 1;
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
goto finished;
}
if (filp->f_pos == 1)
@@ -266,10 +288,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
if (filldir(dirent,"..",2, filp->f_pos,
ncp_info_ino(server, dir->dir)) < 0)
{
return 0;
goto finished;
}
filp->f_pos += 1;
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
goto finished;
}
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
@@ -286,42 +309,44 @@ ncp_readdir(struct inode *inode, struct file *filp,
}
if ((entry == NULL) && c_seen_eof)
{
return 0;
goto finished;
}
}
if (entry == NULL)
{
int entries;
DDPRINTK("ncp_readdir: Not found in cache.\n");
if (ncp_is_server_root(inode))
{
result = ncp_read_volume_list(server, filp->f_pos,
NCP_READDIR_CACHE_SIZE);
DPRINTK("ncp_read_volume_list returned %d\n", result);
entries = ncp_read_volume_list(server, filp->f_pos,
NCP_READDIR_CACHE_SIZE);
DPRINTK("ncp_read_volume_list returned %d\n", entries);
}
else
{
result = ncp_do_readdir(server, inode, filp->f_pos,
NCP_READDIR_CACHE_SIZE,
c_entry);
DPRINTK("ncp_readdir returned %d\n", result);
entries = ncp_do_readdir(server, inode, filp->f_pos,
NCP_READDIR_CACHE_SIZE,
c_entry);
DPRINTK("ncp_readdir returned %d\n", entries);
}
if (result < 0)
if (entries < 0)
{
c_dev = 0;
c_ino = 0;
return result;
result = entries;
goto finished;
}
if (result > 0)
if (entries > 0)
{
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE);
c_dev = inode->i_dev;
c_ino = inode->i_ino;
c_size = result;
c_size = entries;
entry = c_entry;
c_last_returned_index = 0;
index = 0;
@@ -336,7 +361,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
if (entry == NULL)
{
/* Nothing found, even from a ncp call */
return 0;
goto finished;
}
if (index < c_size)
@@ -374,15 +399,18 @@ ncp_readdir(struct inode *inode, struct file *filp,
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
entry->f_pos, ino) < 0)
{
return 0;
goto finished;
}
filp->f_pos += 1;
index += 1;
entry += 1;
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
goto finished;
}
return 0;
finished:
ncp_unlock_dircache();
return result;
}
static int
@@ -407,7 +435,7 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
if (ncp_get_volume_info_with_number(server, i, &info) != 0)
{
return total_count;
return (total_count - fpos);
}
if (strlen(info.volume_name) > 0)
@@ -800,7 +828,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
memcpy(name, __name, len);
name[len] = 0;
lock_super(dir->i_sb);
result_info = ncp_find_dir_inode(dir, name);
if (result_info != 0)
@@ -814,6 +842,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
inode number */
*result = iget(dir->i_sb, ncp_info_ino(server, result_info));
unlock_super(dir->i_sb);
iput(dir);
if (*result == NULL)
@@ -828,7 +857,9 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
server. */
found_in_cache = 0;
ncp_lock_dircache();
if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
{
int first = c_last_returned_index;
@@ -851,6 +882,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
}
while (i != first);
}
ncp_unlock_dircache();
if (found_in_cache == 0)
{
@@ -873,6 +905,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
}
if (res != 0)
{
unlock_super(dir->i_sb);
iput(dir);
return -ENOENT;
}
@@ -883,10 +916,12 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
if (!(*result = ncp_iget(dir, &finfo)))
{
unlock_super(dir->i_sb);
iput(dir);
return -EACCES;
}
unlock_super(dir->i_sb);
iput(dir);
return 0;
}
@@ -916,6 +951,7 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
_name[len] = '\0';
str_upper(_name);
lock_super(dir->i_sb);
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
NCP_ISTRUCT(dir), _name,
OC_MODE_CREATE|OC_MODE_OPEN|
@@ -923,6 +959,7 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
0, AR_READ|AR_WRITE,
&finfo) != 0)
{
unlock_super(dir->i_sb);
iput(dir);
return -EACCES;
}
@@ -935,10 +972,12 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
if (!(*result = ncp_iget(dir, &finfo)) < 0)
{
ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
unlock_super(dir->i_sb);
iput(dir);
return -EINVAL;
}
unlock_super(dir->i_sb);
iput(dir);
return 0;
}
@@ -955,6 +994,7 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|| ( (len == 2)
&& (name[1] == '.'))))
{
iput(dir);
return -EEXIST;
}

View File

@@ -21,6 +21,7 @@
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/ncp_fs.h>
#include <linux/locks.h>
#include "ncplib_kernel.h"
#include <linux/malloc.h>
@@ -50,8 +51,10 @@ ncp_make_open(struct inode *i, int right)
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
lock_super(i->i_sb);
if (finfo->opened == 0)
{
finfo->access = -1;
/* tries max. rights */
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
NULL, NULL,
@@ -69,12 +72,10 @@ ncp_make_open(struct inode *i, int right)
{
finfo->access = O_RDONLY;
}
else
{
return -EACCES;
}
}
unlock_super(i->i_sb);
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|| (finfo->access == O_RDWR)))
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)

View File

@@ -94,7 +94,7 @@ ncp_read_inode(struct inode *inode)
inode->i_nlink = 1;
inode->i_uid = NCP_SERVER(inode)->m.uid;
inode->i_gid = NCP_SERVER(inode)->m.gid;
inode->i_blksize = 1024;
inode->i_blksize = 512;
inode->i_rdev = 0;
if ((inode->i_blksize != 0) && (inode->i_size != 0))
@@ -132,7 +132,9 @@ static void
ncp_put_inode(struct inode *inode)
{
struct nw_file_info *finfo = NCP_FINFO(inode);
struct super_block *sb = inode->i_sb;
lock_super(sb);
if (finfo->opened != 0)
{
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
@@ -155,6 +157,7 @@ ncp_put_inode(struct inode *inode)
}
clear_inode(inode);
unlock_super(sb);
}
struct super_block *

View File

@@ -222,6 +222,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
int timeout;
int retrans;
int major_timeout_seen;
int acknowledge_seen;
int n;
int addrlen;
unsigned long old_mask;
@@ -243,7 +244,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
return -EBADF;
}
init_timeout = server->m.time_out;
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
max_timeout = NCP_MAX_RPC_TIMEOUT;
acknowledge_seen = 0;
retrans = server->m.retry_count;
major_timeout_seen = 0;
old_mask = current->blocked;
@@ -296,11 +298,14 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
{
if (timeout > max_timeout)
{
/* JEJB/JSP 2/7/94
* This is useful to see if the system is
* hanging */
printk("NCP max timeout reached\n");
timeout = max_timeout;
/* JEJB/JSP 2/7/94
* This is useful to see if the system is
* hanging */
if (acknowledge_seen == 0)
{
printk("NCP max timeout reached\n");
}
timeout = max_timeout;
}
current->timeout = jiffies + timeout;
schedule();
@@ -373,6 +378,9 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
sock->ops->recvfrom(sock, (void *)&reply,
sizeof(reply), 1, 0,
NULL, &addrlen);
n = 0;
timeout = max_timeout;
acknowledge_seen = 1;
goto re_select;
}

18
kernel-2.0/README Normal file
View File

@@ -0,0 +1,18 @@
This directory contains the patch you have to apply to the Linux
kernel if you want to use the support for long file names using the
OS/2 namespace on the NetWare server. It did not make it into 2.0, but
patching your kernel is really no problem.
To apply this patch, please take a clean Linux kernel. This patch is
against Linux 2.0.7, but any later kernel version in the 2.0.x series
should also work fine. Please perform the following two steps:
cd /usr/src/linux
patch -p1 </path_to_ncpfs/kernel-2.0/lfn-2.0.7.diff
Please do not forget the -p1 flag for patch. Here I assumed that your
linux kernel resides in /usr/src/linux. After these two steps, you
should recompile your kernel the normal way. If anything goes wrong,
PLEASE first consult the file /usr/src/linux/README for more
information.

498
kernel-2.0/lfn-2.0.7.diff Normal file
View File

@@ -0,0 +1,498 @@
diff -urN 2.0.7/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- 2.0.7/fs/ncpfs/dir.c Mon Jul 8 17:19:03 1996
+++ linux/fs/ncpfs/dir.c Tue Jul 16 17:35:07 1996
@@ -92,6 +92,20 @@
}
}
+static inline int
+ncp_namespace(struct inode *i)
+{
+ struct ncp_server *server = NCP_SERVER(i);
+ struct nw_info_struct *info = NCP_ISTRUCT(i);
+ return server->name_space[info->volNumber];
+}
+
+static inline int
+ncp_preserve_case(struct inode *i)
+{
+ return (ncp_namespace(i) == NW_NS_OS2);
+}
+
static struct file_operations ncp_dir_operations = {
NULL, /* lseek - default */
ncp_dir_read, /* read - bad */
@@ -128,7 +142,7 @@
/* Here we encapsulate the inode number handling that depends upon the
* mount mode: When we mount a complete server, the memory address of
* the ncp_inode_info is used as the inode number. When only a single
- * volume is mounted, then the DosDirNum is used as the inode
+ * volume is mounted, then the dirEntNum is used as the inode
* number. As this is unique for the complete volume, this should
* enable the NFS exportability of a ncpfs-mounted volume.
*/
@@ -143,7 +157,7 @@
ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info)
{
return ncp_single_volume(server)
- ? info->finfo.i.DosDirNum : (ino_t)info;
+ ? info->finfo.i.dirEntNum : (ino_t)info;
}
static inline int
@@ -177,8 +191,6 @@
return NULL;
}
-
-
static int
ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
{
@@ -326,9 +338,12 @@
c_last_returned_index = 0;
index = 0;
- for (i = 0; i < c_size; i++)
+ if (!ncp_preserve_case(inode))
{
- str_lower(c_entry[i].i.entryName);
+ for (i = 0; i < c_size; i++)
+ {
+ str_lower(c_entry[i].i.entryName);
+ }
}
}
}
@@ -345,7 +360,7 @@
if (ncp_single_volume(server))
{
- ino = (ino_t)(entry->i.DosDirNum);
+ ino = (ino_t)(entry->i.dirEntNum);
}
else
{
@@ -652,7 +667,7 @@
root->finfo.opened = 0;
i->attributes = aDIR;
i->dataStreamSize = 1024;
- i->DosDirNum = 0;
+ i->dirEntNum = i->DosDirNum = 0;
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
@@ -729,7 +744,7 @@
do
{
- if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
+ if ( (result->dir->finfo.i.dirEntNum == dir_info->dirEntNum)
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
&& (strcmp(result->finfo.i.entryName, name) == 0)
/* The root dir is never looked up using this
@@ -757,6 +772,7 @@
struct ncp_server *server;
struct ncp_inode_info *result_info;
int found_in_cache;
+ int down_case = 0;
char name[len+1];
*result = NULL;
@@ -867,20 +883,26 @@
if (found_in_cache == 0)
{
int res;
- str_upper(name);
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
NCP_ISTRUCT(dir)->entryName, name);
if (ncp_is_server_root(dir))
{
+ str_upper(name);
+ down_case = 1;
res = ncp_lookup_volume(server, name, &(finfo.i));
}
else
{
+ if (!ncp_preserve_case(dir))
+ {
+ str_upper(name);
+ down_case = 1;
+ }
res = ncp_obtain_info(server,
NCP_ISTRUCT(dir)->volNumber,
- NCP_ISTRUCT(dir)->DosDirNum,
+ NCP_ISTRUCT(dir)->dirEntNum,
name, &(finfo.i));
}
if (res != 0)
@@ -892,7 +914,11 @@
}
finfo.opened = 0;
- str_lower(finfo.i.entryName);
+
+ if (down_case != 0)
+ {
+ str_lower(finfo.i.entryName);
+ }
if (!(*result = ncp_iget(dir, &finfo)))
{
@@ -929,7 +955,11 @@
strncpy(_name, name, len);
_name[len] = '\0';
- str_upper(_name);
+
+ if (!ncp_preserve_case(dir))
+ {
+ str_upper(_name);
+ }
lock_super(dir->i_sb);
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
@@ -946,7 +976,11 @@
ncp_invalid_dir_cache(dir);
- str_lower(finfo.i.entryName);
+ if (!ncp_preserve_case(dir))
+ {
+ str_lower(finfo.i.entryName);
+ }
+
finfo.access = O_RDWR;
if (!(*result = ncp_iget(dir, &finfo)) < 0)
@@ -980,7 +1014,11 @@
strncpy(_name, name, len);
_name[len] = '\0';
- str_upper(_name);
+
+ if (!ncp_preserve_case(dir))
+ {
+ str_upper(_name);
+ }
if (!dir || !S_ISDIR(dir->i_mode))
{
@@ -1038,7 +1076,11 @@
strncpy(_name, name, len);
_name[len] = '\0';
- str_upper(_name);
+
+ if (!ncp_preserve_case(dir))
+ {
+ str_upper(_name);
+ }
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
NCP_ISTRUCT(dir),
@@ -1081,7 +1123,11 @@
{
strncpy(_name, name, len);
_name[len] = '\0';
- str_upper(_name);
+
+ if (!ncp_preserve_case(dir))
+ {
+ str_upper(_name);
+ }
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
NCP_ISTRUCT(dir),
@@ -1136,11 +1182,19 @@
strncpy(_old_name, old_name, old_len);
_old_name[old_len] = '\0';
- str_upper(_old_name);
+
+ if (!ncp_preserve_case(old_dir))
+ {
+ str_upper(_old_name);
+ }
strncpy(_new_name, new_name, new_len);
_new_name[new_len] = '\0';
- str_upper(_new_name);
+
+ if (!ncp_preserve_case(new_dir))
+ {
+ str_upper(_new_name);
+ }
res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
NCP_ISTRUCT(old_dir), _old_name,
diff -urN 2.0.7/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
--- 2.0.7/fs/ncpfs/ncplib_kernel.c Thu Apr 18 08:40:28 1996
+++ linux/fs/ncpfs/ncplib_kernel.c Tue Jul 16 10:52:33 1996
@@ -190,25 +190,6 @@
}
int
-ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
-{
- int result;
-
- ncp_init_request_s(server, 5);
- ncp_add_pstring(server, name);
-
- if ((result = ncp_request(server, 22)) != 0)
- {
- ncp_unlock_server(server);
- return result;
- }
-
- *target = ncp_reply_byte(server, 0);
- ncp_unlock_server(server);
- return 0;
-}
-
-int
ncp_close_file(struct ncp_server *server, const char *file_id)
{
int result;
@@ -278,8 +259,8 @@
ncp_init_request(server);
ncp_add_byte(server, 6); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
- ncp_add_byte(server, 0); /* dos name space as dest */
+ ncp_add_byte(server, server->name_space[vol_num]);
+ ncp_add_byte(server, server->name_space[vol_num]);
ncp_add_word(server, 0xff); /* get all */
ncp_add_dword(server, RIM_ALL);
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
@@ -295,20 +276,57 @@
return 0;
}
+static inline int
+ncp_has_os2_namespace(struct ncp_server *server, __u8 volume)
+{
+ int result;
+ __u8 *namespace;
+ __u16 no_namespaces;
+
+ ncp_init_request(server);
+ ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
+ ncp_add_word(server, 0);
+ ncp_add_byte(server, volume);
+
+ if ((result = ncp_request(server, 87)) != 0)
+ {
+ ncp_unlock_server(server);
+ return 0;
+ }
+
+ no_namespaces = ncp_reply_word(server, 0);
+ namespace = ncp_reply_data(server, 2);
+
+ while (no_namespaces > 0)
+ {
+ DPRINTK("get_namespaces: found %d on %d\n", *namespace,volume);
+
+ if (*namespace == 4)
+ {
+ DPRINTK("get_namespaces: found OS2\n");
+ ncp_unlock_server(server);
+ return 1;
+ }
+ namespace += 1;
+ no_namespaces -= 1;
+ }
+ ncp_unlock_server(server);
+ return 0;
+}
+
int
ncp_lookup_volume(struct ncp_server *server,
char *volname,
struct nw_info_struct *target)
{
int result;
- __u8 vol_num;
- __u32 dir_base;
+ int volnum;
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
ncp_init_request(server);
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
- ncp_add_byte(server, 0); /* DOS name space */
+ ncp_add_byte(server, 0); /* DOS namespace */
ncp_add_byte(server, 0); /* reserved */
ncp_add_byte(server, 0); /* reserved */
ncp_add_byte(server, 0); /* reserved */
@@ -325,20 +343,19 @@
return result;
}
- dir_base = ncp_reply_dword(server, 4);
- vol_num = ncp_reply_byte(server, 8);
+ memset(target, 0, sizeof(*target));
+ target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
+ target->volNumber = volnum = ncp_reply_byte(server, 8);
ncp_unlock_server(server);
- if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
- target)) != 0)
- {
- return result;
- }
+ server->name_space[volnum] = ncp_has_os2_namespace(server,volnum)?4:0;
- DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
+ DPRINTK("lookup_vol: namespace[%d] = %d\n",
+ volnum, server->name_space[volnum]);
target->nameLen = strlen(volname);
strcpy(target->entryName, volname);
+ target->attributes = aDIR;
return 0;
}
@@ -352,14 +369,14 @@
ncp_init_request(server);
ncp_add_byte(server, 7); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[file->volNumber]);
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_dword(server, info_mask);
ncp_add_mem(server, info, sizeof(*info));
ncp_add_handle_path(server, file->volNumber,
- file->DosDirNum, 1, NULL);
+ file->dirEntNum, 1, NULL);
result = ncp_request(server, 87);
ncp_unlock_server(server);
@@ -374,11 +391,11 @@
ncp_init_request(server);
ncp_add_byte(server, 8); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[dir->volNumber]);
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_handle_path(server, dir->volNumber,
- dir->DosDirNum, 1, name);
+ dir->dirEntNum, 1, name);
result = ncp_request(server, 87);
ncp_unlock_server(server);
@@ -406,15 +423,16 @@
{
int result;
__u16 search_attribs = 0x0006;
+ __u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
if ((create_attributes & aDIR) != 0)
{
- search_attribs |= 0x8000;
- }
+ search_attribs |= 0x8000;
+}
ncp_init_request(server);
ncp_add_byte(server, 1); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[volume]);
ncp_add_byte(server, open_create_mode);
ncp_add_word(server, search_attribs);
ncp_add_dword(server, RIM_ALL);
@@ -425,13 +443,11 @@
if (dir != NULL)
{
- ncp_add_handle_path(server, dir->volNumber,
- dir->DosDirNum, 1, name);
+ ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
}
else
{
- ncp_add_handle_path(server,
- target->i.volNumber, target->i.DosDirNum,
+ ncp_add_handle_path(server, volume, target->i.dirEntNum,
1, NULL);
}
@@ -467,9 +483,9 @@
ncp_init_request(server);
ncp_add_byte(server, 2); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[dir->volNumber]);
ncp_add_byte(server, 0); /* reserved */
- ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
+ ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
if ((result = ncp_request(server, 87)) != 0)
{
@@ -493,7 +509,7 @@
ncp_init_request(server);
ncp_add_byte(server, 3); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[seq->volNumber]);
ncp_add_byte(server, 0); /* data stream (???) */
ncp_add_word(server, 0xffff); /* Search attribs */
ncp_add_dword(server, RIM_ALL); /* return info mask */
@@ -528,19 +544,19 @@
ncp_init_request(server);
ncp_add_byte(server, 4); /* subfunction */
- ncp_add_byte(server, 0); /* dos name space */
+ ncp_add_byte(server, server->name_space[old_dir->volNumber]);
ncp_add_byte(server, 1); /* rename flag */
ncp_add_word(server, 0x8006); /* search attributes */
/* source Handle Path */
ncp_add_byte(server, old_dir->volNumber);
- ncp_add_dword(server, old_dir->DosDirNum);
+ ncp_add_dword(server, old_dir->dirEntNum);
ncp_add_byte(server, 1);
ncp_add_byte(server, 1); /* 1 source component */
/* dest Handle Path */
ncp_add_byte(server, new_dir->volNumber);
- ncp_add_dword(server, new_dir->DosDirNum);
+ ncp_add_dword(server, new_dir->dirEntNum);
ncp_add_byte(server, 1);
ncp_add_byte(server, 1); /* 1 destination component */
diff -urN 2.0.7/include/linux/ncp.h linux/include/linux/ncp.h
--- 2.0.7/include/linux/ncp.h Thu Apr 18 08:40:36 1996
+++ linux/include/linux/ncp.h Tue Jul 16 17:27:45 1996
@@ -116,6 +116,12 @@
__u16 update_time;
};
+/* Defines for Name Spaces */
+#define NW_NS_DOS 0
+#define NW_NS_MAC 1
+#define NW_NS_NFS 2
+#define NW_NS_FTAM 3
+#define NW_NS_OS2 4
/* Defines for ReturnInformationMask */
#define RIM_NAME (0x0001L)
diff -urN 2.0.7/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
--- 2.0.7/include/linux/ncp_fs_sb.h Thu Apr 18 08:40:36 1996
+++ linux/include/linux/ncp_fs_sb.h Tue Jul 16 17:35:17 1996
@@ -21,6 +21,8 @@
interest for us later, so we store
it completely. */
+ __u8 name_space[NCP_NUMBER_OF_VOLUMES];
+
struct file *ncp_filp; /* File pointer to ncp socket */
struct file *wdog_filp; /* File pointer to wdog socket */
struct file *msg_filp; /* File pointer to message socket */

View File

@@ -1,7 +1,10 @@
MAN1= slist nprint pqlist nsend pserver
MAN1= slist nprint pqlist nsend pserver ncopy npasswd
MAN1 += nwbols nwboprops nwbpvalues
MAN5= nwclient
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \
ipx_route nwmsg
MAN8 += nwbocreate nwborm nwbpadd nwbpcreate nwbprm
MAN8 += nwgrant nwrevoke

96
man/ncopy.1 Normal file
View File

@@ -0,0 +1,96 @@
.\"
.\" Man page for the ncopy program
.\"
.TH NCOPY 1 17/03/1996 ncopy ncopy
.SH NAME
ncopy \- NetWare file copy
.SH SYNOPSIS
.B ncopy -V
.B ncopy
[
.B -vn
]
[
.B -s
.I amount
]
.B file destinationfile|directory
.B ncopy
[
.B -vn
]
[
.B -s
.I amount
]
.B file1
[
.B file2 ...
]
.B directory
.SH DESCRIPTION
With
.B ncopy
you can copy files to different locations on a single NetWare file
server without generating excess network traffic. The program uses
a NetWare function to do the copy rather than transferring the file
across the network for both the read and write.
If the last argument is a directory,
.B ncopy
will copy the source file(s) into the directory. If only two files
are given and the last argument is not a directory, it will copy the
source file to the destination file.
If the source and destination files are not on the same NetWare server
(or are not on NetWare servers at all),
.B ncopy
will do a normal file copy.
.SH OPTIONS
.B -V
.RS 3
Show version number and exit
.RE
.B -v
.RS 3
Verbose copy. Will show current file and percentage completion.
.RE
.B -n
.RS 3
Nice NetWare copy. Will sleep for a second between copying blocks on
the NetWare server. Gives other people a chance to do some work on
the NetWare server when you are copying large files. This has no
effect if you are not copying on a NetWare server.
.RE
.B -s
.I amount
.RS 3
Nice time slice factor. Used in conjunction with the
.B -n
option, this specifies the number of 100K blocks to copy before sleeping.
Default is 10. (1 Megabyte)
.RE
.SH BUGS
.B ncopy
cannot recurse into directories.
Does not work on NetWare volumes mounted with the
.I -V
option to
.B ncpmount.
.SH "SEE ALSO"
.B ncpmount(8), ncpumount(8)
.SH CREDITS
ncopy was written by Brian G. Reid (breid@tim.com) and
Tom C. Henderson (thenderson@tim.com).
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
and ncplib which made ncopy possible.

55
man/npasswd.1 Normal file
View File

@@ -0,0 +1,55 @@
.TH NPASSWD 1 06/22/1996 npasswd npasswd
.SH NAME
npasswd \- Change a user's password
.SH SYNOPSIS
.B npasswd
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
]
.B -t
.I object type
]
.SH DESCRIPTION
With
.B npasswd,
you can change your password on a NetWare server.
.B npasswd
asks for the old password and twice for the new password. Then it
changes the password on the server.
.SH OPTIONS
.B -h
.RS 3
With -h npasswd prints a little help text.
.RE
.B -S
.I server
.RS 3
is the name of the server you want to use.
.RE
.B -U
.I user name
.RS 3
is the name of the bindery object whose password is to be changed.
.RE
.B -t
.I object type
.RS 3
is the bindery object type of the object whose password is to be
changed.
.RE
.SH CREDITS
npasswd would not have been possible without the work of Guntram
Blom. Look at nwcrypt.c for his work.

133
man/nwbocreate.8 Normal file
View File

@@ -0,0 +1,133 @@
.TH NWBOCREATE 8 7/9/1996 nwbocreate nwbocreate
.SH NAME
nwbocreate \- Create a NetWare Bindery Object
.SH SYNOPSIS
.B nwbocreate
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -r
.I read-flag
] [
.B -w
.I write-flag
]
.SH DESCRIPTION
.B nwbocreate
creates the specified NetWare Bindery Object.
.B nwbocreate
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbocreate
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be created.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -r
.I read-flag
.B -w
.I write-flag
.RS 3
Read security and write security may each have one of the following values:
ANYONE: Anyone may access the object
LOGGED: Anyone who is logged in may access the
object
OBJECT: Anyone who is logged in as the object or
SUPERVISOR equivalent may access the
object
SUPERVISOR: Anyone who is logged in as SUPERVISOR
equivalent may access the object
NETWARE: Only the Bindery may access the object
.RE
.SH AUTHORS
nwbocreate was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

117
man/nwbols.1 Normal file
View File

@@ -0,0 +1,117 @@
.TH NWBOLS 1 7/9/1996 nwbols nwbols
.SH NAME
nwbols \- List NetWare Bindery Objects
.SH SYNOPSIS
.B nwbols
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -t
.I type
] [
.B -v
] [
.B pattern
]
.SH DESCRIPTION
.B nwbols
lists the specified NetWare Bindery Objects visible for the user.
.B nwbols
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbols
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -t
.I type
.RS 3
You can restrict the objects listed by specifying the type of the
objects to be listed.
.I type
must be given as a decimal number.
.RE
.B pattern
.RS 3
Specifying a pattern is another way to restrict the objects
listed. Please note that this pattern is evaluated by the NetWare
server. grep would be a better candidate for complex patterns.
.RE
.B -v
.RS 3
By default, the object's name, its ID and its type are listed by
.B nwbols.
In the verbose mode, activated by
.B -v,
the object flags, its security byte and the properties flag is also
listed.
.RE
.SH AUTHORS
nwbols was written by Volker Lendecke. See the Changes file of ncpfs
for other contributors.

118
man/nwboprops.1 Normal file
View File

@@ -0,0 +1,118 @@
.TH NWBOPROPS 1 7/9/1996 nwboprops nwboprops
.SH NAME
nwboprops \- List properies of a NetWare Bindery Object
.SH SYNOPSIS
.B nwboprops
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -v
]
.SH DESCRIPTION
.B nwboprops
lists all the properties of the specified NetWare Bindery Objects.
.B nwboprops
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwboprops
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be inspected.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -v
.RS 3
By default, only the property name is listed. In verbose mode,
activated by
.B -v,
the property flag, the property security byte and the value flag are
also listed.
.RE
.SH AUTHORS
nwboprops was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

106
man/nwborm.8 Normal file
View File

@@ -0,0 +1,106 @@
.TH NWBORM 8 7/9/1996 nwborm nwborm
.SH NAME
nwborm \- Remove a NetWare Bindery Object
.SH SYNOPSIS
.B nwborm
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
]
.SH DESCRIPTION
.B nwborm
removes the specified NetWare Bindery Objects.
.B nwborm
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwborm
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be deleted.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.SH AUTHORS
nwborm was written by Volker Lendecke with the corresponding Caldera
utility in mind. See the Changes file of ncpfs for other contributors.

145
man/nwbpadd.8 Normal file
View File

@@ -0,0 +1,145 @@
.TH NWBPADD 8 7/9/1996 nwbpadd nwbpadd
.SH NAME
nwbpadd \- Set the value of a NetWare Bindery Property
.SH SYNOPSIS
.B nwbpadd
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
]
.B value
.SH DESCRIPTION
.B nwbpadd
sets the value of a ITEM type property, and adds bindery objects to a
SET type property.
.B nwbpadd
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpadd
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be set.
.RE
.B value
.RS 3
If property is of type SET, value is an object id in hexadecimal
notation. Otherwise, value is either a string value to be written, or
a count of bytes to be written. The latter is assumed if more than one
value argument is given. The count is decimal, and the following
arguments are interpreted as bytes in hexadecimal notation.
Examples:
All these examples assume the existence of the file
$HOME/.nwclient. Otherwise, the server and user would have to be
specified.
nwbpadd -o linus -t 1 -p groups_i\\'m_in os_hackers
In this example, user linus is added to the group os_hackers. Please
note that the ' has to be quoted.
nwbpadd -o linus -t 1 -p identification "Linus Torvalds"
User linus is given his real name :-).
nwbpadd -o linus -t 1 -p revision -v 04 00 00 01 0b
A new 4-byte binary value 0x0000010b (hi-lo order, no byte-swapping) is added
to the "REVISION" property of the user "linus".
.SH AUTHORS
nwbpadd was written by Volker Lendecke with the corresponding Caldera
utility in mind. See the Changes file of ncpfs for other contributors.

154
man/nwbpcreate.8 Normal file
View File

@@ -0,0 +1,154 @@
.TH NWBPCREATE 8 7/9/1996 nwbpcreate nwbpcreate
.SH NAME
nwbpcreate \- Create a NetWare Bindery Propery
.SH SYNOPSIS
.B nwbpcreate
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
] [
.B -s
] [
.B -r
.I read-flag
] [
.B -w
.I write-flag
]
.SH DESCRIPTION
.B nwbpcreate
creates the specified NetWare Bindery Propery.
.B nwbpcreate
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpcreate
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be created.
.RE
.B -s
.RS 3
By default,
.B nwbpcreate
creates properties of type ITEM. If you want to create a property of
type SET, such as groups_i\\'m_in, you must use the
.B -s
option.
.RE
.B -r
.I read-flag
.B -w
.I write-flag
.RS 3
Read security and write security may each have one of the following values:
ANYONE: Anyone may access the property
LOGGED: Anyone who is logged in may access the
property
OBJECT: Anyone who is logged in as the object or
SUPERVISOR equivalent may access the
property
SUPERVISOR: Anyone who is logged in as SUPERVISOR
equivalent may access the property
NETWARE: Only the Bindery may access the property
.RE
.SH AUTHORS
nwbpcreate was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

116
man/nwbprm.8 Normal file
View File

@@ -0,0 +1,116 @@
.TH NWBPRM 8 7/9/1996 nwbprm nwbprm
.SH NAME
nwbprm \- Remove a NetWare Bindery Propery
.SH SYNOPSIS
.B nwbprm
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
]
.SH DESCRIPTION
.B nwbprm
removes the specified NetWare Bindery Propery.
.B nwbprm
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbprm
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be removed.
.RE
.SH AUTHORS
nwbprm was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

128
man/nwbpvalues.1 Normal file
View File

@@ -0,0 +1,128 @@
.TH NWBPVALUES 8 7/9/1996 nwbpvalues nwbpvalues
.SH NAME
nwbpvalues \- Print a NetWare Bindery Propery's contents
.SH SYNOPSIS
.B nwbpvalues
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
] [
.B -v
]
.SH DESCRIPTION
.B nwbpvalues
prints the contents of a SET property.
.B nwbpvalues
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpvalues
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be looked up.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be printed.
.RE
.B -v
.RS 3
By default, the object's name, its ID and its type are listed by
.B nwbols.
In the verbose mode, activated by
.B -v,
the object flags, its security byte and the properties flag is also
listed.
.RE
.SH AUTHORS
nwbpvalues was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

148
man/nwgrant.8 Normal file
View File

@@ -0,0 +1,148 @@
.TH NWGRANT 8 7/9/1996 nwgrant nwgrant
.SH NAME
nwgrant \- Add Trustee Rights to a directory
.SH SYNOPSIS
.B nwgrant
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -r
.I rights
]
.B directory
.SH DESCRIPTION
.B nwgrant
adds the specified bindery object with the corresponding trustee
rights to the directory.
.B nwgrant
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwgrant
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be added as trustee.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -r
.I rights
.RS 3
You must tell
.B nwgrant
which rights it should grant to the bindery object.
The new rights for the object is specified by
.I rights,
which is the sum of the following hexadecimal individual rights values:
00 = no access
01 = read access
02 = write access
04 = open access
08 = create access
10 = delete access
20 = ownership access
40 = search access
80 = modify access
for a possible total of "ff" for all rights.
.RE
.B directory
.RS 3
You must specify the directory to which to add the object as
trustee. This has to be done in fully qualified NetWare notation.
Example:
nwgrant -o linus -t 1 -r ff 'data:home\\linus'
With this example, user linus is given all rights to his home
directory on the data volume. This example assumes the existence of
the file $HOME/.nwclient.
.SH AUTHORS
nwgrant was written by Volker Lendecke with the corresponding NetWare
utility in mind. See the Changes file of ncpfs for other contributors.

124
man/nwrevoke.8 Normal file
View File

@@ -0,0 +1,124 @@
.TH NWREVOKE 8 7/9/1996 nwrevoke nwrevoke
.SH NAME
nwrevoke \- Revoke a Trustee Right from a directory
.SH SYNOPSIS
.B nwrevoke
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -r
.I rights
]
.B directory
.SH DESCRIPTION
.B nwrevoke
revokes the specified bindery object with the corresponding trustee
rights from the directory.
.B nwrevoke
looks up the file
.I $HOME/.nwclient
to find a file server, a user name and possibly a password. See
nwclient(5) for more information. Please note that the access
permissions of $HOME/.nwclient MUST be 600 for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print out a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwrevoke
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -o
.I object name
.RS 3
The name of the object to be added as trustee.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B directory
.RS 3
You must specify the directory from which to remove the object as
trustee. This has to be done in fully qualified NetWare notation.
Example:
nwrevoke -o linus -t 1 'src:bsd_src'
With this example, user linus is removed as trustee from the bsd_src
directory on the src volume.
.SH AUTHORS
nwrevoke was written by Volker Lendecke with the corresponding NetWare
utility in mind. See the Changes file of ncpfs for other contributors.

View File

@@ -1,19 +0,0 @@
Begin3
Title: ncpfs
Version: 0.19
Entered-date: 22. March 1996
Description: With ncpfs you can mount volumes of your netware
server under Linux. You can also print to netware
print queues and spool netware print queues to the
Linux printing system. 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 ncp novell netware printing
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
Primary-site: linux01.gwdg.de:/pub/ncpfs
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
~103k ncpfs-0.19.tgz
~ 1k ncpfs-0.19.lsm
Copying-policy: GPL
End

19
ncpfs-2.0.2.lsm Normal file
View File

@@ -0,0 +1,19 @@
Begin3
Title: ncpfs
Version: 2.0.2
Entered-date: 18. July 1996
Description: With ncpfs you can mount volumes of your netware
server under Linux. You can also print to netware
print queues and spool netware print queues to the
Linux printing system. You need kernel 1.2.x or
1.3.71 and above. ncpfs does NOT work with any 1.3.x
kernel below 1.3.71.
Keywords: filesystem ncp novell netware printing
Author: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke)
Maintained-by: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke)
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/ncpfs
~124k ncpfs-2.0.2.tgz
~ 1k ncpfs-2.0.2.lsm
Copying-policy: GPL
End

View File

@@ -2,17 +2,23 @@
# Makefile for the linux ncp-filesystem routines.
#
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy npasswd
USERUTILS += nwbols nwbocreate nwborm nwboprops
USERUTILS += nwbpcreate nwbprm nwbpvalues nwbpadd
USERUTILS += nwgrant nwrevoke
UIDUTILS = ncpmount ncpumount
SBINUTILS = nwmsg
UTIL_EXECS = $(USERUTILS) $(UIDUTILS) $(SBINUTILS)
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
#CFLAGS = -Wall $(INCLUDES) $(KERNELD) -g -DNCPFS_VERSION=\"$(VERSION)\"
#CFLAGS = -Wall $(INCLUDES) $(KERNELD) -g -DNCPFS_VERSION=\"$(VERSION)\"
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\"
CC = gcc
default:
make -C ..
all: $(UTILS) ncptest
install: all

849
util/ncopy.c Normal file
View File

@@ -0,0 +1,849 @@
/****************************************************************************
* ncopy.c
*
* Copy file on a Netware server without Network Traffic
*
* Copyright (C) 1996 by Brian Reid and Tom Henderson.
*
* Send bug reports for ncopy to "breid@tim.com"
*
* Still to do: support recursive copy with two arguments
* Both must be directories. (similar to rcp -r)
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <ctype.h>
#include <mntent.h>
#include <fcntl.h>
#include <signal.h>
#include "ncplib.h"
struct NCPMountRec
{
char *mountDir;
char *server;
struct ncp_conn *conn;
};
/****************************************************************************
* Globals:
*
*/
const char *VersionStr = "0.1";
char * ProgramName;
struct NCPMountRec *NcpMountTable = NULL;
int ncpCount = 0;
/* (initialized) command options */
int optVersion=0; /* -V TRUE if just want version */
int optVerbose=0; /* -v TRUE if want verbose output */
int optNice=0; /* -n TRUE if we are cooperative (nice) */
int optNiceFactorSel=0; /* -s TRUE if we selected a nice factor */
int optNiceFactor=10; /* -s arg, number of 100K blocks to copy
before sleeping for a second */
__u32 CopyBlockSize = 100000; /* Size of the default block copy size */
unsigned int NiceSleepTime=1; /* Number of seconds to sleep in Nice Mode */
int BlocksCopied=0; /* Number of blocks copied */
int MaxNcopyRetries=25; /* Maximum number of times to retry a failed
copy before giving up */
/* Globals needed for signal handlers */
int OutputOpen=0; /* True if the ncp output file is open */
struct ncp_conn *CurrentConn = NULL; /* Connection of output file */
struct ncp_file_info *CurrentFile = NULL; /* File info of output file */
/* Signal control structures */
static struct sigaction sHangupSig;
static struct sigaction sInterruptSig;
static struct sigaction sQuitSig;
static struct sigaction sTermSig;
/****************************************************************************
*
*/
static void usage()
{
fprintf(stderr,"usage: %s [-V]\n", ProgramName);
fprintf(stderr," %s [-vn] [-s amt] sourcefile destinationfile|directory\n", ProgramName);
fprintf(stderr," %s [-vn] [-s amt] sourcefile [...] directory\n", ProgramName);
}
/****************************************************************************
* Return pointer to last component of the path.
* Returned string may have one or more "/" left on the end.
* ("/" returns pointer to "/", null returns pointer to null)
* Return pointer to original string if no "/" in string. (except at end)
*/
static const char *myBaseName(const char *path)
{
const char *p;
for(p = &path[strlen(path)]; p != path; p--) { /* skip ENDING "/" chars */
if(*p && *p != '/') break;
}
if(p==path) return p;
for( ; p != path || *p == '/'; p--) {
if(*p == '/') return ++p;
}
return p;
}
/****************************************************************************
*
*/
static const char *notDir(const char *path)
{
struct stat buf;
static const char *notDirectory="not a directory";
if(stat(path, &buf)) return strerror(errno); /* no permission? not exist? */
if(!S_ISDIR(buf.st_mode)) return notDirectory; /* not a directory */
return (char *) 0; /* OK */
}
/****************************************************************************
*
*/
static int handleOptions(const int argc, char * const argv[])
{
int opt;
while ((opt = getopt(argc, argv, "vVns:")) != EOF)
{
switch (opt) {
case 'V': /* Version */
optVersion=1;
break;
case 'v': /* Verbose output */
optVerbose=1;
break;
case 'n': /* Nice, cooperative copy */
optNice=1;
break;
case 's': /* Nice Factor */
optNiceFactorSel=1;
optNiceFactor=atoi(optarg);
if (optNiceFactor < 1) {
fprintf(stderr,"%s: -s option requires positive numeric argument > 0\n",
ProgramName);
return 1;
}
break;
default: /* invalid options or options without required arguments */
return 1;
}
continue;
}
return 0;
}
/****************************************************************************
* TODO: if recursive flag last MUST be a directory, even if only 2 args.
*/
static int validateFileArgs(const int argc, char * const argv[])
{
const char *p;
if (argc == 0) {
fprintf(stderr,"%s: No arguments specified.\n", ProgramName);
return 1;
}
if(argc == 1) {
fprintf(stderr,"%s: No destination specified.\n", ProgramName);
return 1;
}
if((argc > 2) && (p=notDir(argv[argc-1]))) { /* last arg MUST be dir */
fprintf(stderr,"%s: %s: %s\n", ProgramName, argv[argc-1], p);
return 1;
}
return 0;
}
/****************************************************************************
* Duplicate a string.
*/
char *duplicateStr(const char *InStr)
{
char *dup;
if (!InStr) return NULL;
dup = (char*)malloc(strlen(InStr)+1);
if (dup)
strcpy(dup,InStr);
return dup;
}
/****************************************************************************
* load a table of ncpfs mount points.
*/
int loadMountTable()
{
FILE *mountedFile;
struct mntent *mountEntry = NULL;
ncpCount = 0;
if ( (mountedFile = fopen(MOUNTED,"r")) == NULL) {
fprintf(stderr,"ncopy: cannot open %s, %s\n",MOUNTED,strerror(errno));
return 1;
}
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
if (!strcmp(mountEntry->mnt_type,"ncpfs"))
ncpCount++;
}
if (ncpCount) {
NcpMountTable = (struct NCPMountRec*)
malloc(ncpCount * sizeof(struct NCPMountRec));
if (!NcpMountTable) {
fprintf(stderr,"Out of memory\n");
fclose(mountedFile);
return 1;
}
fseek(mountedFile,0,SEEK_SET);
ncpCount = 0;
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
if (!strcmp(mountEntry->mnt_type,"ncpfs")) {
NcpMountTable[ncpCount].mountDir = duplicateStr(mountEntry->mnt_dir);
NcpMountTable[ncpCount].server =
duplicateStr(mountEntry->mnt_fsname);
NcpMountTable[ncpCount].conn = NULL;
ncpCount++;
}
}
}
fclose(mountedFile);
return 0;
}
/****************************************************************************
* Releases the table of ncpfs mount points.
*/
void releaseMountTable()
{
int loop;
if (!ncpCount) return;
for (loop = ncpCount; loop; loop--,ncpCount--) {
if (NcpMountTable[loop-1].conn) {
ncp_close(NcpMountTable[loop-1].conn);
NcpMountTable[loop-1].conn = NULL;
}
free(NcpMountTable[loop-1].server);
free(NcpMountTable[loop-1].mountDir);
}
free(NcpMountTable);
}
/****************************************************************************
* Finds the index into the mount point table that enables ncp copy for
* the file.
* Returns -1 if the files do not reference the same server.
*/
int ncpIndex(const char *InputFile, const char *OutputFile)
{
int loop;
char *mountDir;
if (!ncpCount) return -1;
for (loop = 0; loop < ncpCount; loop++) {
mountDir = NcpMountTable[loop].mountDir;
if (!strncmp(mountDir,InputFile,strlen(mountDir)) &&
!strncmp(mountDir,OutputFile,strlen(mountDir))) return loop;
}
return -1;
}
/****************************************************************************
* Does a regular buffered file copy.
* This is used if we cannot use the Netware file copy.
*/
int normalFileCopy(const char *InputFile, const char *OutputFile,
char *Buffer,int BufferSize,
const char *paramInputFile,
const char *paramOutputFile)
{
int fdIn, fdOut;
long fileSize,totalSize;
struct stat statBuf;
fdIn = open(InputFile,O_RDONLY);
if (fdIn == -1) {
fprintf(stderr,"%s: Cannot open %s, %s\n",ProgramName,paramInputFile,
strerror(errno));
return 1;
}
if (fstat(fdIn,&statBuf)) {
fprintf(stderr,"%s: Cannot stat %s, %s\n",ProgramName,paramInputFile,
strerror(errno));
close(fdIn);
return 1;
}
if(S_ISDIR(statBuf.st_mode)) {
close(fdIn);
fprintf(stderr,"%s: %s: omitting directory\n",ProgramName,paramInputFile);
return 0; /* At this point, don't consider this a fatal error */
}
fdOut = open(OutputFile,O_CREAT | O_TRUNC | O_WRONLY,statBuf.st_mode);
if (fdOut == -1) {
fprintf(stderr,"%s: Cannot create %s, %s\n",ProgramName,paramOutputFile,
strerror(errno));
close(fdIn);
return 1;
}
fileSize = lseek(fdIn,0,SEEK_END);
if (fileSize < 0) {
fprintf(stderr,"%s: lseek error on %s, %s\n",ProgramName,paramInputFile,
strerror(errno));
close(fdOut);
close(fdIn);
return 1;
}
lseek(fdIn,0,SEEK_SET);
if (optVerbose) {
printf("Normal copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
fflush(stdout);
}
totalSize = fileSize;
while (fileSize) {
int currentMove;
int writeAmt;
currentMove = (fileSize > BufferSize) ? BufferSize : fileSize;
if (read(fdIn,Buffer,currentMove) != currentMove) {
fprintf(stderr,"%s: Error reading %s, %s\n",ProgramName,paramInputFile,
strerror(errno));
close(fdIn);
close(fdOut);
return 1;
}
writeAmt = write(fdOut,Buffer,currentMove);
if (writeAmt < 0) {
fprintf(stderr,"%s: Error writing %s, %s\n",ProgramName,paramOutputFile,
strerror(errno));
close(fdIn);
close(fdOut);
return 1;
} else if (writeAmt == 0) {
fprintf(stderr,"%s: Out of space on destination device writing %s\n",
ProgramName,OutputFile);
close(fdIn);
close(fdOut);
return 1;
}
fileSize -= currentMove;
if (optVerbose) {
printf("\rNormal copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,(100 - (fileSize * 100/totalSize)));
fflush(stdout);
}
}
close(fdOut);
close(fdIn);
if (optVerbose)
printf("\n");
return 0;
}
/****************************************************************************
* Converts a string to upper case.
* Netware file names need to be all upper case.
*/
char *upString(char *str)
{
char *alias = str;
while (*alias) {
*alias = toupper(*alias);
++alias;
}
return str;
}
/****************************************************************************
* Locates the first occurrance of a single character in the input string.
* returns -1 if the character is not found.
*/
int stringPosition(const char *str,char token)
{
const char *alias = str;
while (*alias) {
if (*alias == token) return alias - str;
alias++;
}
return -1;
}
/****************************************************************************
* Walks up the directory path building info structures along the way
* in order to get a dir_handle.
* This will mangle the input "FileString", leaving just the file name
* component in it when it is finished.
*/
int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 *NewDirHandle)
{
struct nw_info_struct info1,info2;
int currentLevel = 0;
int k;
struct nw_info_struct *parentInfo = NULL;
struct nw_info_struct *currentInfo = NULL;
while ( (k = stringPosition(FileString,'/')) >= 0) {
FileString[k] = 0;
if (!currentLevel) {
parentInfo = NULL;
currentInfo = &info1;
} else if (currentLevel % 2) {
parentInfo = &info1;
currentInfo = &info2;
} else {
parentInfo = &info2;
currentInfo = &info1;
}
if (ncp_do_lookup(conn, parentInfo, FileString,
currentInfo) != 0) {
fprintf(stderr,"%s: Ncp lookup failed on directory %s--%s\n",
ProgramName,FileString,strerror(errno));
return 1;
}
++currentLevel;
memmove(FileString,FileString+k+1,strlen(FileString+k+1)+1);
}
if (ncp_alloc_short_dir_handle(conn, currentInfo, NCP_ALLOC_TEMPORARY,
NewDirHandle) != 0) {
fprintf(stderr,"%s: Ncp alloc dir handle failed--%s\n",
ProgramName,strerror(errno));
return 1;
}
return 0;
}
/****************************************************************************
* Interfaces with the ncplib to do the netware copy of the file.
*/
int netwareCopyFile(int ncpMountIndex, const char *sourcefile,
const char *destfile,
const char *paramInputFile,
const char *paramOutputFile)
{
__u8 source_dir_handle;
__u8 dest_dir_handle;
struct ncp_file_info source_file;
struct ncp_file_info dest_file;
__u32 amountCopied;
__u32 amtLeft;
__u32 totalSize;
__u32 sourceOff;
__u32 thisMove;
int stroffset;
int retValue;
char *sourceDup;
char *destDup;
struct ncp_conn *sourceconn;
int retryCount;
long err = 0;
/* Establish a connection to a Netware mount point if
one is not already established. */
if (!NcpMountTable[ncpMountIndex].conn) {
NcpMountTable[ncpMountIndex].conn =
ncp_open_mount(NcpMountTable[ncpMountIndex].mountDir,&err);
if (err) {
com_err(ProgramName,err,"opening ncp connection on mount point %s",
NcpMountTable[ncpMountIndex].mountDir);
return 2;
}
}
sourceconn = NcpMountTable[ncpMountIndex].conn;
/* Duplicate and upper case the file names so we do not trample
on the input strings */
stroffset = strlen(NcpMountTable[ncpMountIndex].mountDir) + 1;
sourceDup = duplicateStr(sourcefile+stroffset);
destDup = duplicateStr(destfile+stroffset);
if (!sourceDup || !destDup) {
fprintf(stderr,"%s: Malloc failed duplicating file names\n",
ProgramName);
return 2;
}
upString(sourceDup);
upString(destDup);
/* Get Handles to the input and output directories */
if (getDirHandle(sourceconn,sourceDup,&source_dir_handle) ||
getDirHandle(sourceconn,destDup,&dest_dir_handle)) {
free(sourceDup);
free(destDup);
return 1;
}
/* Open the input and output files. */
if (ncp_open_file(sourceconn, source_dir_handle, sourceDup,0,AR_READ,
&source_file) != 0) {
fprintf(stderr,"%s: Cannot open %s--%s\n",
ProgramName,paramInputFile,strerror(errno));
free(sourceDup);
free(destDup);
return 1;
}
if (ncp_create_file(sourceconn, dest_dir_handle, destDup,
source_file.file_attributes, &dest_file) != 0) {
fprintf(stderr,"%s: Cannot create %s--%s\n",ProgramName, paramOutputFile,
strerror(errno));
ncp_close_file(sourceconn,source_file.file_id);
free(sourceDup);
free(destDup);
return 1;
}
/* Set globals in case a signal happens while copying */
CurrentConn = sourceconn;
CurrentFile = &dest_file;
OutputOpen = 1;
free(sourceDup);
free(destDup);
retValue = 0;
if (optVerbose) {
printf("NetWare copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
fflush(stdout);
}
/* The main copy loop. */
amtLeft = totalSize = source_file.file_length;
sourceOff = 0;
retryCount = 0;
while (amtLeft && retryCount < MaxNcopyRetries) {
int ncopyRetValue;
if (amtLeft > CopyBlockSize)
thisMove = CopyBlockSize;
else
thisMove = amtLeft;
/* If we are being nice and we've copied enough blocks, go to sleep */
if (optNice) {
if (BlocksCopied == optNiceFactor) {
sleep(NiceSleepTime);
BlocksCopied=0;
} else
++BlocksCopied;
}
ncopyRetValue = ncp_copy_file(sourceconn, source_file.file_id,
dest_file.file_id, sourceOff,sourceOff,
thisMove,&amountCopied);
if (ncopyRetValue != 0) {
/* In my testing this only happens when you run out of space
on the server.
Netware seems to wait a bit before reporting space recently
free'd. I will just wait a bit before bombin */
sleep(1); /* Sleep for a second and try again */
retryCount++;
amountCopied = thisMove = 0;
}
if (amountCopied != thisMove) {
fprintf(stderr,"%s: Warning, amountCopied (%u) != thisMove (%u)\n",
ProgramName,(unsigned int)amountCopied,(unsigned int)thisMove);
}
#ifdef NCOPY_DEBUG
fprintf(stderr,"Copied %u (actual %u)\n",(unsigned int)thisMove,
(unsigned int)amountCopied);
#endif
amtLeft -= amountCopied;
sourceOff += amountCopied;
if (optVerbose) {
printf("\rNetWare copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,
(100 - (long)((float)amtLeft /(float)totalSize * 100.0)));
if (retryCount)
printf(" %d retries",retryCount);
fflush(stdout);
}
}
if (retryCount >= MaxNcopyRetries)
retValue = 1;
if (optVerbose)
printf("\n");
if (ncp_close_file(sourceconn,dest_file.file_id) != 0) {
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramOutputFile);
retValue = 1;
}
/* Clear signal handling globals */
OutputOpen = 0;
CurrentConn = NULL;
CurrentFile = NULL;
if (ncp_close_file(sourceconn,source_file.file_id) != 0) {
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramInputFile);
retValue = 1;
}
if (ncp_dealloc_dir_handle(sourceconn, dest_dir_handle) != 0)
{
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
paramOutputFile);
retValue = 1;
}
if (ncp_dealloc_dir_handle(sourceconn, source_dir_handle) != 0)
{
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
paramInputFile);
retValue = 1;
}
return retValue;
}
/****************************************************************************
* Decides whether to use the traditional file copy or the netware remote
* file copy.
*/
int copyFiles(const char *realsource, const char *realdestination,
const char *paraminputfile, const char *paramoutputfile)
{
int oldUMask;
char fileBuffer[24000];
int retVal = 0;
int ncpMountIndex = ncpIndex(realsource,realdestination);
#ifdef NCOPY_DEBUG
printf("Real Source '%s'\n"
"Real Dest '%s'\n"
"Param Src '%s'\n"
"Param Dest '%s'\n",realsource,realdestination,paraminputfile,
paramoutputfile);
#endif
oldUMask = umask(0);
if (ncpMountIndex < 0)
retVal = normalFileCopy(realsource,realdestination,fileBuffer,
sizeof(fileBuffer),
paraminputfile,paramoutputfile);
else
retVal = netwareCopyFile(ncpMountIndex,realsource,realdestination,
paraminputfile,paramoutputfile);
umask(oldUMask);
return retVal;
}
/****************************************************************************
*
* HERE
*
* Brian may NEED "fake" path if he prints error messages?
* or I may need a way to get his error messages so I can
* print them with the "fake" path.
* My current error messages are on the REAL path, which would be confusing...
*
* (1-source problem, 2-destination problem, 3-other fatal)
* We need to decide when to exit or continue the loop,
* and what to return when we do exit the loop.
* Is it failure if 3 files are to be copied, and 1 fails?
* If one copy fails, we stay in the loop, right?
* Is it failure if destination fails?
* Do we Stay in the loop?
*/
static int copyRealPaths(const char *source, const char *destination)
{
char realsource[MAXPATHLEN*2];
char realdestination[MAXPATHLEN*2];
char dirPart[MAXPATHLEN+1];
char filePart[MAXPATHLEN+1];
const char *p;
if(realpath(source, realsource) == 0) { /* the source must at least exist */
fprintf(stderr,"%s: %s: %s\n",
ProgramName, source, strerror(errno));
return 1; /* indicate a "source" problem */
}
if(realpath(destination, realdestination) == 0) {/* dest file missing? OK */
strncpy(dirPart, destination, MAXPATHLEN); /* but "dirpart" must work */
dirPart[MAXPATHLEN] = 0;
p=myBaseName(dirPart);
strcpy(filePart, p);
dirPart[p - dirPart] = 0; /* isolates "directory" part from "file part" */
if(realpath(dirPart, realdestination) == 0) {
fprintf(stderr,"%s: %s: %s\n",
ProgramName, dirPart, strerror(errno));
return 2; /* indicate a "destination" problem */
}
if(*realdestination != '/' || *(realdestination+1)) strcat(realdestination, "/");
strcat(realdestination, filePart);
}
/* becomes prog exit code */
/* Test Cases: (Where file/dir may or may not exist)
* "", file, file/, dir, dir/
* /, //, /dir, /dir/, /file, /file/,
* /tmp/file, /tmp/file/, tmp/file, tmp/file/,
* /tmp/dir, /tmp/dir/, tmp/dir, tmp/dir/
*/
return copyFiles(realsource, realdestination,source,destination);
}
/****************************************************************************
* guaranteed argc is at least 2 and
* if argc > 2 last parameter is a directory
* by validateFileArgs()
*/
static int handleFileArgs(int argc, char * const argv[])
{
int loop;
const char *destination;
int copyStatus;
int returnCode=0; /* default program exit code */
const char *baseNamePtr;
char destinationfile[MAXPATHLEN*2];
destination=argv[argc-1]; /* get LAST argument */
for (loop = 0; loop < (argc-1); loop++) { /* all file arguments, but last */
strncpy(destinationfile, destination, MAXPATHLEN);
destinationfile[MAXPATHLEN]=0;
if((argc > 2) || (!notDir(argv[argc-1]))) { /* destination is a dir */
if(*destinationfile != '/' || *(destinationfile+1)) strcat(destinationfile,"/");
baseNamePtr=myBaseName(argv[loop]); /* get the file name */
strcat(destinationfile,baseNamePtr); /* add it on end of directory */
}
copyStatus=copyRealPaths(argv[loop], destinationfile); /* do the copy */
if(copyStatus > 1) return copyStatus; /* fatal failure? bye */
if(copyStatus == 1) returnCode=1; /* a partial failure? we can continue */
}
return returnCode; /* return what will be the program exit code */
}
/****************************************************************************
*
*/
static void handleSignals(int sigNumber)
{
/* Ignore Signal Handling while cleaning up */
/* SIGHUP */
sHangupSig.sa_handler=SIG_IGN;
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
fprintf(stderr,"%s: Reset to ignore SIGHUP signal failed: %s",
ProgramName, strerror(errno));
}
/* SIGINT */
sInterruptSig.sa_handler=SIG_IGN;
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
fprintf(stderr,"%s: Reset to ignore SIGINT signal failed: %s",
ProgramName, strerror(errno));
}
/* SIGQUIT */
sQuitSig.sa_handler=SIG_IGN;
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
fprintf(stderr,"%s: Reset to ignore SIGQUIT signal failed: %s",
ProgramName, strerror(errno));
}
/* SIGTERM */
sTermSig.sa_handler=SIG_IGN;
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
fprintf(stderr,"%s: Reset to ignore SIGTERM signal failed: %s",
ProgramName, strerror(errno));
}
/* If we don't close the ncp output file, we have to ncpumount and
ncpmount before we can get rid of it. */
if (OutputOpen) {
/* Issue a warning if we cannot close the file */
/* If an error occurs we probably have to umount/mount to
remove the file */
if (ncp_close_file(CurrentConn,CurrentFile->file_id) != 0) {
fprintf(stderr,"%s: unclean close of output file",ProgramName);
}
OutputOpen = 0;
}
exit(128 + sigNumber);
}
/****************************************************************************
* We'll trap Hangup, Interrupt, Quit or Terminate
*/
static int trapSignals()
{
if(sigaction(SIGHUP, NULL, &sHangupSig)) { /* init structure fields */
fprintf(stderr,"%s: Get HANGUP signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
sHangupSig.sa_handler = handleSignals;
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
fprintf(stderr,"%s: Reset HANGUP signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
if(sigaction(SIGINT, NULL, &sInterruptSig)) { /* init structure fields */
fprintf(stderr,"%s: Get INTERRUPT signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
sInterruptSig.sa_handler = handleSignals;
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
fprintf(stderr,"%s: Reset INTERRUPT signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
if(sigaction(SIGQUIT, NULL, &sQuitSig)) { /* init structure fields */
fprintf(stderr,"%s: Get QUIT signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
sQuitSig.sa_handler = handleSignals;
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
fprintf(stderr,"%s: Reset QUIT signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
if(sigaction(SIGTERM, NULL, &sTermSig)) { /* init structure fields */
fprintf(stderr,"%s: Get TERMINATE signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
sTermSig.sa_handler = handleSignals;
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
fprintf(stderr,"%s: Reset TERMINATE signal action failed: %s",
ProgramName, strerror(errno));
return 1;
}
return 0;
}
/****************************************************************************
*
*/
int main(int argc, char * const argv[])
{
int returnCode;
ProgramName=argv[0];
if(handleOptions(argc, argv)) { /* bad option, missing option parameter */
usage();
return 1;
}
if(optVersion) { /* only option not requiring any arguments */
printf("%s version %s\n", ProgramName, VersionStr);
return 0;
}
if(validateFileArgs(argc - optind, argv + optind)) {
usage();
return 1;
}
if(trapSignals()) return 1;
loadMountTable();
returnCode = handleFileArgs(argc - optind, argv + optind);
releaseMountTable();
return returnCode;
}

View File

@@ -237,6 +237,10 @@ ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result,
if ((sock = socket(AF_IPX,SOCK_DGRAM,PF_IPX)) < 0)
{
if (errno == EINVAL)
{
return NCPL_ET_NO_IPX;
}
return errno;
}
@@ -255,6 +259,10 @@ ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result,
if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))==-1)
{
if (errno == EADDRNOTAVAIL)
{
errno = NCPL_ET_NO_INTERFACE;
}
goto finished;
}
@@ -340,7 +348,11 @@ ipx_make_reachable(IPXNet network)
if (sock == -1)
{
return -1;
if (errno == EINVAL)
{
return NCPL_ET_NO_IPX;
}
return errno;
}
opt=1;
@@ -516,14 +528,16 @@ do_ncp_call(struct ncp_conn *conn, int request_size)
*((struct ncp_request_header *)(&(conn->packet)));
int result;
int retries = 3;
int retries = 20;
int len;
long err;
struct ncp_reply_header *r =
(struct ncp_reply_header *)&(conn->packet);
while (retries > 0)
{
struct ncp_reply_header reply;
struct sockaddr_ipx sender;
int sizeofaddr = sizeof(sender);
retries -= 1;
result = sendto(conn->ncp_sock, conn->packet,
@@ -537,30 +551,48 @@ do_ncp_call(struct ncp_conn *conn, int request_size)
}
re_select:
len = ipx_recv(conn->ncp_sock,
conn->packet, NCP_PACKET_SIZE, 0, 1, &err);
len = ipx_recvfrom(conn->ncp_sock,
(char *)&reply, sizeof(reply),
MSG_PEEK, &sender, &sizeofaddr, 3, &err);
if ( (len == sizeof(*r))
&& (r->type == NCP_POSITIVE_ACK))
if ((len < 0) && (err == ETIMEDOUT))
{
goto re_select;
}
if ( (len >= sizeof(*r))
&& (r->type == NCP_REPLY)
&& ( (request.type == NCP_ALLOC_SLOT_REQUEST)
|| ( (r->sequence == request.sequence)
&& (r->conn_low == request.conn_low)
&& (r->conn_high == request.conn_high))))
{
conn->reply_size = len;
break;
continue;
}
if (len < 0)
{
return err;
}
if ( /* Is the sender wrong? */
(memcmp(&sender.sipx_node,
&(conn->i.addr.sipx_node), 6) != 0)
|| (sender.sipx_port != conn->i.addr.sipx_port)
/* Did the sender send a positive acknowledge? */
|| ( (len == sizeof(reply))
&& (reply.type == NCP_POSITIVE_ACK))
/* Did we get a bogus answer? */
|| ( (len < sizeof(reply))
|| (reply.type != NCP_REPLY)
|| ( (request.type != NCP_ALLOC_SLOT_REQUEST)
&& ( (reply.sequence != request.sequence)
|| (reply.conn_low != request.conn_low)
|| (reply.conn_high != request.conn_high)))))
{
/* Then throw away the packet */
ipx_recv(conn->ncp_sock, (char *)&reply, sizeof(reply),
0, 1, &err);
goto re_select;
}
ipx_recv(conn->ncp_sock, conn->packet, NCP_PACKET_SIZE,
0, 1, &err);
conn->reply_size = len;
return 0;
}
return 0;
return ETIMEDOUT;
}
static int
@@ -578,8 +610,9 @@ ncp_mount_request(struct ncp_conn *conn, int function)
if (conn->has_subfunction != 0)
{
*(__u16 *)&(h->data[0]) = conn->current_size
- sizeof(struct ncp_request_header)- 2;
*(__u16 *)&(h->data[0])
= htons(conn->current_size
- sizeof(struct ncp_request_header) - 2);
}
request.function = function;
@@ -591,6 +624,8 @@ ncp_mount_request(struct ncp_conn *conn, int function)
return result;
}
conn->completion = reply->completion_code;
conn->conn_status = reply->connection_state;
conn->ncp_reply_size = result - sizeof(struct ncp_reply_header);
if ((reply->completion_code != 0) && (conn->verbose != 0))
@@ -614,8 +649,9 @@ ncp_temp_request(struct ncp_conn *conn, int function)
if (conn->has_subfunction != 0)
{
*(__u16 *)&(h->data[0]) = conn->current_size
- sizeof(struct ncp_request_header) - 2;
*(__u16 *)&(h->data[0])
= htons(conn->current_size
- sizeof(struct ncp_request_header) - 2);
}
h->type = NCP_REQUEST;
@@ -751,9 +787,10 @@ ncp_connect_any(struct ncp_conn *conn, int wdog_needed)
char name[NCP_BINDERY_NAME_LEN];
long result;
if (ipx_sap_find_nearest(IPX_SAP_FILE_SERVER, &addr, name) != 0)
if ((result = ipx_sap_find_nearest(IPX_SAP_FILE_SERVER,
&addr, name)) != 0)
{
return -1;
return result;
}
if ((result = ncp_connect_addr(conn, &addr, wdog_needed)) != 0)
@@ -833,13 +870,19 @@ ncp_find_fileserver(const char *server_name, long *err)
result.sipx_network = n_addr->network;
result.sipx_port = n_addr->port;
ipx_assign_node(result.sipx_node, n_addr->node);
/* To make the final server reachable, we connect again. See
above. (When can we rely on all users running ipxd??? :-)) */
memzero(conn);
if ( ((*err = ncp_connect_addr(&conn, &result, 0)) != 0)
|| ((*err = ncp_do_close(&conn)) != 0))
{
return NULL;
}
return &result;
}
static long
ncp_open_temporary(struct ncp_conn *conn,
const struct ncp_conn_spec *spec)
@@ -887,6 +930,8 @@ ncp_find_permanent(const struct ncp_conn_spec *spec)
int mount_fid;
struct ncp_fs_info i;
initialize_NCPL_error_table();
if ((mtab = fopen(MOUNTED, "r")) == NULL)
{
return NULL;
@@ -960,8 +1005,16 @@ ncp_open_permanent(struct ncp_conn *conn,
conn->mount_fid = open(mount_point, O_RDONLY, 0);
conn->i.version = NCP_GET_FS_INFO_VERSION;
ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &(conn->i));
strncpy(conn->server, spec->server, sizeof(conn->server));
strncpy(conn->user, spec->user, sizeof(conn->user));
if (spec != NULL)
{
strncpy(conn->server, spec->server, sizeof(conn->server));
strncpy(conn->user, spec->user, sizeof(conn->user));
}
else
{
memset(conn->server, '\0', sizeof(conn->server));
memset(conn->user, '\0', sizeof(conn->user));
}
strcpy(conn->mount_point, mount_point);
conn->is_connected = CONN_PERMANENT;
return 0;
@@ -972,6 +1025,8 @@ ncp_open(const struct ncp_conn_spec *spec, long *err)
{
struct ncp_conn *result;
initialize_NCPL_error_table();
result = malloc(sizeof(struct ncp_conn));
if (result == NULL)
@@ -1001,6 +1056,8 @@ ncp_open_mount(const char *mount_point, long *err)
{
struct ncp_conn *result;
initialize_NCPL_error_table();
if (strlen(mount_point) >= sizeof(result->mount_point))
{
*err = ENAMETOOLONG;
@@ -1288,7 +1345,7 @@ ncp_fopen_nwc(const char *user, const char *mode)
struct ncp_conn_spec *
ncp_find_conn_spec(const char *server, const char *user, const char *password,
uid_t uid, long *err)
int login_necessary, uid_t uid, long *err)
{
static struct ncp_conn_spec spec;
@@ -1297,6 +1354,8 @@ ncp_find_conn_spec(const char *server, const char *user, const char *password,
FILE *nwc;
struct ncp_conn_spec *nwc_ent;
initialize_NCPL_error_table();
*err = 0;
memzero(spec);
spec.uid = getuid();
@@ -1383,6 +1442,12 @@ ncp_find_conn_spec(const char *server, const char *user, const char *password,
}
}
if (login_necessary == 0)
{
memset(spec.user, 0, sizeof(spec.user));
memset(spec.password, 0, sizeof(spec.password));
}
if (strlen(spec.user) == 0)
{
return &spec;
@@ -1500,12 +1565,21 @@ ncp_initialize_as(int *argc, char **argv,
i += 1;
}
if ((spec = ncp_find_conn_spec(server, user, password,
getuid(), err)) == NULL)
{
return NULL;
}
spec = ncp_find_conn_spec(server, user, password, login_necessary,
getuid(), err);
if (spec == NULL)
{
if (login_necessary != 0)
{
return NULL;
}
else
{
return ncp_open(NULL, err);
}
}
spec->login_type = login_type;
if (login_necessary == 0)
@@ -1789,7 +1863,7 @@ ncp_send_broadcast(struct ncp_conn *conn,
}
/*
* result is a 8-byte buffer
* target is a 8-byte buffer
*/
long
ncp_get_encryption_key(struct ncp_conn *conn,
@@ -1846,6 +1920,27 @@ ncp_get_bindery_object_id(struct ncp_conn *conn,
return 0;
}
long
ncp_get_bindery_object_name(struct ncp_conn *conn,
__u32 object_id,
struct ncp_bindery_object *target)
{
long result;
ncp_init_request_s(conn, 54);
ncp_add_dword(conn, htonl(object_id));
if ((result = ncp_request(conn, 23)) != 0) {
ncp_unlock_conn(conn);
return result;
}
target->object_id = ntohl(ncp_reply_dword(conn, 0));
target->object_type = ntohs(ncp_reply_word (conn, 4));
memcpy(target->object_name, ncp_reply_data(conn, 6), 48);
ncp_unlock_conn(conn);
return 0;
}
long
ncp_scan_bindery_object(struct ncp_conn *conn,
__u32 last_id, __u16 object_type, char *search_string,
@@ -1874,6 +1969,40 @@ ncp_scan_bindery_object(struct ncp_conn *conn,
return 0;
}
long
ncp_create_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
__u8 object_security,
__u8 object_status)
{
long result;
ncp_init_request_s(conn, 50);
ncp_add_byte(conn, object_status);
ncp_add_byte(conn, object_security);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_delete_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name)
{
long result;
ncp_init_request_s(conn, 51);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_read_property_value(struct ncp_conn *conn,
@@ -1900,6 +2029,149 @@ ncp_read_property_value(struct ncp_conn *conn,
return 0;
}
long
ncp_scan_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
__u32 last_id, char *search_string,
struct ncp_property_info *property_info)
{
long result;
ncp_init_request_s(conn, 60);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_dword(conn, htonl(last_id));
ncp_add_pstring(conn, search_string);
if ((result = ncp_request(conn, 23)) != 0) {
ncp_unlock_conn(conn);
return result;
}
memcpy(property_info->property_name,ncp_reply_data(conn, 0), 16);
property_info->property_flags = ncp_reply_byte(conn,16);
property_info->property_security = ncp_reply_byte(conn,17);
property_info->search_instance = ntohl(ncp_reply_dword(conn,18));
property_info->value_available_flag = ncp_reply_byte(conn,22);
property_info->more_properties_flag = ncp_reply_byte(conn,23);
ncp_unlock_conn(conn);
return 0;
}
long
ncp_add_object_to_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name)
{
long result;
ncp_init_request_s(conn, 65);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_pstring(conn, property_name);
ncp_add_word(conn, htons(member_type));
ncp_add_pstring(conn, member_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_change_property_security(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_security)
{
long result;
ncp_init_request_s(conn, 59);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_byte(conn, property_security);
ncp_add_pstring(conn, property_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_create_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_flags, __u8 property_security)
{
long result;
ncp_init_request_s(conn, 57);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_byte(conn, property_flags);
ncp_add_byte(conn, property_security);
ncp_add_pstring(conn, property_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_delete_object_from_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name)
{
long result;
ncp_init_request_s(conn, 66);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_pstring(conn, property_name);
ncp_add_word(conn, htons(member_type));
ncp_add_pstring(conn, member_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_delete_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name)
{
long result;
ncp_init_request_s(conn, 58);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_pstring(conn, property_name);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_write_property_value(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 segment,
struct nw_property *property_value)
{
long result;
ncp_init_request_s(conn, 62);
ncp_add_word(conn, htons(object_type));
ncp_add_pstring(conn, object_name);
ncp_add_byte(conn,segment);
ncp_add_byte(conn, property_value->more_flag);
ncp_add_pstring(conn, property_name);
ncp_add_mem(conn, property_value->value, 128);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_login_encrypted(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
@@ -1924,6 +2196,43 @@ ncp_login_encrypted(struct ncp_conn *conn,
return result;
}
long
ncp_change_login_passwd(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *oldpasswd,
const unsigned char *newpasswd)
{
long id = htonl(object->object_id);
unsigned char cryptkey[8];
unsigned char newpwd[16]; /* new passwd as stored by server */
unsigned char oldpwd[16]; /* old passwd as stored by server */
unsigned char len;
long result;
memcpy(cryptkey, key, 8);
shuffle((byte *)&id, oldpasswd, strlen(oldpasswd), oldpwd);
shuffle((byte *)&id, newpasswd, strlen(newpasswd), newpwd);
nw_encrypt(cryptkey, oldpwd, cryptkey);
newpassencrypt(oldpwd, newpwd, newpwd);
newpassencrypt(oldpwd+8, newpwd+8, newpwd+8);
if ((len = strlen(newpasswd)) > 63)
{
len = 63;
}
len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40;
ncp_init_request_s(conn, 75);
ncp_add_mem(conn, cryptkey, 8);
ncp_add_word(conn, htons(object->object_type));
ncp_add_pstring(conn, object->object_name);
ncp_add_byte(conn, len);
ncp_add_mem(conn, newpwd, 16);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_login_user(struct ncp_conn *conn,
const unsigned char *username,
@@ -1952,8 +2261,27 @@ ncp_login_object(struct ncp_conn *conn,
}
if ((result = ncp_login_encrypted(conn, &user,
ncp_key, password)) != 0) {
return result;
ncp_key, password)) != 0)
{
struct nw_property p;
struct ncp_prop_login_control *l
= (struct ncp_prop_login_control *)&p;
if (conn->completion != NCP_GRACE_PERIOD)
{
return result;
}
fprintf(stderr, "Your password has expired\n");
if ((result = ncp_read_property_value(conn, NCP_BINDERY_USER,
username, 1,
"LOGIN_CONTROL",
&p)) == 0)
{
fprintf(stderr, "You have %d login attempts left\n",
l->GraceLogins);
}
}
return 0;
}
@@ -2287,7 +2615,42 @@ ncp_delete_directory(struct ncp_conn *conn,
ncp_unlock_conn(conn);
return result;
}
long
ncp_add_trustee(struct ncp_conn *conn,
int dir_handle, const char *path,
__u32 object_id, __u8 rights)
{
long result;
ncp_init_request_s(conn, 13);
ncp_add_byte(conn, dir_handle);
ncp_add_dword(conn, htonl(object_id));
ncp_add_byte(conn, rights);
ncp_add_pstring(conn, path);
result = ncp_request(conn, 22);
ncp_unlock_conn(conn);
return result;
}
long
ncp_delete_trustee(struct ncp_conn *conn,
int dir_handle, const char *path,__u32 object_id)
{
long result;
ncp_init_request_s(conn, 14);
ncp_add_byte(conn, dir_handle);
ncp_add_dword(conn, htonl(object_id));
ncp_add_byte(conn, 0);
ncp_add_pstring(conn, path);
result = ncp_request(conn, 22);
ncp_unlock_conn(conn);
return result;
}
long
ncp_rename_directory(struct ncp_conn *conn,
int dir_handle,
@@ -2858,9 +3221,9 @@ ncp_copy_file(struct ncp_conn *conn,
ncp_add_byte(conn, 0); /* reserved */
ncp_add_mem(conn, source_file, 6);
ncp_add_mem(conn, target_file, 6);
ncp_add_dword(conn, source_offset);
ncp_add_dword(conn, target_offset);
ncp_add_dword(conn, count);
ncp_add_dword(conn, htonl(source_offset));
ncp_add_dword(conn, htonl(target_offset));
ncp_add_dword(conn, htonl(count));
if ((result = ncp_request(conn, 74)) != 0)
{
@@ -2868,7 +3231,7 @@ ncp_copy_file(struct ncp_conn *conn,
return result;
}
*copied_count = ncp_reply_dword(conn, 0);
*copied_count = ntohl(ncp_reply_dword(conn, 0));
ncp_unlock_conn(conn);
return 0;
}
@@ -2933,3 +3296,33 @@ ncp_alloc_short_dir_handle(struct ncp_conn *conn,
ncp_unlock_conn(conn);
return result;
}
long
ncp_add_trustee_set(struct ncp_conn *conn,
__u8 volume_number, __u32 dir_entry,
__u16 rights_mask,
int object_count, struct ncp_trustee_struct *rights)
{
long result = 0;
ncp_init_request(conn);
ncp_add_byte(conn, 10); /* subfunction */
ncp_add_byte(conn, 0); /* dos name space */
ncp_add_byte(conn, 0); /* reserved */
ncp_add_word(conn, 0x8006);
ncp_add_word(conn, rights_mask);
ncp_add_word(conn, object_count);
ncp_add_handle_path(conn, volume_number, dir_entry, 1, NULL);
while (object_count > 0)
{
ncp_add_dword(conn, htonl(rights->object_id));
ncp_add_word(conn, rights->rights);
object_count -= 1;
rights += 1;
}
result = ncp_request(conn, 87);
ncp_unlock_conn(conn);
return result;
}

View File

@@ -79,6 +79,15 @@ struct ncp_search_seq {
int namespace;
};
struct ncp_property_info {
__u8 property_name[16];
__u8 property_flags;
__u8 property_security;
__u32 search_instance;
__u8 value_available_flag;
__u8 more_properties_flag;
};
/* 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
@@ -95,7 +104,7 @@ ncp_initialize_as(int *argc, char **argv,
int login_necessary, int login_type, long *err);
/* Open an existing permanent connection */
/* Open a connection */
struct ncp_conn *
ncp_open(const struct ncp_conn_spec *spec, long *err);
@@ -137,7 +146,7 @@ ncp_get_conn_ent(FILE *filep);
struct ncp_conn_spec *
ncp_find_conn_spec(const char *server, const char *user, const char *password,
uid_t uid, long *err);
int login_necessary, uid_t uid, long *err);
long
ncp_get_file_server_description_strings(struct ncp_conn *conn,
@@ -165,19 +174,106 @@ ncp_get_bindery_object_id(struct ncp_conn *conn,
const char *object_name,
struct ncp_bindery_object *target);
long
ncp_get_bindery_object_name(struct ncp_conn *conn,
__u32 object_id,
struct ncp_bindery_object *target);
long
ncp_scan_bindery_object(struct ncp_conn *conn,
__u32 last_id, __u16 object_type, char *search_string,
struct ncp_bindery_object *target);
long
ncp_create_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
__u8 object_security,
__u8 object_status);
long
ncp_delete_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name);
long
ncp_change_object_security(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
__u8 security);
struct ncp_prop_login_control {
__u8 AccountExpireDate[3] __attribute__ ((packed));
__u8 Disabled __attribute__ ((packed));
__u8 PasswordExpireDate[3] __attribute__ ((packed));
__u8 GraceLogins __attribute__ ((packed));
__u16 PasswordExpireInterval __attribute__ ((packed));
__u8 MaxGraceLogins __attribute__ ((packed));
__u8 MinPasswordLength __attribute__ ((packed));
__u16 MaxConnections __attribute__ ((packed));
__u8 ConnectionTimeMask[42] __attribute__ ((packed));
__u8 LastLogin[6] __attribute__ ((packed));
__u8 RestrictionMask __attribute__ ((packed));
__u8 reserved __attribute__ ((packed));
__u32 MaxDiskUsage __attribute__ ((packed));
__u16 BadLoginCount __attribute__ ((packed));
__u32 BadLoginCountDown __attribute__ ((packed));
__u8 LastIntruder[8] __attribute__ ((packed));
};
long
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);
long
ncp_scan_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
__u32 last_id, char *search_string,
struct ncp_property_info *property_info);
long
ncp_add_object_to_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name);
long
ncp_change_property_security(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_security);
long
ncp_create_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_flags, __u8 property_security);
long
ncp_delete_object_from_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name);
long
ncp_delete_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name);
long
ncp_write_property_value(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 segment,
struct nw_property *property_value);
long
ncp_login_encrypted(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *passwd);
long
ncp_change_login_passwd(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *oldpasswd,
const unsigned char *newpasswd);
#define NCP_GRACE_PERIOD (0xdf)
long
ncp_login_user(struct ncp_conn *conn,
const unsigned char *username,
@@ -251,6 +347,15 @@ ncp_rename_directory(struct ncp_conn *conn,
int dir_handle,
const char *old_path, const char *new_path);
long
ncp_add_trustee(struct ncp_conn *conn,
int dir_handle, const char *path,
__u32 object_id, __u8 rights);
long
ncp_delete_trustee(struct ncp_conn *conn,
int dir_handle, const char *path, __u32 object_id);
long
ncp_read(struct ncp_conn *conn, const char *file_id,
off_t offset, size_t count, char *target);
@@ -355,4 +460,22 @@ ncp_alloc_short_dir_handle(struct ncp_conn *conn,
__u16 alloc_mode,
__u8 *target);
long
ncp_get_effective_dir_rights(struct ncp_conn *conn,
struct nw_info_struct *file,
__u16 *target);
struct ncp_trustee_struct
{
__u32 object_id;
__u16 rights;
};
long
ncp_add_trustee_set(struct ncp_conn *conn,
__u8 volume_number, __u32 dir_entry,
__u16 rights_mask,
int object_count, struct ncp_trustee_struct *rights);
#endif /* _NCPLIB_H */

View File

@@ -18,4 +18,22 @@ ec NCPL_ET_MSG_TOO_LONG,
ec NCPL_ET_NO_SPEC,
"Could not find valid connection spec"
ec NCPL_ET_INVALID_MODE,
"$HOME/.nwclient has invalid mode"
ec NCPL_ET_LOGIN_DENIED,
"Login denied"
ec NCPL_ET_NO_INTERFACE,
"No primary IPX interface found"
ec NCPL_ET_NO_PASSWORD,
"Could not get password"
ec NCPL_ET_PWD_TOO_LONG,
"Password too long"
ec NCPL_ET_NO_IPX,
"Could not alloc IPX socket. Probably no IPX support in kernel."
end

View File

@@ -10,7 +10,7 @@
* a conditional which leaves out the test and load code.
*
* Even if we _do_ want ncpmount to load the module, passing a
* fully-qualified pathname to insmod causes it to bypass a
* fully-qualified pathname to modprobe causes it to bypass a
* path search. This may lead to ncpfs.o not being found on
* some systems.
*/
@@ -102,7 +102,7 @@ load_ncpfs(void)
else if (pid == 0)
{
/* child */
execl("/sbin/insmod", "insmod", "ncpfs", NULL);
execl("/sbin/modprobe", "modprobe", "ncpfs", NULL);
_exit(127); /* execl error */
}
else
@@ -321,7 +321,7 @@ main(int argc, char *argv[])
}
}
if ((spec = ncp_find_conn_spec(server, user, password, data.uid, &err))
if ((spec = ncp_find_conn_spec(server,user,password,1, data.uid, &err))
== NULL)
{
com_err(progname, err, "in find_conn_spec");
@@ -484,12 +484,42 @@ main(int argc, char *argv[])
exit(1);
}
if ( ((conn = ncp_open_mount(mount_point, &err)) == NULL)
|| ((err = ncp_login_user(conn, spec->user, spec->password)) != 0)
|| ((err = ioctl(conn->mount_fid, NCP_IOC_CONN_LOGGED_IN,
NULL)) != 0))
if ((conn = ncp_open_mount(mount_point, &err)) == NULL)
{
com_err("ncpmount", err, "in login");
com_err("ncpmount", err, "attempt to open mount point");
umount(mount_point);
exit(1);
}
if ((err = ncp_login_user(conn, spec->user, spec->password)) != 0)
{
struct nw_property p;
struct ncp_prop_login_control *l
= (struct ncp_prop_login_control *)&p;
if (conn->completion != NCP_GRACE_PERIOD)
{
com_err("ncpmount", err, "in login");
fprintf(stderr, "Login denied\n");
ncp_close(conn);
umount(mount_point);
exit(1);
}
fprintf(stderr, "Your password has expired\n");
if ((err = ncp_read_property_value(conn, NCP_BINDERY_USER,
spec->user, 1,
"LOGIN_CONTROL", &p)) == 0)
{
fprintf(stderr, "You have %d login attempts left\n",
l->GraceLogins);
}
}
if ((err = ioctl(conn->mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL)) != 0)
{
com_err("ncpmount", err, "in logged_indication");
ncp_close(conn);
umount(mount_point);
exit(1);

View File

@@ -106,7 +106,30 @@ test_create(struct ncp_conn *conn)
return;
}
}
int
test_change(struct ncp_conn *conn)
{
long result;
unsigned char ncp_key[8];
struct ncp_bindery_object user;
if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) {
return result;
}
if ((result = ncp_get_bindery_object_id(conn, 1,
"ME", &user)) != 0) {
return result;
}
if ((result = ncp_change_login_passwd(conn, &user, ncp_key,
"MEE", "ME")) != 0)
{
return result;
}
return 0;
}
int
main(int argc, char *argv[])
@@ -120,7 +143,7 @@ main(int argc, char *argv[])
return 1;
}
test_send(conn);
test_change(conn);
ncp_close(conn);
return 0;
}

144
util/npasswd.c Normal file
View File

@@ -0,0 +1,144 @@
/*
* npasswd.c
*
* Change a bindery object's password
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-t type Object type (decimal value)\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn_spec *spec;
struct ncp_conn *conn;
char *server = NULL;
char *object_name = NULL;
int object_type = NCP_BINDERY_USER;
unsigned char ncp_key[8];
struct ncp_bindery_object user;
long err;
char *str;
char oldpass[200], newpass1[200], newpass2[200];
int opt;
progname = argv[0];
while ((opt = getopt(argc, argv, "hS:U:t:")) != EOF)
{
switch(opt) {
case 'S':
server = optarg;
break;
case 'U':
object_name = optarg;
break;
case 't':
object_type = atoi(optarg);
break;
case 'h':
help();
exit(1);
default:
usage();
exit(1);
}
}
spec = ncp_find_conn_spec(server, object_name, "",
1, getuid(), &err);
if (spec == NULL)
{
com_err(argv[0], err, "trying to find server");
exit(1);
}
spec->login_type = object_type;
printf("Changing password for user %s on server %s\n",
spec->user, spec->server);
str = getpass("Enter old password: ");
if (strlen(str) >= sizeof(oldpass))
{
printf("Password too long\n");
exit(1);
}
strcpy(oldpass, str);
str = getpass("Enter new password: ");
if (strlen(str) >= sizeof(newpass1))
{
printf("Password too long\n");
exit(1);
}
strcpy(newpass1, str);
str = getpass("Re-Enter new password: ");
if (strlen(str) >= sizeof(newpass2))
{
printf("Password too long\n");
exit(1);
}
strcpy(newpass2, str);
str_upper(oldpass);
str_upper(newpass1);
str_upper(newpass2);
if (strcmp(newpass1, newpass2) != 0)
{
printf("You mistype the new password, try again\n");
exit(1);
}
strcpy(spec->password, oldpass);
if ((conn = ncp_open(spec, &err)) == NULL)
{
com_err(argv[0], err, "when trying to open connection");
exit(1);
}
if ( ((err = ncp_get_encryption_key(conn, ncp_key)) != 0)
|| ((err = ncp_get_bindery_object_id(conn, 1, spec->user,
&user)) != 0)
|| ((err = ncp_change_login_passwd(conn, &user, ncp_key,
oldpass, newpass1)) != 0))
{
com_err(argv[0], err, "trying to change password");
}
ncp_close(conn);
return 0;
}

View File

@@ -306,8 +306,6 @@ main(int argc, char *argv[])
if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) {
printf("close error\n");
ncp_close(conn);
return;
}
ncp_close(conn);

160
util/nwbocreate.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* nwbocreate.c
*
* Create a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of created object\n"
"-t type Object type (decimal value)\n"
"-r read-flag Read security\n"
"-w write-flag Write security\n"
"\n");
}
static int
parse_security(const char *security)
{
if (strcasecmp(security, "anyone") == 0)
{
return 0;
}
if (strcasecmp(security, "logged") == 0)
{
return 1;
}
if (strcasecmp(security, "object") == 0)
{
return 2;
}
if (strcasecmp(security, "supervisor") == 0)
{
return 3;
}
if (strcasecmp(security, "netware") == 0)
{
return 4;
}
return -1;
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
long err;
int read_sec = 1; /* logged read */
int write_sec = 3; /* supervisor write */
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:r:w:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'r':
read_sec = parse_security(optarg);
if (read_sec < 0)
{
fprintf(stderr,
"%s: Wrong read security\n"
"Must be one of anyone, logged, "
"object, supervisor or netware\n",
argv[0]);
goto finished;
}
break;
case 'w':
write_sec = parse_security(optarg);
if (write_sec < 0)
{
fprintf(stderr,
"%s: Wrong write security\n"
"Must be one of anyone, logged, "
"object, supervisor or netware\n",
argv[0]);
goto finished;
}
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (ncp_create_bindery_object(conn, object_type, object_name,
(write_sec << 4) + read_sec, 0) != 0)
{
fprintf(stderr, "%s: Could not create the object\n", argv[0]);
}
else
{
result = 0;
}
finished:
ncp_close(conn);
return result;
}

124
util/nwbols.c Normal file
View File

@@ -0,0 +1,124 @@
/*
* nwlsobj.c
*
* List bindery objects
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <stdlib.h>
#include "ncplib.h"
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options] pattern\n", progname);
return;
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-t type Object type to be listed (decimal)\n"
"-v Verbose listing\n"
"\n");
}
int
main(int argc, char **argv)
{
struct ncp_conn *conn;
struct ncp_bindery_object o;
int found = 0;
char default_pattern[] = "*";
char *pattern = default_pattern;
char *p;
long err;
int opt;
int verbose = 0;
__u16 type = 0xffff;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
return 1;
}
while ((opt = getopt(argc, argv, "hvt:")) != EOF)
{
switch(opt) {
case 'h':
help();
exit(1);
case 't':
type = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
default:
usage();
exit(1);
}
}
if (optind < argc-1)
{
usage();
exit(1);
}
if (optind == argc-1)
{
pattern = argv[optind];
}
for (p = pattern; *p != '\0'; p++)
{
*p = toupper(*p);
}
o.object_id = 0xffffffff;
while (ncp_scan_bindery_object(conn, o.object_id,
type, pattern, &o) == 0)
{
found = 1;
if (verbose != 0)
{
printf("%s %08X %04X %d %02X %d\n",
o.object_name, (unsigned int)o.object_id,
(unsigned int)o.object_type,
o.object_flags, o.object_security,
o.object_has_prop);
}
else
{
printf("%s %08X %04X\n",
o.object_name, (unsigned int)o.object_id,
(unsigned int)o.object_type);
}
}
ncp_close(conn);
return 0;
}

120
util/nwboprops.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* nwboprops.c
*
* List properties of a bindery object
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object inspected\n"
"-t type Object type (decimal value)\n"
"-v Verbose listing\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
long err;
struct ncp_property_info info;
int result = 1;
int verbose = 0;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:v")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
info.search_instance = 0xffffffff;
while (ncp_scan_property(conn, object_type, object_name,
info.search_instance, "*", &info) == 0)
{
if (verbose != 0)
{
printf("%s %d %02x %d\n",
info.property_name, info.property_flags,
info.property_security,
info.value_available_flag);
}
else
{
printf("%s\n", info.property_name);
}
}
finished:
ncp_close(conn);
return result;
}

105
util/nwborm.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* nwborm.c
*
* Destroy a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object to be removed\n"
"-t type Object type (decimal value)\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (ncp_delete_bindery_object(conn, object_type, object_name) != 0)
{
fprintf(stderr, "%s: Could not delete the object\n", argv[0]);
}
else
{
result = 0;
}
finished:
ncp_close(conn);
return result;
}

246
util/nwbpadd.c Normal file
View File

@@ -0,0 +1,246 @@
/*
* nwbpadd.c
*
* Set the contents of a SET property of a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options] [values]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of accessed object\n"
"-t type Object type (decimal value)\n"
"-p property Name of property to be touched\n"
"value value to be added\n"
"\n"
"If property is of type SET, value is an object id (hex)\n"
"Otherwise, value is either a string value to be written, or\n"
"a count of bytes to be written. The latter is assumed if\n"
"more than one value argument is given. The count is decimal,\n"
"and the following arguments are interpreted as bytes in\n"
"hexadecimal notation.\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
char *property_name = NULL;
char *value = NULL;
struct ncp_property_info info;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:p:v:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'p':
property_name = optarg;
if (strlen(property_name) > 15)
{
fprintf(stderr, "%s: Property Name too long\n",
argv[0]);
exit(1);
}
str_upper(property_name);
break;
case 'v':
value = optarg;
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (property_name == NULL)
{
fprintf(stderr, "%s: You must specify a property name\n",
argv[0]);
goto finished;
}
if (optind > argc-1)
{
fprintf(stderr, "%s: You must specify a property value\n",
argv[0]);
goto finished;
}
value = argv[optind];
optind += 1;
if (ncp_scan_property(conn, object_type, object_name,
0xffffffff, property_name, &info) != 0)
{
fprintf(stderr, "%s: Could not find property\n", argv[0]);
goto finished;
}
if ((info.property_flags & 2) != 0)
{
/* Property is of type SET */
struct ncp_bindery_object o;
if (optind != argc)
{
fprintf(stderr, "%s: For the SET property %s, you must"
" specify an object id as value\n",
progname, property_name);
goto finished;
}
if (ncp_get_bindery_object_name(conn,
ntohl(strtol(value, NULL, 16)),
&o) != 0)
{
fprintf(stderr, "%s: %s is not a valid object id\n",
progname, value);
goto finished;
}
if (ncp_add_object_to_set(conn, object_type, object_name,
property_name,
o.object_type, o.object_name) != 0)
{
fprintf(stderr, "%s: could not add object %s\n",
progname, o.object_name);
goto finished;
}
}
else
{
/* Property is of type ITEM */
char contents[255*128];
int segno = 1;
int length;
memset(contents, 0, sizeof(contents));
if (optind == argc)
{
/* value is the string to add */
length = strlen(value);
if (length >= sizeof(contents))
{
fprintf(stderr, "%s: Value too long\n",
progname);
goto finished;
}
strcpy(contents, value);
}
else
{
/* value is the byte count */
int i;
length = atoi(value);
if (length >= sizeof(contents))
{
fprintf(stderr, "%s: Value too long\n",
progname);
goto finished;
}
if (optind != argc - length)
{
fprintf(stderr, "%s: Byte count does not match"
" number of bytes\n", progname);
goto finished;
}
i = 0;
while (optind < argc)
{
contents[i] = strtol(argv[optind], NULL, 16);
i += 1;
optind += 1;
}
}
for (segno = 1; segno <= 255; segno++)
{
struct nw_property segment;
int offset = (segno-1)*128;
if ( offset > length )
{
/* everything written */
break;
}
memcpy(segment.value, &(contents[offset]), 128);
segment.more_flag = segno*128 < length;
if (ncp_write_property_value(conn, object_type,
object_name,
property_name,
segno, &segment) != 0)
{
fprintf(stderr, "%s: Could not write "
"property\n", progname);
goto finished;
}
}
}
result = 0;
finished:
ncp_close(conn);
return result;
}

186
util/nwbpcreate.c Normal file
View File

@@ -0,0 +1,186 @@
/*
* nwbpcreate.c
*
* Create a property for a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object\n"
"-t type Object type (decimal value)\n"
"-p property Name of property to be created\n"
"-s Property is SET, default: ITEM\n"
"-r read-flag Read security\n"
"-w write-flag Write security\n"
"\n");
}
static int
parse_security(const char *security)
{
if (strcasecmp(security, "anyone") == 0)
{
return 0;
}
if (strcasecmp(security, "logged") == 0)
{
return 1;
}
if (strcasecmp(security, "object") == 0)
{
return 2;
}
if (strcasecmp(security, "supervisor") == 0)
{
return 3;
}
if (strcasecmp(security, "netware") == 0)
{
return 4;
}
return -1;
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
char *property_name = NULL;
int property_is_set = 0;
long err;
int read_sec = 1; /* logged read */
int write_sec = 3; /* supervisor write */
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:p:sr:w:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'p':
property_name = optarg;
if (strlen(property_name) > 15)
{
fprintf(stderr, "%s: Property Name too long\n",
argv[0]);
exit(1);
}
str_upper(property_name);
break;
case 's':
property_is_set = 1;
break;
case 'r':
read_sec = parse_security(optarg);
if (read_sec < 0)
{
fprintf(stderr,
"%s: Wrong read security\n"
"Must be one of anyone, logged, "
"object, supervisor or netware\n",
argv[0]);
goto finished;
}
break;
case 'w':
write_sec = parse_security(optarg);
if (write_sec < 0)
{
fprintf(stderr,
"%s: Wrong write security\n"
"Must be one of anyone, logged, "
"object, supervisor or netware\n",
argv[0]);
goto finished;
}
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (property_name == NULL)
{
fprintf(stderr, "%s: You must specify a property name\n",
argv[0]);
goto finished;
}
if (ncp_create_property(conn, object_type, object_name,
property_name,
property_is_set ? 2 : 0,
(write_sec << 4) + read_sec) != 0)
{
fprintf(stderr, "%s: Could not create the property\n",argv[0]);
}
else
{
result = 0;
}
finished:
ncp_close(conn);
return result;
}

125
util/nwbprm.c Normal file
View File

@@ -0,0 +1,125 @@
/*
* nwbprm.c
*
* Delete a property of a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <unistd.h>
#include <stdlib.h>
#include "ncplib.h"
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options] [pattern]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object\n"
"-t type Object type (decimal value)\n"
"-p property Name of property to be deleted\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
char *property_name = NULL;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:p:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'p':
property_name = optarg;
if (strlen(property_name) > 15)
{
fprintf(stderr, "%s: Property Name too long\n",
argv[0]);
exit(1);
}
str_upper(property_name);
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (property_name == NULL)
{
fprintf(stderr, "%s: You must specify a property name\n",
argv[0]);
goto finished;
}
if (ncp_delete_property(conn, object_type, object_name,
property_name) != 0)
{
fprintf(stderr, "%s: Could not delete the property\n",argv[0]);
}
else
{
result = 0;
}
finished:
ncp_close(conn);
return result;
}

261
util/nwbpvalues.c Normal file
View File

@@ -0,0 +1,261 @@
/*
* nwbpvalues.c
*
* List the contents of a SET property of a bindery object on a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
static char *progname;
static void
print_property(char *prop_name, __u8 *val, int segments);
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object\n"
"-t type Object type (decimal value)\n"
"-p property Name of property to be listed\n"
"-v Verbose object listing\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
char *property_name = NULL;
__u8 property_value[255*128];
int segno;
int verbose = 0;
struct nw_property segment;
struct ncp_property_info info;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:p:v")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'p':
property_name = optarg;
if (strlen(property_name) > 15)
{
fprintf(stderr, "%s: Property Name too long\n",
argv[0]);
exit(1);
}
str_upper(property_name);
break;
case 'v':
verbose = 1;
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (property_name == NULL)
{
fprintf(stderr, "%s: You must specify a property name\n",
argv[0]);
goto finished;
}
if (ncp_scan_property(conn, object_type, object_name,
0xffffffff, property_name, &info) != 0)
{
fprintf(stderr, "%s: Could not find property\n", argv[0]);
goto finished;
}
segno = 1;
while (ncp_read_property_value(conn, object_type, object_name,
segno, property_name, &segment) == 0)
{
memcpy(&(property_value[(segno-1)*128]), segment.value, 128);
if ((segment.more_flag == 0) || (segno == 255))
{
break;
}
}
if ((info.property_flags & 2) == 0)
{
print_property(property_name, property_value, segno);
}
else
{
int objects = 32 * segno;
__u32 *value = (__u32 *)property_value;
int i;
for (i = 0; i < objects; i++)
{
struct ncp_bindery_object o;
if ((*value == 0) || (*value == 0xffffffff))
{
break;
}
if (ncp_get_bindery_object_name(conn, ntohl(*value),
&o) == 0)
{
if (verbose != 0)
{
printf("%s %08X %04X\n",
o.object_name,
(unsigned int) o.object_id,
(unsigned int) o.object_type);
}
else
{
printf("%s\n", o.object_name);
}
}
value += 1;
}
}
result = 0;
finished:
ncp_close(conn);
return result;
}
static void
print_unknown(__u8 *val)
{
int j = (128/16);
while (1)
{
int i;
for ( i = 0 ; i < 16 ; i++ )
{
printf ( "%02X " , val[i] );
}
printf ( " [" );
for ( i = 0 ; i < 16 ; i++ )
{
printf ( "%c" , isprint(val[i]) ? val[i] : '.');
}
j -= 1;
if ( j == 0 )
{
printf ( "]\n" );
return;
}
printf ( "]+\n" ) ;
val += 16;
}
}
static void
print_string(__u8 *val)
{
puts(val);
}
static struct {
char *pname ;
void (*func)(__u8 *) ;
} formats[] = {
{ "DESCRIPTION" , print_string } ,
{ "SURNAME" , print_string } ,
{ "OBJECT_CLASS" , print_string } ,
{ "DESCRIPTION" , print_string } ,
{ "IDENTIFICATION" , print_string } ,
{ "Q_DIRECTORY" , print_string } ,
{ NULL , NULL }
};
static void
print_property(char *prop_name, __u8 *val, int segments)
{
int i;
void (*f)(__u8 *);
for (i = 0; formats[i].pname != NULL; i++)
{
if (strcasecmp(prop_name, formats[i].pname) == 0)
{
break;
}
}
f = formats[i].func;
if (f != NULL)
{
f(val);
return;
}
for (i = 0; i < segments; i++)
{
printf("Segment: %03d\n", i+1);
print_unknown(&(val[i*128]));
printf("\n");
}
}

View File

@@ -209,3 +209,131 @@ nw_encrypt(const unsigned char *fra,
}
/*****************************************************************************/
/* */
/* The following code was contributed by */
/* Guntram Blohm <gbl%th7csun1@str.daimler-benz.com> */
/* */
/*****************************************************************************/
/* server side (mars etc.) should:
* store the *encrypted* password internally (output from shuffle)
* verify if nw_encrypt(cryptkey from GetCryptKey, old stored password)
== cryptkey in EncryptedChangePassword request buffer (this means
old password was correct)
* decrypt new password in request buffer using (yet to write) inverse of
newpassencrypt with old stored password as parameter
* compute the length of the unencrypted new password as len ^ (first byte of
old internal password) ^ (second byte of old internal password)
*/
static char
newshuffle[256+16] = {
0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08,
};
/*
* verschluesseln des neuen Passworts fuer keyed change password
* Verwendung:
* - Shuffle (aus nwcrypt.c) altes passwort nach old (16 bytes)
* - shuffle neues passwort nach new (16 bytes)
* - nwpassencrypt (diese Funktion) zweimal aufrufen fuer je 8 bytes:
* nwpassencrypt(old+0, new+0, out+0)
* nwpassencrypt(old+8, new+8, out+8)
* - NCP-Buffer aufbauen:
* 2 byte Laenge im Hi-Lo-Format
* 1 byte Funktion (0x4b)
* 8 byte (nwcrypt Ergebnis analog login/verify password)
* 2 byte Objecttype
* 1 byte Objectname-Laenge
* n byte Objectname
* 1 byte (Laenge des eingegebenen neuen Passworts ^ old[0] ^ old[1])&0x7f|0x40
* 16 byte (Ergebnis dieser Funktion doppelt aufgerufen, s.o.)
*/
/*
* Encrypt the new password for keyed change password
* For info on how to use this function, look at ncp_change_login_passwd
* in ncplib.c.
*/
static void
newpassencrypt(char *old, char *new, char *out)
{
char *p, *bx;
char copy[8];
int i, di, ax;
char cl, dl, ch;
memcpy(copy, new, 8);
for (i=0; i<16; i++)
{
for (di=0, ax=0, p=old; di<8; di++, ax+=0x20, p++)
{
cl=newshuffle[(((copy[di]^*p)>>4)&0x0f)+ax+0x10]<<4;
dl=newshuffle[((copy[di]^*p)&0xf)+ax];
copy[di]=cl|dl;
}
ch=old[7];
for (bx=old+7; bx>old; bx--)
{
*bx=((bx[-1]>>4)&0x0f)|((*bx)<<4);
}
*old=((ch>>4)&0x0f)|(*old)<<4;
memset(out, '\0', 8);
for (di=0; di<16; di++)
{
if (newshuffle[di+0x100]&1)
ch=((copy[newshuffle[di+0x100]/2]>>4)&0x0f);
else
ch=copy[newshuffle[di+0x100]/2]&0x0f;
out[di/2]|=((di&1) ? ch<<4 : ch);
}
memcpy(copy, out, 8);
}
}

133
util/nwgrant.c Normal file
View File

@@ -0,0 +1,133 @@
/*
* nwgrant.c
*
* Add trustee rights to file or directory
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options] file/directory\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object added as trustee\n"
"-t type Object type (decimal value)\n"
"-r rights Rights mask (see manual page)\n"
"\n"
"directory\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
struct ncp_bindery_object o;
int rights = -1;
char *path = NULL;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:r:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'r':
rights = strtol(optarg, NULL, 16);
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (rights < 0)
{
fprintf(stderr, "%s: You must specify a rights mask\n",
progname);
goto finished;
}
if (optind != argc-1)
{
fprintf(stderr, "%s: You must specify a directory\n",
progname);
goto finished;
}
path = argv[optind];
if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0)
{
fprintf(stderr, "%s: Could not find object %s\n",
progname, object_name);
goto finished;
}
if (ncp_add_trustee(conn, 0, path, o.object_id, rights) != 0)
{
fprintf(stderr, "%s: Could not add trustee rights\n",progname);
goto finished;
}
result = 0;
finished:
ncp_close(conn);
return result;
}

View File

@@ -1,62 +0,0 @@
/*
* nwlsobj.c
*
* List bindery objects
*
* 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 o;
int found = 0;
char default_pattern[] = "*";
char *pattern = default_pattern;
char *p;
long err;
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
return 1;
}
if (argc > 2)
{
fprintf(stderr, "usage: %s [options]\n", argv[0]);
return 1;
}
if (argc == 2)
{
pattern = argv[1];
}
for (p = pattern; *p != '\0'; p++)
{
*p = toupper(*p);
}
o.object_id = 0xffffffff;
while (ncp_scan_bindery_object(conn, o.object_id,
0xffff, pattern, &o) == 0)
{
found = 1;
printf("%s %08X %04X\n",
o.object_name, (unsigned int)o.object_id,
(unsigned int)o.object_type);
}
ncp_close(conn);
return 0;
}

View File

@@ -32,6 +32,7 @@ main(int argc, char *argv[])
{
struct ncp_conn *conn;
char message[256];
char *mount_point;
struct ncp_fs_info info;
struct passwd *pwd;
char tty[256];
@@ -53,7 +54,8 @@ main(int argc, char *argv[])
exit(1);
}
if ((conn = ncp_open_mount(argv[1], &err)) == NULL)
mount_point = argv[1];
if ((conn = ncp_open_mount(mount_point, &err)) == NULL)
{
com_err(progname, err, "in ncp_open_mount");
exit(1);
@@ -104,7 +106,7 @@ main(int argc, char *argv[])
while ((mnt = getmntent(mtab)) != NULL)
{
if (strcmp(mnt->mnt_dir, conn->mount_point) == 0)
if (strcmp(mnt->mnt_dir, mount_point) == 0)
{
break;
}

122
util/nwrevoke.c Normal file
View File

@@ -0,0 +1,122 @@
/*
* nwrevoke.c
*
* Remove trustee rights from file or directory
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options] file/directory\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-o object_name Name of object removed as trustee\n"
"-t type Object type (decimal value)\n"
"\n"
"file/directory\n"
"\n");
}
int
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char *object_name = NULL;
int object_type = -1;
struct ncp_bindery_object o;
char *path = NULL;
long err;
int result = 1;
int opt;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
goto finished;
}
while ((opt = getopt(argc, argv, "ho:t:")) != EOF)
{
switch(opt) {
case 'o':
object_name = optarg;
str_upper(object_name);
break;
case 't':
object_type = atoi(optarg);
break;
case 'h':
help();
goto finished;
default:
usage();
goto finished;
}
}
if (object_type < 0)
{
fprintf(stderr, "%s: You must specify an object type\n",
argv[0]);
goto finished;
}
if (object_name == NULL)
{
fprintf(stderr, "%s: You must specify an object name\n",
argv[0]);
goto finished;
}
if (optind != argc-1)
{
fprintf(stderr, "%s: You must specify a directory\n",
progname);
goto finished;
}
path = argv[optind];
if (ncp_get_bindery_object_id(conn, object_type, object_name, &o) != 0)
{
fprintf(stderr, "%s: Could not find object %s\n",
progname, object_name);
goto finished;
}
if (ncp_delete_trustee(conn, 0, path, o.object_id) != 0)
{
fprintf(stderr, "%s: Could not remove trustee rights\n",
progname);
goto finished;
}
result = 0;
finished:
ncp_close(conn);
return result;
}

View File

@@ -41,9 +41,9 @@ main(int argc, char *argv[])
*p = toupper(*p);
}
if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL)
if ((conn = ncp_open(NULL, &err)) == NULL)
{
com_err(argv[0], err, "in ncp_initialize");
com_err(argv[0], err, "in ncp_open");
exit(1);
}