From 13a3dc63c35c242cdbe7485012a8b1267cd86e73 Mon Sep 17 00:00:00 2001 From: gdr Date: Thu, 30 Oct 1997 04:57:25 +0000 Subject: [PATCH] added: path expansion file copying GS/OS error printing (unused) --- lib/libcontrib/Makefile | 6 +- lib/libcontrib/contrib.h | 35 ++- lib/libcontrib/copyfile.c | 437 ++++++++++++++++++++++++++++++++++++ lib/libcontrib/errnoGS.c | 128 +++++++++++ lib/libcontrib/expandpath.c | 90 ++++++++ lib/libcontrib/strarray.c | 15 +- 6 files changed, 702 insertions(+), 9 deletions(-) create mode 100644 lib/libcontrib/copyfile.c create mode 100644 lib/libcontrib/errnoGS.c create mode 100644 lib/libcontrib/expandpath.c diff --git a/lib/libcontrib/Makefile b/lib/libcontrib/Makefile index 721a4d4..8548cf4 100644 --- a/lib/libcontrib/Makefile +++ b/lib/libcontrib/Makefile @@ -1,19 +1,19 @@ # # This is the top-level makefile for libcontrib, GNO v2.0.6 # -# $Id: Makefile,v 1.1 1997/10/03 04:49:40 gdr Exp $ +# $Id: Makefile,v 1.2 1997/10/30 04:57:24 gdr Exp $ # .INCLUDE: ../../paths.mk .INCLUDE: ../const.mk LIB = libcontrib -OBJS = strarray.o xalloc.o +OBJS = copyfile.o expandpath.o strarray.o xalloc.o HEADER = contrib.h LIBDIR = $(RELEASE_DIR)/usr/lib INCDIR = $(RELEASE_DIR)/usr/include/gno -CFLAGS += -I. -O78 +CFLAGS += -I. -O78 -Slibcontrib $(LIB): $(OBJS) $(LIB).r $(RM) -f $@ diff --git a/lib/libcontrib/contrib.h b/lib/libcontrib/contrib.h index 9dd5aec..414d501 100644 --- a/lib/libcontrib/contrib.h +++ b/lib/libcontrib/contrib.h @@ -1,9 +1,13 @@ /* - * $Id: contrib.h,v 1.1 1997/10/03 04:49:40 gdr Exp $ + * $Id: contrib.h,v 1.2 1997/10/30 04:57:24 gdr Exp $ */ -#ifndef _CONTRIB_H_ -#define _CONTRIB_H_ +#ifndef _GNO_CONTRIB_H_ +#define _GNO_CONTRIB_H_ + +#ifndef __TYPES__ +#include +#endif #ifndef _SYS_TYPES_H_ #include @@ -34,7 +38,30 @@ typedef struct LC_StringArrayElem_t { LC_StringArray_t LC_StringArrayNew __P((void)); void LC_StringArrayAdd __P((LC_StringArray_t, char *)); void LC_StringArrayDelete __P((LC_StringArray_t, char *)); +void LC_StringArrayDestroy __P((LC_StringArray_t)); void LC_StringArrayClear __P((LC_StringArray_t)); char * LC_StringArrayCat __P((LC_StringArray_t, int)); -#endif /* _CONTRIB_H_ */ +/* + * File copy operations + */ + +#define LC_COPY_DATA 0x0001 /* copy the data fork? */ +#define LC_COPY_REZ 0x0002 /* copy the resource fork? */ +#define LC_COPY_KEEPBUF 0x0004 /* keep the internally allocated buffer? */ +#define LC_COPY_BACKUP 0x0008 /* set the backup bit? */ + +#define LC_COPY_FORKS_MASK 0x0003 + +GSStringPtr LC_CopyFileGS __P((GSStringPtr from, GSStringPtr to, + unsigned short flags)); +char * LC_CopyFile __P((const char *, const char *, unsigned short)); + +/* + * Filename expansion + */ + +GSStringPtr LC_ExpandPathGS __P((GSStringPtr path)); +char * LC_ExpandPath __P((char *path)); + +#endif /* _GNO_CONTRIB_H_ */ diff --git a/lib/libcontrib/copyfile.c b/lib/libcontrib/copyfile.c new file mode 100644 index 0000000..8cf9e05 --- /dev/null +++ b/lib/libcontrib/copyfile.c @@ -0,0 +1,437 @@ +/* + * $Id: copyfile.c,v 1.1 1997/10/30 04:57:25 gdr Exp $ + */ + +/* Change the arg types of GS/OS parameter blocks. Must be before #includes */ +#define __USE_DYNAMIC_GSSTRING__ + +#include /* for _toolErr, among others */ +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#include "contrib.h" + +#ifndef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +#if 1 +#define DEBUG(a) +#else +#include +#define DEBUG(a) printf a +#endif + +/* + * copyfile + * + * copy a file from the pathname to the location , which + * may be a directory. Ensure that file types and other information + * (except for the backup bit) is matched. + * + * Returns NULL and sets errno on failure. On success, returns a + * pointer to an internal buffer containing the final pathname. + * + * Possible errnos: + * EINVAL Neither the LC_COPY_DATA nor the LC_COPY_REZ + * flags were set. + * + * ENOMEM Ran out of memory. + * + * ENOENT A request was made to copy only the resource + * fork, but the file does not have a resource fork. + * + * (any errno returned from ExpandPathGS, GetFileInfoGS, DestroyGS, + * CreateGS, OpenGS, CloseGS, SetFileInfoGS) + * + * +++ THIS ROUTINE IS NOT REENTRANT +++ + */ + +#define NAMELEN_QUANTUM 256 + +GSStringPtr +LC_CopyFileGS (GSStringPtr from, GSStringPtr to, unsigned short flags) +{ + static ResultBufPtr expandedFrom = NULL; + static size_t expandedFromLen = 0; + static ResultBufPtr expandedTo = NULL; + static size_t expandedToLen = 0; + static char * buffer = NULL; + static size_t bufferLen = 0; + static ExpandPathRecGS expandrec; + static FileInfoRecGS inforec; + static OpenRecGS openrec; + static struct { + Word pCount; + Word refNum; + Longword dataBuffer; + Longword requestCount; + Longword transferCount; + Word cachePriority; + } iobuf; + static struct { + Word pCount; + Word refNum; + } closerec; + + ResultBufPtr rbp; + GSStringPtr gsp; + size_t newlen; + int done, i, j, k, isDir, exists; + char *p, *q; + Word refNumIn, refNumOut, oldAccess; + + /* concheck */ + if ((flags & (LC_COPY_DATA | LC_COPY_REZ)) == 0) { + errno = EINVAL; + return NULL; + } + + /* + * First time through? We have to allocate our buffer. Try + * 64k to start, then keep dividing by 2 until we can allocate + * one successfully. Don't bother with anything less that 1k, + * just return an error. + */ + if (buffer == NULL) { + newlen = 128; /* we'll divide this at least once */ + do { + newlen /= 2; + if (newlen <= 1) { + errno = ENOMEM; + return NULL; + } + buffer = malloc(newlen * 1024); + } while (buffer == NULL); + bufferLen = newlen * 1024; + + /* do some other initializations */ + expandrec.pCount = 3; + } + + /* + * Initialize the name result buffers, growing them if necessary. + */ + for (i=0; i<2; i++) { + switch (i) { + case 0: + gsp = from; + rbp = expandedFrom; + newlen = expandedFromLen; + break; + case 1: + gsp = to; + rbp = expandedTo; + newlen = expandedToLen; + break; + } + done = 0; + + if (newlen < gsp->length) { + while (newlen < gsp->length) { + newlen += NAMELEN_QUANTUM; + } + rbp = GOchange(rbp, newlen, NULL); + if (rbp == NULL) { + return NULL; + } + } + while (!done) { + expandrec.inputPath = gsp; + expandrec.outputPath = rbp; + expandrec.flags = 0x0000; + ExpandPathGS(&expandrec); + switch ((j = _toolErr)) { + case 0: + /* NULL-terminate it */ + (rbp->bufString.text)[rbp->bufString.length] + = '\0'; + done = 1; + break; + case buffTooSmall: + newlen += NAMELEN_QUANTUM; + rbp = GOchange(rbp, newlen, NULL); + if (rbp == NULL) { + done = 1; + newlen -= NAMELEN_QUANTUM; + errno = ENOMEM; + /* + * we delay the return until after + * the next switch statement so that + * we can reset the static variables. + */ + } + break; + default: + errno = _mapErr(j); + return NULL; + } + } + switch(i) { + case 0: + expandedFrom = rbp; + expandedFromLen = newlen; + break; + case 1: + expandedTo = rbp; + expandedToLen = newlen; + break; + } + if (rbp == NULL) { + return NULL; + } + } + + /* find out if is a directory */ + inforec.pCount = 5; + inforec.pathname = &(expandedTo->bufString); + GetFileInfoGS(&inforec); + i = _toolErr; + switch(i) { + case 0: + exists = 1; + isDir = ((inforec.storageType == 0x0D) || + (inforec.storageType == 0x0F)) ? 1 : 0; + break; + case fileNotFound: + exists = 0; + isDir = 0; + break; + default: + errno = _mapErr(i); + return NULL; + } + + /* it's a directory? tack on the file name */ + if (isDir) { + /* we know that the text field is null-terminated */ + p = expandedFrom->bufString.text + + expandedFrom->bufString.length; + if (p != expandedFrom->bufString.text) { + --p; + } + /* p now points to the last legal char in the input name */ + i = 0; + assert(*p != ':'); + q = expandedFrom->bufString.text; + while ((p > q) && (*p != ':')) { + --p; + i++; + } + if (*p == ':') { + p++; + } + /* + * p now points to the basename of expandedFrom and + * i is the length of that basename + */ + + /* grow the resultbuf if necessary */ + if (expandedTo->bufString.length + i + 1 > + expandedTo->bufSize) { + rbp = GOchange(expandedTo, expandedTo->bufString.length + + 1 + MAX(i, NAMELEN_QUANTUM), NULL); + if (rbp == NULL) { + errno = ENOMEM; + return NULL; + } + expandedTo = rbp; + } + + /* copy the basename over */ + q = expandedTo->bufString.text + expandedTo->bufString.length; + *q++ = ':'; + memcpy(q, p, i+1); /* one for the term */ + expandedTo->bufString.length += i + 1; /* one for the ':' */ + } + + /* check to see it's not the same file */ + if (!strcmp(expandedFrom->bufString.text, expandedTo->bufString.text)) { + errno = EINVAL; + return NULL; + } + + /* get the file info of the original file */ + inforec.pCount = 7; + inforec.pathname = &(expandedFrom->bufString); + GetFileInfoGS(&inforec); + if ((i = _toolErr) != 0) { + errno = _mapErr(i); + return NULL; + } + oldAccess = inforec.access; + + if (((flags & LC_COPY_FORKS_MASK) == LC_COPY_REZ) && + (inforec.storageType == extendedFile)) { + errno = ENOENT; + return NULL; + } + + /* destroy the old target file if it exists and is not a directory */ + inforec.pCount = 1; + inforec.pathname = &(expandedTo->bufString); + DestroyGS(&inforec); + i = _toolErr; + switch(i) { + case 0: + case fileNotFound: + break; + default: + errno = _mapErr(i); + return NULL; + } + +DEBUG(("creating %s\n", expandedTo->bufString.text)); + /* create the new file */ + inforec.pCount = 5; + inforec.pathname = &(expandedTo->bufString); + inforec.access = 0x00c3; + CreateGS(&inforec); + if ((i = _toolErr) != 0) { + errno = _mapErr(i); + return NULL; + } + +DEBUG(("copying file\n")); + /* copy both forks, if necessary */ + for (i=0; i<2; i++) { + + switch (i) { + case 0: + if ((flags & LC_COPY_DATA) == 0) { + continue; + } + openrec.resourceNumber = 0x0000; + break; + case 1: + if ((inforec.storageType != extendedFile) || + ((flags & LC_COPY_REZ) == 0)) { + continue; + } + openrec.resourceNumber = 0x0001; + break; + } + + /* open the input file */ + openrec.pCount = 4; + openrec.pathname = &(expandedFrom->bufString); + openrec.requestAccess = readEnable; + OpenGS(&openrec); + if ((j = _toolErr) != 0) { + errno = _mapErr(j); + return NULL; + } + refNumIn = openrec.refNum; + + /* open the output file */ + openrec.pathname = &(expandedTo->bufString); + openrec.requestAccess = writeEnable; + OpenGS(&openrec); + if ((j = _toolErr) != 0) { + closerec.pCount = 1; + closerec.refNum = refNumIn; + CloseGS(&closerec); + errno = _mapErr(j); + return NULL; + } + refNumOut = openrec.refNum; + + /* transfer the data */ + done = 0; + iobuf.pCount = 5; + iobuf.dataBuffer = (Longword) buffer; + iobuf.cachePriority = cacheOn; + while (!done) { + + iobuf.refNum = refNumIn; + iobuf.requestCount = bufferLen; + ReadGS(&iobuf); + k = _toolErr; + switch (k) { + case 0: + break; + case eofEncountered: + k = 0; /* no error condition */ + done = 1; + break; + default: + /* leave k set as the error condition */ + done = 1; + continue; + } + + iobuf.refNum = refNumOut; + iobuf.requestCount = iobuf.transferCount; + WriteGS(&iobuf); + if ((k = _toolErr) != 0) { + /* leave k set as the error condition */ + done = 1; + } + } /* end loop over buffering */ + + closerec.pCount = 1; + closerec.refNum = refNumIn; + CloseGS(&closerec); + closerec.refNum = refNumOut; + CloseGS(&closerec); + if (k != 0) { + /* ending I/O before EOF is encountered? */ + errno = _mapErr(k); + return NULL; + } + } /* end loop over forks */ + +DEBUG(("setting file info\n")); + + /* set file information to match original file */ + inforec.pCount = 7; + inforec.pathname = &(expandedTo->bufString); + inforec.access = oldAccess; + SetFileInfoGS(&inforec); + if ((i = _toolErr) != 0) { + errno = _mapErr(i); + return NULL; + } + + return &(expandedTo->bufString); +} + +char * +LC_CopyFile (char *from, char *to, unsigned short flags) +{ + GSStringPtr fromGS, toGS, result; + int e; + + if ((fromGS = __C2GSMALLOC(from)) == NULL) { + return NULL; + } + if ((toGS = __C2GSMALLOC(to)) == NULL) { + e = errno; + GIfree(fromGS); + errno = e; + return NULL; + } + result = LC_CopyFileGS (fromGS, toGS, flags); + e = errno; + GIfree(fromGS); + GIfree(toGS); + errno = e; +#if 1 + /* get around a bug in ORCA/C v2.1.0 (reported) */ + if (result == NULL) { + return NULL; + } else { + return result->text; + } +#else + return (result == NULL) ? NULL : result->text; +#endif +} diff --git a/lib/libcontrib/errnoGS.c b/lib/libcontrib/errnoGS.c new file mode 100644 index 0000000..5f75d8e --- /dev/null +++ b/lib/libcontrib/errnoGS.c @@ -0,0 +1,128 @@ +/* + * $Id: errnoGS.c,v 1.1 1997/10/30 04:57:25 gdr Exp $ + */ + +#include +#include +#include +#include "contrib.h" + +#pragma lint -1 +#pragma debug 0 +#pragma optimize 78 + +#define NONE "no error" +#define UNKNOWN "unknown error" + +#ifdef __ORCAC__ +segment "errnoGS___"; +#endif + +typedef struct errEntry { + unsigned short num; + char *str; +} errEntry; + +static errEntry +sys_errlistGS[] = { + { badSystemCall, "bad system call number" }, + { invalidPcount, "invalid parameter count" }, + { gsosActive, "GS/OS already active" }, + { devNotFound, "device not found" }, + { invalidDevNum, "invalid device number" }, + { drvrBadReq, "bad request or command" }, + { drvrBadCode, "bad control or status code" }, + { drvrBadParm, "bad call parameter" }, + { drvrNotOpen, "character device not open" }, + { drvrPriorOpen, "character device already open" }, + { irqTableFull, "interrupt table full" }, + { drvrNoResrc, "resources not available" }, + { drvrIOError, "I/O error" }, + { drvrNoDevice, "device not connected" }, + { drvrBusy, "call aborted; driver is busy" }, + { drvrWrtProt, "device is write protected" }, + { drvrBadCount, "invalid byte count" }, + { drvrBadBlock, "invalid block address" }, + { drvrDiskSwitch, "disk has been switched" }, + { drvrOffLine, "device off line/ no media present" }, + { badPathSyntax, "invalid pathname syntax" }, + { tooManyFilesOpen, "too many files open on server volume" }, + { invalidRefNum, "invalid reference number" }, + { pathNotFound, "subdirectory does not exist" }, + { volNotFound, "volume not found" }, + { fileNotFound, "file not found" }, + { dupPathname, "create or rename with existing name" }, + { volumeFull, "volume full error" }, + { volDirFull, "volume directory full" }, + { badFileFormat, "version error (incompatible file format)" }, + { badStoreType, "unsupported (or incorrect) storage type" }, + { eofEncountered, "end-of-file encountered" }, + { outOfRange, "position out of range" }, + { invalidAccess, "access not allowed" }, + { buffTooSmall, "buffer too small" }, + { fileBusy, "file is already open" }, + { dirError, "directory error" }, + { unknownVol, "unknown volume type" }, + { paramRangeErr, "parameter out of range" }, + { outOfMem, "out of memory" }, + { dupVolume, "duplicate volume name" }, + { notBlockDev, "not a block device" }, + { invalidLevel, "specifield level outside legal range" }, + { damagedBitMap, "block number too large" }, + { badPathNames, "invalid pathnames for ChangePath" }, + { notSystemFile, "not an executable file" }, + { osUnsupported, "Operating System not supported" }, + { stackOverflow, "too many applications on stack" }, + { dataUnavail, "data unavailable" }, + { endOfDir, "end of directory has been reached" }, + { invalidClass, "invalid FST call class" }, + { resForkNotFound, "file does not contain required resource" }, + { invalidFSTID, "error - FST ID is invalid" }, + { invalidFSTop, "invalid FST operation" }, + { fstCaution, "FST handled call, but result is weird" }, + { devNameErr, "device exists with same name as replacement name" }, + { defListFull, "device list is full" }, + { supListFull, "supervisor list is full" }, + { fstError, "generic FST error" }, + { resExistsErr, "cannot expand file, resource already exists" }, + { resAddErr, "cannot add resource fork to this type file" }, + { networkError, "generic network error" }, + { 0, NONE } /* we shouldn't see this */ +}; + +unsigned short errnoGS = 0; + +char * +strerrorGS(unsigned short num) +{ + int i; + + if (num == 0) { + return NONE; + } + i = 0; + while (sys_errlistGS[i].num) { + if (sys_errlistGS[i].num == num) { + return sys_errlistGS[i].str; + } + i++; + } + return UNKNOWN; +} + +#ifdef __ORCAC__ +#pragma debug 0 +#pragma optimize 78 +#endif + +void +perrorGS(char *format, ...) +{ + va_list ap; + + va_start(ap,format); + vfprintf(stderr,format,ap); + fprintf(stderr,": %s\n",strerrorGS(errnoGS)); + va_end(ap); + return; +} diff --git a/lib/libcontrib/expandpath.c b/lib/libcontrib/expandpath.c new file mode 100644 index 0000000..1be6138 --- /dev/null +++ b/lib/libcontrib/expandpath.c @@ -0,0 +1,90 @@ +/* + * $Id: expandpath.c,v 1.1 1997/10/30 04:57:25 gdr Exp $ + */ + +/* Change the arg types of GS/OS parameter blocks. Must be before #includes */ +#define __USE_DYNAMIC_GSSTRING__ + +#include +#include +#include +#include +#include +#include "contrib.h" + +/* + * expandpath + * + * Uses the GS/OS facilities to expand the pathname . On + * success, returns a pointer to the malloc'd expanded path. On + * failure it will return NULL and set errno. + * + * Note that in using this function, all directory separators will + * be converted to colons. + * + * *********** THIS ROUTINE IS NOT REENTRANT ************** + */ + +#define OUTBUF_QUANTUM 255 + +GSStringPtr +LC_ExpandPathGS (GSStringPtr path) +{ + static ExpandPathRecGS expand; + static ResultBufPtr outBuf = NULL; + static int outBufSize = 0; + int i; + + expand.pCount = 2; + expand.inputPath = path; + expand.flags = 0x0000; + if (outBuf == NULL) { + outBufSize += OUTBUF_QUANTUM; + outBuf = GOinit(outBufSize, NULL); + if (outBuf == NULL) { + errno = ENOMEM; + return NULL; + } + } + for(;;) { + expand.outputPath = outBuf; + ExpandPathGS(&expand); + switch (_toolErr) { + case 0: + /* NULL-terminate it and return */ + (outBuf->bufString.text)[outBuf->bufString.length] + = '\0'; + return &(outBuf->bufString); + break; + case buffTooSmall: + break; + default: + errno = _mapErr(_toolErr); + return NULL; + } + /* if we got here, the buffer wasn't large enough */ + + outBufSize += OUTBUF_QUANTUM; + outBuf = GOchange(outBuf, outBufSize, NULL); + } +} + +char * +LC_ExpandPath (char *path) +{ + GSStringPtr inStr, result; + int e; + + if ((inStr = __C2GSMALLOC(path)) == NULL) { + return NULL; + } + result = LC_ExpandPathGS(inStr); + e = errno; + GIfree(inStr); + errno = e; + if (result) { + return result->text; + } else { + return NULL; + } +} diff --git a/lib/libcontrib/strarray.c b/lib/libcontrib/strarray.c index 4f51b85..3dcd058 100644 --- a/lib/libcontrib/strarray.c +++ b/lib/libcontrib/strarray.c @@ -5,8 +5,9 @@ * * Devin Reade, September 1997. * - * $Id: strarray.c,v 1.1 1997/10/03 04:49:40 gdr Exp $ + * $Id: strarray.c,v 1.2 1997/10/30 04:57:25 gdr Exp $ */ +#include #include #include #include @@ -123,7 +124,11 @@ LC_StringArrayDelete (LC_StringArray_t array, char *str) { void LC_StringArrayClear (LC_StringArray_t array) { int i; - + + if (array == NULL) { + errno = EINVAL; + err(1, "LC_StringArrayClear passed NULL pointer"); + } if (array->lc_used == 0) { return; } @@ -140,6 +145,12 @@ LC_StringArrayClear (LC_StringArray_t array) { return; } +void +LC_StringArrayDestroy (LC_StringArray_t array) { + LC_StringArrayClear(array); + free(array); +} + /* * LC_StringArrayCat *