Import ncpfs 0.20

This commit is contained in:
ncpfs archive import
2026-04-28 20:39:58 +02:00
parent 0520c1d2f7
commit 6cb56005ea
12 changed files with 1192 additions and 108 deletions

BIN
.downloads/ncpfs-0.20.tgz Normal file

Binary file not shown.

16
Changes
View File

@@ -1,5 +1,19 @@
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-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 ndt1001@chu.cam.ac.uk (Neil Turton) 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

View File

@@ -2,7 +2,7 @@
# Makefile for the linux ncp-filesystem routines.
#
VERSION = 0.19
VERSION = 0.20
TOPDIR = $(shell pwd)
BINDIR = /usr/local/bin

View File

@@ -275,6 +275,124 @@ 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 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;
}
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 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 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]);
@@ -311,86 +429,6 @@ void handle_ncp (struct sockaddr_ipx *source,
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:
printf("fn: %-3d\n", rq->function);
printf("End of Job\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 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;
default:
printf("fn: %-3d\n", rq->function);
}

View File

@@ -1,4 +1,4 @@
MAN1= slist nprint pqlist nsend pserver
MAN1= slist nprint pqlist nsend pserver ncopy
MAN5= nwclient
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \
ipx_route nwmsg

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.

View File

@@ -1,7 +1,7 @@
Begin3
Title: ncpfs
Version: 0.19
Entered-date: 22. March 1996
Version: 0.20
Entered-date: 25. 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
@@ -11,9 +11,9 @@ Description: With ncpfs you can mount volumes of your netware
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
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
~103k ncpfs-0.19.tgz
~ 1k ncpfs-0.19.lsm
~111k ncpfs-0.20.tgz
~ 1k ncpfs-0.20.lsm
Copying-policy: GPL
End

View File

@@ -2,7 +2,7 @@
# Makefile for the linux ncp-filesystem routines.
#
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy
UIDUTILS = ncpmount ncpumount
SBINUTILS = nwmsg

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

@@ -591,6 +591,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))
@@ -837,9 +839,6 @@ ncp_find_fileserver(const char *server_name, long *err)
return &result;
}
static long
ncp_open_temporary(struct ncp_conn *conn,
const struct ncp_conn_spec *spec)
@@ -887,6 +886,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;
@@ -972,6 +973,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 +1004,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;
@@ -1297,6 +1302,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();
@@ -1500,12 +1507,20 @@ 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, 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)
@@ -1952,8 +1967,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;
}
@@ -2858,9 +2892,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 +2902,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;
}

View File

@@ -168,6 +168,26 @@ long
ncp_scan_bindery_object(struct ncp_conn *conn,
__u32 last_id, __u16 object_type, char *search_string,
struct ncp_bindery_object *target);
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,
@@ -178,6 +198,9 @@ ncp_login_encrypted(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *passwd);
#define NCP_GRACE_PERIOD (0xdf)
long
ncp_login_user(struct ncp_conn *conn,
const unsigned char *username,

View File

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