Import ncpfs 0.20
This commit is contained in:
BIN
.downloads/ncpfs-0.20.tgz
Normal file
BIN
.downloads/ncpfs-0.20.tgz
Normal file
Binary file not shown.
16
Changes
16
Changes
@@ -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
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -2,7 +2,7 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
VERSION = 0.19
|
||||
VERSION = 0.20
|
||||
TOPDIR = $(shell pwd)
|
||||
|
||||
BINDIR = /usr/local/bin
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
96
man/ncopy.1
Normal file
@@ -0,0 +1,96 @@
|
||||
.\"
|
||||
.\" Man page for the ncopy program
|
||||
.\"
|
||||
.TH NCOPY 1 17/03/1996 ncopy ncopy
|
||||
.SH NAME
|
||||
ncopy \- NetWare file copy
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B ncopy -V
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file destinationfile|directory
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file1
|
||||
[
|
||||
.B file2 ...
|
||||
]
|
||||
.B directory
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B ncopy
|
||||
you can copy files to different locations on a single NetWare file
|
||||
server without generating excess network traffic. The program uses
|
||||
a NetWare function to do the copy rather than transferring the file
|
||||
across the network for both the read and write.
|
||||
|
||||
If the last argument is a directory,
|
||||
.B ncopy
|
||||
will copy the source file(s) into the directory. If only two files
|
||||
are given and the last argument is not a directory, it will copy the
|
||||
source file to the destination file.
|
||||
|
||||
If the source and destination files are not on the same NetWare server
|
||||
(or are not on NetWare servers at all),
|
||||
.B ncopy
|
||||
will do a normal file copy.
|
||||
.SH OPTIONS
|
||||
.B -V
|
||||
.RS 3
|
||||
Show version number and exit
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
Verbose copy. Will show current file and percentage completion.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
Nice NetWare copy. Will sleep for a second between copying blocks on
|
||||
the NetWare server. Gives other people a chance to do some work on
|
||||
the NetWare server when you are copying large files. This has no
|
||||
effect if you are not copying on a NetWare server.
|
||||
.RE
|
||||
|
||||
.B -s
|
||||
.I amount
|
||||
.RS 3
|
||||
Nice time slice factor. Used in conjunction with the
|
||||
.B -n
|
||||
option, this specifies the number of 100K blocks to copy before sleeping.
|
||||
Default is 10. (1 Megabyte)
|
||||
.RE
|
||||
|
||||
.SH BUGS
|
||||
.B ncopy
|
||||
cannot recurse into directories.
|
||||
Does not work on NetWare volumes mounted with the
|
||||
.I -V
|
||||
option to
|
||||
.B ncpmount.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.B ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncopy was written by Brian G. Reid (breid@tim.com) and
|
||||
Tom C. Henderson (thenderson@tim.com).
|
||||
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
|
||||
and ncplib which made ncopy possible.
|
||||
@@ -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
|
||||
@@ -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
849
util/ncopy.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user