path expansion
	file copying
	GS/OS error printing (unused)
This commit is contained in:
gdr 1997-10-30 04:57:25 +00:00
parent 68e30dd46a
commit 13a3dc63c3
6 changed files with 702 additions and 9 deletions

View File

@ -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 $@

View File

@ -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 <types.h>
#endif
#ifndef _SYS_TYPES_H_
#include <sys/types.h>
@ -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_ */

437
lib/libcontrib/copyfile.c Normal file
View File

@ -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 <types.h> /* for _toolErr, among others */
#include <errno.h>
#include <gsos.h>
#include <orca.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <gno/gno.h>
#define NDEBUG
#include <assert.h>
#include "contrib.h"
#ifndef MAX
#define MAX(a,b) (((a)>(b)) ? (a) : (b))
#endif
#if 1
#define DEBUG(a)
#else
#include <stdio.h>
#define DEBUG(a) printf a
#endif
/*
* copyfile
*
* copy a file from the pathname <from> to the location <to>, 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 <to> 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
}

128
lib/libcontrib/errnoGS.c Normal file
View File

@ -0,0 +1,128 @@
/*
* $Id: errnoGS.c,v 1.1 1997/10/30 04:57:25 gdr Exp $
*/
#include <gsos.h>
#include <stdarg.h>
#include <stdio.h>
#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;
}

View File

@ -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 <types.h>
#include <gsos.h>
#include <errno.h>
#include <orca.h>
#include <gno/gno.h>
#include "contrib.h"
/*
* expandpath
*
* Uses the GS/OS facilities to expand the pathname <path>. 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;
}
}

View File

@ -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 <errno.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
@ -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
*