jac@yoko.rutgers.edu (Jonathan A. Chandross) (05/02/91)
Submitted-by: Andy McFadden (fadden@cory.berkeley.edu) Posting-number: Volume 1, Source:36 Archive-name: archive/unix/nulib/part05.10 Architecture: UNIX Version-number: 3.03 =nuetc.c -/* - * nuetc.c - extra stuff; most is #ifdefed to death (mostly time routines - * and file stuff that are highly system dependent) - * - * NuLib v3.0 February 1991 Freeware (distribute, don't sell) - * By Andy McFadden (fadden@cory.berkeley.edu) - */ -#ifdef APW -segment "NuMain" -#endif - -#include "nudefs.h" -#include <stdio.h> -#include <fcntl.h> -#include <errno.h> /* errno declarations */ -#include <ctype.h> /* for tolower(), isupper() */ - -#ifdef UNIX -# include <time.h> /* need localtime() */ -# include <sys/types.h> /* defn of time_t */ -# include <sys/stat.h> -#endif -#ifdef APW -# include <stdlib.h> /* exit(), etc. */ -# include <types.h> /* has _toolErr in it */ -# include <prodos.h> -# include "apwerr.h" /* APW/ProDOS error codes */ -#endif -#ifdef MSDOS -# include <process.h> -# include <stdlib.h> -# include <io.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <time.h> -#endif - -#include "nuetc.h" -/* note "nuread.h" is not included... none of the routines here assume */ -/* any knowledge of NuFX archives. */ - -#ifndef MSDOS -extern char *malloc(); /* all systems ... except DOS : RBH */ -#endif /* +PORT+ */ - -extern void free(); -extern char *getenv(); -#ifdef APW -extern Time ReadTimeHex(); /* should be TimeRec, from misctool.h */ -#endif - -/* This is a generally available TEMPORARY filename buffer */ -char tmpNameBuf[MAXFILENAME]; - - -/******************** general misc routines ********************/ - -/* - * Fatal error handler - */ -void Fatal(deathstr, procName) -char *deathstr, *procName; -{ - fflush(stdout); - fprintf(stderr, "\n%s: fatal error: %s\n--- ", prgName, deathstr); - perror(procName); - Quit (-1); -} - - -/* - * Quit can be used to perform cleanup operations before exiting. - */ -void Quit(val) -int val; -{ - exit(val); -} - - -/* - * Safe malloc()... checks return value - */ -char *Malloc(size) -int size; -{ - char *ptr = (char *) malloc(size); - - if (ptr != (char *) NULL) { - return(ptr); - } else { - /* 8910.31 - RBH: report byte size that failed */ - printf("Malloc: memory alloc error [%u : bytes]\n", size); -#ifdef MSDOS - printf("(Largest Available Block: %u)\n", _memmax()); -#endif - Quit (-1); - } -} - -/******************** UNIX compatibility routines ********************/ - -#ifdef UNIX -/* - * Convert expanded date to a number of seconds for UNIX systems. - * - * Remember that *atime follows the NuFX docs for time values, which - * don't necessarily match those in UNIX manual pages. - * Adapted from _Advanced UNIX Programming_ by Marc J. Rochkind. - * - * Returns 0 if date/time is invalid. - */ -long timecvt(atime) -Time *atime; -{ - long tm; - int days; - BOOLEAN isleapyear; - int tzone; - char *getenv(), *tz; - - if ((tz = getenv("TZ")) == NULL) - tzone = 8; /* pacific std time */ - else - tzone = atoi(&tz[3]); - - isleapyear = (atime->year != 0) && (atime->year%4 == 0); /* 2000 isn't */ - if (atime->year < 70) - atime->year += 100; /* years after 2000 */ - days = (atime->year - 70) * 365L; - days += ((atime->year - 69L) / 4); /* previous years' leap days */ - - switch (atime->month +1) { /* month is 0-11 */ - case 12: - days += 30; /* Nov */ - case 11: - days += 31; /* Oct */ - case 10: - days += 30; /* Sep */ - case 9: - days += 31; /* Aug */ - case 8: - days += 31; /* Jul */ - case 7: - days += 30; /* Jun */ - case 6: - days += 31; /* May */ - case 5: - days += 30; /* Apr */ - case 4: - days += 31; /* Mar */ - case 3: - days += (isleapyear ? 29 : 28); /* Feb */ - case 2: - days += 31; /* Jan */ - case 1: - break; - default: - /*printf("Invalid month\n");*/ - return (0L); - } - - if (atime->day > 31) { - /*printf("Invalid day\n");*/ - return (0L); - } - tm = (days + atime->day) * 24L * 60L * 60L; - - if (atime->hour > 23) { - /*printf("Invalid hour\n");*/ - return (0L); - } - atime->hour += tzone; /* correct for time zone */ - tm += atime->hour * 60L * 60L; - - if (atime->minute > 59) { - /*printf("Invalid minute\n");*/ - return (0L); - } - tm += atime->minute * 60L; - - if (atime->second > 59) { - /*printf("Invalid second\n");*/ - return (0L); - } - tm += atime->second; - - if (localtime(&tm)->tm_isdst) /* was that day in dst? */ - tm -= 60L * 60L; /* adjust for daylight savings */ - return (tm); -} -#endif /* UNIX */ - -/******************** APW compatibility routines ********************/ - -#ifdef APW -/* - * Normally a C library function to print out a description of the most - * recent system (non-toolbox, non-ProDOS) error. Exists under UNIX and - * MS C 5.1, so I'm assuming it exists most everywhere else... - */ -void perror(errstr) -char *errstr; -{ - fflush(stdout); - if ( (errno > 0) && (errno < sys_nerr) ) { /* known APW error? */ - fprintf(stderr, "%s: %s\n", errstr, sys_errlist[errno]); - } else { - fprintf(stderr, "%s: ", errstr); - fflush(stderr); - ERROR( errno ); - } - Quit (-1); -} - - -/* Check for //gs toolbox errors; all are fatal */ -void ToolErrChk() -{ - int err = _toolErr; - - if (err) { - if (err < MPErr) { /* was a ProDOS error? */ - fprintf(stderr, "Error: $%.2x %s\n", (char) err, - ProDOSErr[err]); - } else { - fprintf(stderr, "Tool err ($%.4x): ", err); - fflush(stderr); - ERROR( err ); - } - Quit (-1); - } -} - -#endif /* APW */ - -/******************** miscellaneous string routines ********************/ - -/* - * Compare strings, ignoring case (may be in standard C lib; stricmp()?) - */ -int strcasecmp(str1, str2) -register char *str1, *str2; -{ - register char one, two; - register int val; - - for ( ; *str1 && *str2; str1++, str2++) { - one = (isupper(*str1) ? tolower(*str1) : *str1); - two = (isupper(*str2) ? tolower(*str2) : *str2); - if (val = two - one) - return (val); - } - if (!(*str1) && !(*str2)) /* both zero -> equivalent */ - return (0); - else { /* one is shorter; return result */ - one = (isupper(*str1) ? tolower(*str1) : *str1); - two = (isupper(*str2) ? tolower(*str2) : *str2); - return (two - one); - } -} - -int strncasecmp(str1, str2, num) -register char *str1, *str2; -int num; -{ - register int i; - register char one, two; - register int val; /* keep going 'til no more registers... */ - - for (i = 0; (i < num) && (*str1) && (*str2); i++, str1++, str2++) { - one = (isupper(*str1) ? tolower(*str1) : *str1); - two = (isupper(*str2) ? tolower(*str2) : *str2); - if (val = two - one) - return (val); - } - if (i == num) /* first num characters are equal, so return zero */ - return (0); - else { /* one ended early; return result */ - one = (isupper(*str1) ? tolower(*str1) : *str1); - two = (isupper(*str2) ? tolower(*str2) : *str2); - return (two - one); - } -} - -/******************* file-related routines ********************/ - -/* - * Do operating system-dependent CREATE stuff - * - * Creates a NuFX archive file, with type info where necessary. - * Does not leave file open. - */ -void ArcfiCreate(filename) -char *filename; -{ - static char *procName = "ArcfiCreate"; -#ifdef UNIX - int fd; - - if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0) - Fatal("Unable to create file", procName); - close(fd); -#else -# ifdef APW - FileRec create_p; - - c2pstr(filename); - create_p.pathname = filename; - create_p.fAccess = 0x00e3; - create_p.fileType = 0x00e0; /* LBR */ - create_p.auxType = 0x8002; /* SHK */ - create_p.storageType = 0x0001; - create_p.createDate = 0x0000; /* let ProDOS fill in the blanks */ - create_p.createTime = 0x0000; - CREATE( &create_p ); - ToolErrChk(); - p2cstr(filename); -# endif /* APW */ -# ifdef MSDOS - int fd; - - if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0) - Fatal("Unable to create file", procName); - close(fd); -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - int fd; - - if ((fd = open(filename, O_CREAT|O_RDWR, WPERMS)) < 0) - Fatal("Unable to create file", procName); - close(fd); -# endif /* none2 */ -# endif /* none1 */ -#endif /* UNIX */ -} - - -/* - * Determine if a file already exists. - */ -BOOLEAN Exists(filename) -char *filename; -{ - static char *procName = "Exists"; -#ifdef UNIX - struct stat sm; - - if (stat(filename, &sm) < 0) { - if (errno == ENOENT) /* if doesn't exist, then okay */ - return (FALSE); - else /* some other problem killed stat(), probably serious */ - fprintf(stderr, "Unable to stat() '%s'\n", filename); - Fatal("Bad stat()", procName); /*serious prob*/ - } else /* successful call - file exists */ - return (TRUE); -#else -# ifdef APW - FileRec info_p; /* check if file exists, is dir */ - int err; - - c2pstr(filename); - info_p.pathname = filename; - GET_FILE_INFO( &info_p ); - err = _toolErr; - p2cstr(filename); - if (err == pathNotFound || err == fileNotFound) - return (FALSE); - else if (!err) - return (TRUE); - else { - _toolErr = err; - ToolErrChk(); - return (TRUE); - } -# endif /* APW */ -# ifdef MSDOS - struct stat sm; - - if (stat(filename, &sm) < 0) { - if (errno == ENOENT) /* if doesn't exist, then okay */ - return (FALSE); - else /* some other problem killed stat(), probably serious */ - fprintf(stderr, "Unable to stat() '%s'\n", filename); - Fatal("Bad stat()", procName); /*serious prob*/ - } else /* successful call - file exists */ - return (TRUE); -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - printf("Need [other] Exists()\n"); /* +PORT+ */ - return (FALSE); -# endif /* none2 */ -# endif /* none1 */ -#endif /* UNIX */ -} - - -/* - * Generate a temporary file name (system dependent). - * Assumes space is allocated for buffer. - */ -char *MakeTemp(buffer) -char *buffer; -{ - static char *procName = "MakeTemp"; -#ifdef UNIX - extern char *mktemp(); - - strcpy(buffer, "nulb.tmpXXXXXX"); - return (mktemp(buffer)); -#else -# ifdef APW - int idx = 0; - - do { - sprintf(buffer, "nulb.tmp%d", idx++); - } while (Exists(buffer)); - return (buffer); -# endif /* APW */ -# ifdef MSDOS - extern char *mktemp(); - - strcpy(buffer, "nulbXXXX.tmp"); - return (mktemp(buffer)); -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - strcpy(buffer, "nulb.tmp"); /* +PORT+ */ - return (buffer); -# endif /* none2 */ -# endif /* none1 */ -#endif /* UNIX */ -} - -#ifdef NO_RENAME -/* - * This is a replacement for the library call, in case somebody's C library - * doesn't have it. - */ -int rename(fromname, toname) -{ - if (link(fromname, toname) < 0) - return (-1); - if (unlink(fromname) < 0) - return (-1); -} -#endif - - -/* - * Rename a file. - */ -void Rename(fromname, toname) -char *fromname, *toname; -{ - static char *procName = "Rename"; -#ifdef UNIX - if (Exists(toname)) { - fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n", - prgName, fromname, toname); - fflush(stderr); - } -# ifdef AOSVS /* BAK 04/30/90 */ - printf("Work on AOS/VS rename command\n"); /* BAK 04/30/90 */ -# else /* BAK 04/30/90 */ - else { - if (rename(fromname, toname) < 0) { /* this should "never" fail */ - fprintf(stderr, - "\n%s: WARNING: Unable to rename '%s' as '%s'\n", - prgName, fromname, toname); - Fatal("Bad rename()", procName); /*serious prob*/ - } - } -# endif -#else -# ifdef APW - PathNameRec cpath_p; - - if (Exists(toname)) { - fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n", - prgName, fromname, toname); - fflush(stderr); - return; - } - - cpath_p.pathname = fromname; - cpath_p.newPathname = toname; - c2pstr(fromname); - c2pstr(toname); - CHANGE_PATH( &cpath_p ); - ToolErrChk(); - p2cstr(fromname); - p2cstr(toname); -# endif /* APW */ -# ifdef MSDOS - if (Exists(toname)) { - fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n", - prgName, fromname, toname); - fflush(stderr); - return; - } - printf("Work on MSDOS rename command\n"); -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - if (Exists(toname)) { - fprintf(stderr, "\n%s: WARNING: Unable to rename '%s' as '%s'\n", - prgName, fromname, toname); - fflush(stderr); - return; - } - printf("Need [other] rename command\n"); /* +PORT+ */ -# endif /* none2 */ -# endif /* none1 */ -#endif /*UNIX*/ -} - -/******************** date/time routines ********************/ - -/* - * Expand date/time from file-sys dependent format to eight byte NuFX format. - * tptr is filesys format, TimePtr is NuFX format - */ -void ExpandTime(tptr, TimePtr) /* (BSD) UNIX version */ -onebyt *tptr; /* usually points to a time_t (long) */ -Time *TimePtr; -{ -#ifdef UNIX - time_t *tp = (time_t *) tptr; - struct tm *unixt; - - unixt = localtime(tp); /* expand time_t into components */ - TimePtr->second = unixt->tm_sec; - TimePtr->minute = unixt->tm_min; - TimePtr->hour = unixt->tm_hour; - TimePtr->year = unixt->tm_year; - TimePtr->day = unixt->tm_mday -1; /* want 0-xx, not 1-xx */ - TimePtr->month = unixt->tm_mon; - TimePtr->extra = 0; - TimePtr->weekDay = unixt->tm_wday +1; /* Sunday = 1, not 0 like UNIX */ -#else -# ifdef APW /* APW version */ - twobyt date, time; - - date = (twobyt)tptr[0] + ((twobyt)tptr[1] << 8); - time = (twobyt)tptr[2] + ((twobyt)tptr[3] << 8); - TimePtr->second = 0; /* not stored in ProDOS file info */ - TimePtr->minute = (char) time; /* truncated to char */ - TimePtr->hour = time >> 8; - TimePtr->year = date >> 9; - TimePtr->day = (date & 0x1f) - 1; - TimePtr->month = ((date & 0x01e0) >> 5) - 1; - TimePtr->extra = 0; - TimePtr->weekDay = 0; -# endif /* APW */ -# ifdef MSDOS - struct tm *newtime; - time_t *tp = (time_t *) tptr; - - newtime = localtime (tp); - TimePtr->second = (onebyt)newtime->tm_sec; - TimePtr->minute = (onebyt)newtime->tm_min; - TimePtr->hour = (onebyt)newtime->tm_hour; - TimePtr->year = (onebyt)newtime->tm_year; - TimePtr->day = (onebyt)newtime->tm_mday - 1; - TimePtr->month = (onebyt)newtime->tm_mon; - TimePtr->extra = 0; - TimePtr->weekDay= (onebyt)newtime->tm_wday + 1; -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - printf("Need [other] time-expander\n"); /* +PORT+ */ - TimePtr->second = 0; - TimePtr->minute = 0; - TimePtr->hour = 0; - TimePtr->year = 0; - TimePtr->day = 0; - TimePtr->month = 0; - TimePtr->extra = 0; - TimePtr->weekDay = 0; -# endif /* none1 */ -# endif /* none2 */ -#endif /* UNIX */ -} - - -/* - * Get current time, put in struct - */ -Time *GetTime() -{ - static Time t; -#ifdef UNIX - struct tm *unixt; - time_t now = time(NULL); - - unixt = localtime(&now); - t.second = unixt->tm_sec; - t.minute = unixt->tm_min; - t.hour = unixt->tm_hour; - t.year = unixt->tm_year; - t.day = unixt->tm_mday -1; /* want 0-xx, not 1-xx */ - t.month = unixt->tm_mon; - t.extra = 0; - t.weekDay = unixt->tm_wday +1; /* Sunday = 1, not 0 like UNIX */ - /* return (&t) */ -#else -# ifdef APW - t = ReadTimeHex(t); - /* return (&t) */ -# endif /* APW */ -# ifdef MSDOS - struct tm *pctime; - time_t now = time(NULL); - - pctime = localtime(&now); - t.second = (onebyt)pctime->tm_sec; - t.minute = (onebyt)pctime->tm_min; - t.hour = (onebyt)pctime->tm_hour; - t.year = (onebyt)pctime->tm_year; - t.day = (onebyt)pctime->tm_mday -1; /* want 0-xx, not 1-xx */ - t.month = (onebyt)pctime->tm_mon; - t.extra = 0; - t.weekDay= (onebyt)pctime->tm_wday +1; /* Sunday = 1, not 0 */ - /* return (&t) */ -# endif /* MSDOS */ - -# ifndef APW -# ifndef MSDOS - printf("\nNeed [other] GetTime\n"); /* +PORT+ */ - t->second = 0; - t->minute = 0; - t->hour = 0; - t->year = 0; - t->day = 0; - t->month = 0; - t->filler = 0; - t->weekDay = 0; - /* return (&t) */ -# endif /* none1 */ -# endif /* none2 */ -#endif /* UNIX */ - return (&t); -} - - -/* - * Convert a NuFX Time struct to a compact system-dependent format - * - * This is used to set a file's date when extracting. Most systems don't - * dedicate 8 bytes to storing the date; this reduces it to the format - * used by a "set_file_date" command. - */ -long ReduceTime(tptr) -Time *tptr; -{ -#ifdef UNIX - long t = timecvt(tptr); - - return (t ? t : time(NULL)); /* if stored time is invalid, */ - /* return current time */ -#else -# ifdef APW - twobyt date, time; - long val; - - date = ((twobyt)tptr->year << 9) | ((((twobyt)tptr->month)+1) << 5) | - (((twobyt)tptr->day)+1); - time = ((twobyt)tptr->hour << 8) | ((twobyt)tptr->minute); - - val = (long) date + ((long) time << 16); - return (val); -# endif /* APW */ -# ifdef MSDOS - return (time(NULL)); /* not sure what to do, return current : RBH */ -# endif /* MSDOS */ - -#ifndef APW -#ifndef MSDOS - printf("Need [other] ReduceTime\n"); /* +PORT+ */ -# endif /* none2 */ -# endif /* none1 */ -#endif /* UNIX */ -} - =numain.c -/* - * numain.c - shell-based front end for NuLib - * - * NuLib v3.0 February 1991 Freeware (distribute, don't sell) - * By Andy McFadden (fadden@cory.berkeley.edu) - */ -#ifdef APW -segment "main" -#endif - -static char *header = - "NuLib v3.03 February 1991 Freeware Copyright 1989-91 By Andy McFadden"; - -#include "nudefs.h" /* system-dependent defines */ -#include <stdio.h> /* standard I/O library */ -#include <errno.h> -#include <fcntl.h> -#include <ctype.h> /* C type stuff, like tolower() */ -#ifdef BSD43 -# include <strings.h> -#else /* SYSV, APW, MSC */ -# include <string.h> /* string stuff */ -#endif - -#ifdef APW -# include <stdlib.h> -# include <types.h> -# include <strings.h> -# include <shell.h> -#endif - -#include "nuread.h" /* structs for archive info, archive read routines */ -#include "nuview.h" /* archive listing functions */ -#include "nuadd.h" /* archive operations (add, create, move) */ -#include "nuext.h" /* archive operations (extract) */ -#include "nupdel.h" /* archive operations (delete, update, freshen) */ -#include "nublu.h" /* Binary II archive operations */ -#include "nupak.h" /* need PAKBUFSIZ */ -#include "nuetc.h" /* Malloc(), Fatal(), etc. */ - -extern char *getenv(); /* +PORT+ */ - -#define Whoops(str) printf("WARNING: typedef %s may be set incorrectly\n",str); -#define ENVAR "NULIBOPT" /* environment variable with options in it */ - -/* - * global to entire program - */ -int HiLo; /* byte ordering; FALSE on low-first (65816) */ -int verbose; /* print verbose? */ -int interact; /* interactive overwrite mode? */ -int dopack; /* do we want to pack/unpack? */ -int doExpand; /* do we want to expand archive filenames? */ -int doSubdir; /* process subdirectories at all? */ -int doMessages; /* do comments instead of data */ -int transfrom; /* how to do CR<->LF translation (from what?) (-1 = off) */ -int transto; /* translate to ? */ -int packMethod; /* how to pack a file */ -fourbyt defFileType; /* default file type */ -fourbyt defAuxType; /* default aux type */ -onebyt *pakbuf; /* used by compression routines; created once to reduce */ - /* overhead involved in malloc()ing a 64K buffer */ -char *prgName = "NuLib"; /* for error messages; don't like argv[0] */ - /* besides, the name changes every 3 weeks */ - -/* - * Print simple usage info - */ -static void Usage(argv0) -char *argv0; -{ - printf("\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0); - printf("\nType \"%s h\" for help.\n", argv0); -} - - -/* - * Print usage info - */ -static void Help(argv0, options) -char *argv0, *options; -{ - if (INDEX(options+1, 'n')) { /* using 'n' suboption? */ - printf("%s\n", header); - printf("\nCompression methods:\n"); - printf(" # Name Abbr Pack? Unpack?\n"); - printf(" 0: Uncompressed unc Y Y\n"); - printf(" 1: SQueezed (sq/usq) squ N Y\n"); - printf(" 2: Dynamic LZW-I (ShrinkIt) shk Y Y\n"); - printf(" 3: Dynamic LZW-II (ShrinkIt) sh2 N N\n"); - printf(" 4: UNIX 12-bit compress u12 Y Y\n"); - printf(" 5: UNIX 16-bit compress u16 Y Y\n"); - printf("The default is #2\n"); - printf("\nText conversion methods (during extraction):\n"); - printf(" 0: Convert from CR to this system (ProDOS files)\n"); - printf(" 1: Convert from LF to this system (UNIX files)\n"); - printf(" 2: Convert from CRLF to this system (MS-DOS files)\n"); - - } else if (INDEX(options+1, 'w')) { /* print author info */ - - printf("%s\n", header); - printf( - "Internet: fadden@cory.berkeley.edu Usenet: ...!ucbvax!cory!fadden\n"); - printf("\nShrinkIt and NuFX standard by Andy Nicholas.\n"); - printf( - "ShrinkIt LZW compression by Kent Dickey. LZW/II (a modified version of\n"); - printf(" Kent's algorithm) by Andy Nicholas.\n"); - printf("\nUNIX compress code adapted from COMPRESS v4.3.\n"); - printf( -"\nBinary II unpack and unsqueeze C code adapted from unblu.c and usq.c by\n"); - printf(" Marcel J.E. Mol (usq.c based on usq2/sq3 by Don Elton).\n"); - printf("\nMS-DOS port by Robert B. Hess and Bruce Kahn.\n"); - printf( -"\nThis program is Freeware. Please distribute as widely as possible, but\n"); - printf( - " don't sell it. Source code is available via e-mail upon request.\n"); - printf( - "\nUsers without Usenet/Internet access may send mail to me at:\n"); - printf(" 1474 Saskatchewan Drive\n"); - printf(" Sunnyvale, CA 94087\n"); - - } else if (INDEX(options+1, 's')) { /* suboption info */ - printf("%s\n", header); - printf("\nUsual meaning of suboptions:\n"); - printf(" c - compression type, followed by a number\n"); - printf( - " f - file/aux type to add, followed by file/aux type spec\n"); - printf(" i - interactive; prompt before overwriting file\n"); - printf(" m - messages (add/extract comments instead of data)\n"); - printf(" r - don't recursively descend subdirectories\n"); - printf(" s - storage type (store as compressed w/o compressing), "); - printf("followed by number\n"); - printf( - " t - text translation (CR<->LF), followed by conversion mode\n"); - printf(" u - store as uncompressed (same as c0)\n"); - printf(" v - verbose mode\n"); -#ifndef NO_BLU - printf(" x - extract during Binary II operations\n"); -#endif - printf(" + - match partial pathnames for extract and delete\n"); - printf("\nTable of contents suboptions:\n"); - printf(" v - verbose output (same as V option)\n"); - printf(" a - ARC/ZOO style format\n"); - printf(" z - full output, prints all aspects of archive\n"); - - printf("\nSample shell variable command (csh):\n"); - printf( - " setenv NULIBOPT=verbose,interactive,type=SRC,aux=000a,compress=5\n"); - printf(" (default is non-verbose, non-interactive, type=NON, "); - printf( "aux=0000, compress=2)\n"); - - } else { /* default help screen */ - - printf("%s\n", header); - printf( - "\nUsage: %s option[suboptions] archive-name [filespec]\n", argv0); - printf("Option must be one of:\n"); - printf(" a[vucsrf] add to archive\n"); -#ifndef NO_BLU - printf(" b[xvti] Binary II archive operations\n"); -#endif - printf( - " c[vucsrf] create archive (add, but suppress 'create' message)\n"); - printf(" d[v+] delete file from archive\n"); - printf(" f[vucsrf] freshen files in archive\n"); - printf(" h[snw] show help screen (subopt/numbers/who's who)\n"); - printf(" i[v] verify archive integrity\n"); - printf(" m[vucsrf] move files to archive (add, delete original)\n"); - printf(" p[vmt+] print archived file to stdout\n"); - printf(" t[vaz] display table of contents\n"); - printf(" u[vucsrf] update files in archive\n"); - printf(" v verbose listing (ProDOS 8 ShrinkIt format)\n"); - printf(" x,e[vumti+] extract from archive\n"); - } -} - - -/* - * Check machine dependencies - */ -static void CheckMach() -{ - onebyt one; - onebyt *oneptr; - twobyt two; - fourbyt four; - -#ifdef UNIX -# ifdef APW - ^^ "ERROR: You have both APW and UNIX defined" ^^ -# endif -# ifdef MSDOS - ^^ "ERROR: You have both MSDOS and UNIX defined" ^^ -# endif -#endif /*UNIX*/ -#ifdef APW -# ifdef MSDOS - ^^ "ERROR: You have both APW and MSDOS defined" ^^ -# endif -#endif - - /* some compilers complain about (unsigned) -1 , so I'm doing it this */ - /* way to keep everybody quiet. */ - - one = 0x100; - if (one) - Whoops("onebyt"); /* one > 1 */ - two = 0x10000; - if (two) - Whoops("twobyt"); /* two > 2 */ - two = 0x1000; - if (!two) - Whoops("twobyt"); /* two < 2 */ - four = 0xffffffff; - four++; - if (four) - Whoops("fourbyt"); /* four > 4 */ - four = 0x10000; - if (!four) - Whoops("fourbyt"); /* four < 4 */ - - /* check byte ordering */ - two = 0x1122; - oneptr = (onebyt *) &two; - if (*oneptr == 0x11) - HiLo = TRUE; - else if (*oneptr == 0x22) - HiLo = FALSE; - else { - printf("WARNING: Unable to determine a value for HiLo\n"); - HiLo = FALSE; - } - - /* check some other stuff... compilers may (should?) give warnings here */ - if (ATTSIZE < MHsize) - printf("WARNING: ATTSIZE must be >= than MHsize\n"); - if (RECBUFSIZ < ATTSIZE) - printf("WARNING: RECBUFSIZ should be larger than ATTSIZE\n"); - if (MHsize != 48 || THsize != 16) - printf("WARNING: Bad MHsize or THsize\n"); - if (sizeof(Time) != 8) - printf("WARNING: struct Time not 8 bytes\n"); -} - - -/* - * Check to see if string 2 is in string 1. - * - * Returns the position of string 2 within string 1; -1 if not found. - */ -static int strc(host, sub) -char *host, *sub; -{ - int hlen = strlen(host); - int slen = strlen(sub); - int i; - - if (slen > hlen) /* substring longer than host string */ - return (-1); - - /* generic linear search... */ - for (i = 0; i <= (hlen - slen); i++) - if ((*(host+i) == *sub) && (!strncmp(host+i, sub, slen))) - return (i); - - return (-1); -} - - -/* - * Yank a number from a character string. - */ -int OptNum(ptr) -char *ptr; -{ - int val = 0; - - while (*ptr && isdigit(*ptr)) { - val *= 10; - val += (*ptr - '0'); - ptr++; - } - return (val); -} - - -/* - * Set default values for globals. - * - * Should be of form "NULIBOPT=..." - * verbose : default to verbose output - * interactive : default to interactive mode when overwriting - * type=xxx : set storage type to ProDOS type "xxx" - * aux=xxxx : set aux storage type to 4-byte hex number "xxxx" - */ -void GetDefaults(options) -char *options; -{ - char *envptr; - int off, idx, pt; - int len = strlen(options); - char type[5]; - - /* set program default values */ - verbose = FALSE; /* silent mode */ - interact = FALSE; /* don't ask questions */ - doSubdir = TRUE; /* process subdirectories unless told not to */ - dopack = TRUE; /* don't pack unless told to */ - doExpand = FALSE; /* don't expand archived filenames */ - doMessages = FALSE; /* do comments instead of data */ - packMethod = 0x0002;/* ShrinkIt LZW */ - transfrom = -1; /* no text translation */ - transto = -1; - defFileType = (fourbyt) 0; /* NON */ - defAuxType = (fourbyt) 0; /* $0000 */ - - /* read from global envir var */ - if (envptr = getenv(ENVAR)) { - if (strc(envptr, "verbose") >= 0) { - verbose = TRUE; - } - if (strc(envptr, "interactive") >= 0) { - interact = TRUE; - } - if ((off = strc(envptr, "compress=")) >= 0) { - off += 9; - if (off+1 > strlen(envptr)) { - fprintf(stderr, "Error with 'compress=n' in NULIBOPT var\n"); - Quit (-1); - } - packMethod = atoi(envptr+off); - } - if ((off = strc(envptr, "type=")) >= 0) { - off += 5; - if (off+3 > strlen(envptr)) { - fprintf(stderr, "Error with 'type=xxx' in NULIBOPT var\n"); - Quit (-1); - } - strncpy(type, envptr+off, 3); - type[3] = '\0'; - for (idx = 0; idx < 256; idx++) /* scan for file type */ - if (!strcasecmp(FT[idx], type)) { - defFileType = (fourbyt) idx; - break; /* out of for */ - } - } - if ((off = strc(envptr, "aux=")) >= 0) { - off += 4; - if (off+4 > strlen(envptr)) { - fprintf(stderr, "Error with 'aux=$xxxx' in NULIBOPT var\n"); - Quit (-1); - } - strncpy(type, envptr+off, 4); - type[4] = '\0'; - sscanf(type, "%x", &defAuxType); - } - } - - /* handle command line suboption string */ - for (pt = 1; pt < len; pt++) { /* skip option char */ - switch(options[pt]) { - case '+': /* expand */ - doExpand = TRUE; - break; - case 'a': /* ARC/ZOO output format */ - /* do nothing */ - break; - case 'c': /* compress method */ - packMethod = OptNum(&options[pt+1]); - while (pt < len && isdigit(options[pt+1])) /* advance to next */ - pt++; - dopack = TRUE; - break; - case 'f': /* filetype specified */ - strncpy(type, &options[pt+1], 3); - type[3] = '\0'; - for (idx = 0; idx < 256; idx++) /* scan for file type */ - if (!strcasecmp(FT[idx], type)) { - defFileType = (fourbyt) idx; - break; /* out of for */ - } - - pt += strlen(type); - if (options[pt+1] == '/') { /* auxtype specification */ - pt++; - strncpy(type, &options[pt+1], 4); - type[4] = '\0'; - sscanf(type, "%lx", &defAuxType); - pt += strlen(type); - } - break; - case 'i': /* interactive overwrites */ - interact = TRUE; - break; - case 'm': /* do messages instead of data */ - doMessages = TRUE; - break; - case 'n': /* help with numbers */ - /* do nothing */ - break; - case 'r': /* don't recursively descend subdir */ - doSubdir = FALSE; - break; - case 's': /* store method */ - packMethod = OptNum(&options[pt+1]); - while (pt < len && isdigit(options[pt+1])) /* advance to next */ - pt++; - dopack = FALSE; - break; - case 't': /* how to translate text? */ - transfrom = OptNum(&options[pt+1]); - while (pt < len && isdigit(options[pt+1])) - pt++; - break; - case 'u': /* don't use compression */ - dopack = FALSE; /* this doesn't matter, but FALSE may be faster */ - packMethod = 0x0000; /* archive w/o compression */ - break; - case 'v': /* verbose mode */ - verbose = TRUE; - break; - case 'w': /* help on people */ - /* do nothing */ - break; - case 'x': /* extract BLU files */ - /* do nothing */ - break; - case 'z': /* in view files */ - /* do nothing */ - break; - default: /* unknown */ - fprintf(stderr, "%s: unknown subopt '%c'\n", prgName, options[pt]); - break; /* do nothing */ - } - } /* for */ -} - - -#ifdef APW -/* - * Expand a ProDOS filename using APW wildcard calls (even if the file doesn't - * exist). - * - * Returns a pointer to a buffer holding the filename. - */ -char *ExpandFilename(filename) -char *filename; -{ - char *ptr; - - c2pstr(filename); - if (!(*filename)) { - printf("Internal error: can't expand null filename\n"); - Quit (-1); - } - - INIT_WILDCARD(filename, 0); - ToolErrChk(); - p2cstr(filename); - - NEXT_WILDCARD(tmpNameBuf); - p2cstr(tmpNameBuf); - if (strlen(tmpNameBuf)) /* found it */ - return(tmpNameBuf); - else { - /* file does not exist; expand path */ - strcpy(tmpNameBuf, filename); - ptr = RINDEX(tmpNameBuf, '/'); /* remove filename */ - if (!ptr) /* filename only */ - return (filename); - - *ptr = '\0'; - if (!strlen(tmpNameBuf)) { /* something weird... */ - printf("Unable to expand '%s'\n", filename); - Quit (-1); - } - - c2pstr(tmpNameBuf); - INIT_WILDCARD(tmpNameBuf, 0); - ToolErrChk(); - - NEXT_WILDCARD(tmpNameBuf); - p2cstr(tmpNameBuf); - if (!strlen(tmpNameBuf)) { - printf("Unable to fully expand '%s'\n", filename); - Quit (-1); - } - - strcat(tmpNameBuf, RINDEX(filename, '/')); - return (tmpNameBuf); - } -} -#endif /* APW */ - - -/* - * Parse args, call functions. - */ -main(argc, argv) -int argc; -char **argv; -{ - char *filename; /* hold expanded archive file name */ - int idx; - - filename = (char *) Malloc(MAXFILENAME); - CheckMach(); /* check compiler options, and set HiLo */ - - if (argc < 2) { /* no arguments supplied */ - Usage(argv[0]); - Quit (0); - } - - if (argv[1][0] == '-') { /* skip initial dashes */ - argv[1]++; - } - for (idx = 0; argv[1][idx]; idx++) /* conv opts to lower case */ - if (isupper(argv[1][idx])) - argv[1][idx] = tolower(argv[1][idx]); - - if (argc < 3) { /* no archive file specified; show help screen */ - if (argv[1][0] == 'h') /* could be HS, HN, or HW */ - Help(argv[0], argv[1]); - else /* not 'H' option; show generic help scrn */ - Help(argv[0], "h"); - Quit (0); - } - -#ifdef APW - strcpy(filename, ExpandFilename(argv[2])); -#else - strcpy(filename, argv[2]); -#endif - GetDefaults(argv[1]); /* get defaults, process suboption string */ - - pakbuf = (onebyt *) Malloc(PAKBUFSIZ); /* allocate global pack buf */ - switch (argv[1][0]) { - case 'a': /* add */ - case 'c': /* create */ - case 'm': /* move */ - NuAdd(filename, argc-3, argv+3, argv[1]); /* NuAdd will read */ - break; -#ifndef NO_BLU - case 'b': /* Binary II operations */ - NuBNY(filename, argc-3, argv+3, argv[1]); - break; -#endif - case 'd': /* delete */ - NuDelete(filename, argc-3, argv+3, argv[1]); - break; - case 'f': /* freshen */ - case 'u': /* update */ - NuUpdate(filename, argc-3, argv+3, argv[1]); - break; - case 'i': /* verify integrity */ - NuTest(filename, argv[1]); - break; - case 't': /* table of contents */ - case 'v': /* verbose output */ - NuView(filename, argv[1]); - break; - case 'e': /* extract */ - case 'x': - case 'p': - NuExtract(filename, argc-3, argv+3, argv[1]); - break; - default: /* need help */ - fprintf(stderr, "%s: unknown option '%c'\n", argv[0], argv[1][0]); - break; - } - - free (filename); - free (pakbuf); - Quit (0); -} - =nupak.c -/* - * nupak.c - interface to the compression routines - * - * NuLib v3.0 February 1991 Freeware (distribute, don't sell) - * By Andy McFadden (fadden@cory.berkeley.edu) - */ -#ifdef APW -segment "Compress" -#endif - -#include "nudefs.h" -#include <stdio.h> -/*#include <fcntl.h>*/ /* "nucomp.h" includes <fcntl.h> for us */ -#include "nuread.h" /* need THblock */ -#include "nucomp.h" /* includes "nucompfn.h" + "types.h" */ - -#ifdef MSDOS /* for file I/O */ -# include <io.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <errno.h> -#endif - -#include "nupak.h" -#include "nuetc.h" - -#define CONVSIZ 1024 - -long packedSize; /* global - size of file after packing */ -onebyt lastseen; /* used in crlf(); must be set by caller */ - - -/* - * Make a little spinning thing. - * - * This just lets the user know that the whole thing hasn't stalled on him. - * Prints a character, then backspaces so that the next thing will overwrite - * it. - * - * Currently called by FCopy(), unpak_SHK(), pak_SHK() - */ -void Spin() -{ - static char *sp = "/-\\|"; - static int posn = 0; - - posn++; - if ((posn < 0) || (posn > 3)) - posn = 0; - putchar(sp[posn]); - putchar('\b'); - fflush(stdout); -} - - -/* - * Convert the end-of-line terminator between systems. - * - * Compile-time defines determine the value that things are translated to; - * the value of "translate" determines what they are translated from. This - * will write the contents of the buffer to the passed file descriptor, - * altering bytes as necessary. Max buffer size is 64K. Note that the - * syntax is the same as for write(); - * - * This would have been a lot easier without IBM... lastseen is the last - * character seen (used only in CRLF translations). This needs to be set - * by the caller (FCopy(), extract_files()). - * - * The putc_ncr() procedure in nusq.c does its own processing; this was - * somewhat unavoidable. - * - * BUGS: This proc will have to be re-written. It would be nice to be - * able to pack files with a CRLF translation, not just unpack... but you - * can't just do buffer writes for that. It'll take some work, and will - * probably appear in the next version. - */ -unsigned int crlf(dstfd, buffer, length) -int dstfd; -onebyt *buffer; -unsigned int length; -{ - register BOOLEAN doconv; - register onebyt *bptr = buffer; - register unsigned int idx; - static char *procName = "crlf"; - unsigned int partial; /* size for partial read/write */ - onebyt tobuf[2048]; - onebyt *toptr; - int conv; - unsigned int origlength = length; - - if ((transfrom == -1) && (transto == -1)) { /* no translation necessary */ - return (write(dstfd, buffer, length)); - } - if (transfrom < -1 || transfrom > 2) { - fprintf(stderr, "%s: unknown translation type %d\n", - prgName, transfrom); - fprintf(stderr, "%s: assuming conversion 0 (from CR)\n", prgName); - transfrom = 0; - } - if (transto < -1 || transto > 2) { - fprintf(stderr, "%s: unknown translation type %d\n", - prgName, transto); - fprintf(stderr, "%s: assuming conversion 0 (to CR)\n", prgName); - transto = 0; - } - - /* macro defs for system-dependent actions */ -#ifdef UNIX -# define DEFCONVFROM if (*bptr == 0x0a) /* LF */ \ - doconv = TRUE -# define DEFCONVTO *(toptr++) = 0x0a -#else -# ifdef APW -# define DEFCONVFROM if (*bptr == 0x0d) /* CR */ \ - doconv = TRUE -# define DEFCONVTO *(toptr++) = 0x0d -# endif -# ifdef MSDOS -# define DEFCONVFROM if ((*bptr == 0x0a) && (lastseen == 0x0d)) { \ - doconv = TRUE; \ - toptr--; /*already put CR; back up over it*/ \ - } \ - lastseen = *bptr -# define DEFCONVTO *(toptr++) = 0x0d; \ - *(toptr++) = 0x0a -# endif -# ifndef APW -# ifndef MSDOS -# define DEFCONVFROM if (*bptr == 0x0a) /* LF */ \ - doconv = TRUE -# endif /* none2 */ -# endif /* none1 */ -#endif /* UNIX */ - - while (length != 0) { - if (length > CONVSIZ) { - partial = CONVSIZ; - length -= CONVSIZ; - } else { - partial = length; - length = 0; - } - - /* uses an explicit flag rather than "continue" for clarity... */ - toptr = tobuf; - for (idx = partial; idx > 0; idx--, bptr++) { - doconv = FALSE; - switch (transfrom) { - case -1: /* convert from current system's terminator */ - DEFCONVFROM; - break; - case 0: - if (*bptr == 0x0d) /* CR */ - doconv = TRUE; - break; - case 1: - if (*bptr == 0x0a) /* LF */ - doconv = TRUE; - break; - case 2: - if ((*bptr == 0x0a) && (lastseen == 0x0d)) { - doconv = TRUE; - toptr--; /*already outputed CR; back up over it*/ - } - lastseen = *bptr; - break; - } - - - if (doconv) { - switch (transto) { - case -1: /* convert to current system's terminator */ - DEFCONVTO; - break; - case 0: - *(toptr++) = 0x0d; - break; - case 1: - *(toptr++) = 0x0a; - break; - case 2: - *(toptr++) = 0x0d; - *(toptr++) = 0x0a; - break; - } - } else { - *(toptr++) = *bptr; - } - } /* for loop */ - - if (write(dstfd, tobuf, (toptr-tobuf)) != (toptr-tobuf)) - Fatal("Dest write failed", procName); - } /* while loop */ - return (origlength); -} - - -/* - * Read a file, and place in another file at current posn. We can't read more - * than PAKBUFSIZ at a time, so for some files it will have to be broken down - * into pieces. Note PAKBUFSIZ is expected to be an int (defined in nupak.h), - * and can't be any larger than read() can handle (64K... unsigned 16-bit int). - * - * The transl option is present for NuUpdate and NuDelete, which have to - * copy old records to a new archive w/o performing translation. - */ -void FCopy(srcfd, dstfd, length, copybuf, transl) -int srcfd; /* source file descriptor (must be open & seek()ed) */ -int dstfd; /* destination file descriptor (must be open & seek()ed) */ -fourbyt length; /* number of bytes to copy */ -onebyt *copybuf; -BOOLEAN transl; /* maybe do text translation? */ -{ - unsigned int partial; /* size for partial read/write */ - static char *procName = "FCopy"; - - if (transl) lastseen = '\0'; - while (length != 0L) { - if (length > (long) PAKBUFSIZ) { - partial = (unsigned int) PAKBUFSIZ; - length -= (long) PAKBUFSIZ; - if (verbose) Spin(); - } else { - partial = (unsigned int) length; - length = 0L; - } - - if (read(srcfd, copybuf, partial) != partial) - Fatal("Source read failed", procName); - if (transl) { /* do text translation if user wants it */ - if (crlf(dstfd, copybuf, partial) != partial) - Fatal("Dest write failed (c)", procName); - } else { /* NEVER do translation */ - if (write(dstfd, copybuf, partial) != partial) - Fatal("Dest write failed (w)", procName); - } - } -} - - -/* - * Add a range of bytes from one file into another, packing them. - * - * Set up stuff, then call the appropriate pack routine. Returns the actual - * algorithm used (thread_format), since the compression algorithm could - * fail, storing the file in uncompressed format instead. The packed length - * is stored in a global variable. - * - * Since we're only using version 0 records, we don't need to propagate the - * thread_crc. - * - * Compression routines must do the following: - * - compress data from one file descriptor to another, given two seeked - * file descriptors and a length value. They may not rely on EOF conditions - * for either file. - * - return the packing method actually used. If they cope with failure - * by starting over with something different, the successful method should - * be returned. Failure may be handled in the switch statement below. - */ -twobyt PackFile(srcfd, dstfd, thread_eof, thread_format, buffer) -int srcfd; /* source file descriptor (must be open & seek()ed) */ -int dstfd; /* destination file descriptor (must be open & seek()ed) */ -fourbyt thread_eof; /* size of input */ -int thread_format; /* how to pack the bytes */ -onebyt *buffer; /* alloc in main prog so we don't have to each time */ -{ - long length = (long) thread_eof; - twobyt retval = thread_format; /* default = successful pack */ - long srcposn, dstposn; - static char *procName = "PackFile"; - - switch (thread_format) { - case 0x0000: /* uncompressed */ - if (verbose) { printf("storing...", thread_format); fflush(stdout); } - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - break; - - case 0x0001: /* SQUeeze */ - if (verbose) { - printf("[can't squeeze; storing]..."); - fflush(stdout); - } else { - printf("WARNING: can't squeeze; files stored uncompressed\n"); - } - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - retval = 0x0000; /* uncompressed */ - break; - - case 0x0002: /* LZW (ShrinkIt) */ - if (verbose) { printf("shrinking..."); fflush(stdout); } - /* packedSize set by pak_SHK */ - retval = pak_SHK(srcfd, dstfd, length, buffer); - break; - case 0x0003: /* LZW II (ShrinkIt) */ - if (verbose) { - printf("[can't do LZW II; storing]..."); - fflush(stdout); - } else { - printf("WARNING: can't do LZW II; files stored uncompressed\n"); - } - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - retval = 0x0000; /* uncompressed */ - break; - case 0x0004: /* UNIX 12-bit compress */ -#ifdef NO_UCOMP - if (verbose) { - printf("[can't do 12-bit UNIX compress; storing]..."); - fflush(stdout); - } else { - printf( - "WARNING: can't do 12-bit compress; files stored uncompressed\n"); - } - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - retval = 0x0000; /* uncompressed */ -#else - maxbits = 12; /* global compress parameter */ - if (verbose) { printf("compressing..."); fflush(stdout); } - /* packedSize set by compress() */ - if (u_compress(srcfd, dstfd, length) == OK) - retval = 0x0004; - else - retval = 0x0004; /* FIX this */ -#endif - break; - - case 0x0005: /* UNIX 16-bit compress */ -#ifdef NO_UCOMP - if (verbose) { - printf("[can't do 16-bit UNIX compress; storing]..."); - fflush(stdout); - } else { - printf( - "WARNING: can't do 16-bit compress; files stored uncompressed\n"); - } - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - retval = 0x0000; /* uncompressed */ -#else - maxbits = 16; /* global compress parameter */ - if (verbose) { printf("compressing..."); fflush(stdout); } - /* packedSize set by compress() */ - srcposn = lseek(srcfd, 0L, S_REL); /* save posn */ - dstposn = lseek(dstfd, 0L, S_REL); - if (u_compress(srcfd, dstfd, length) == OK) { - /* compress succeeded */ - retval = 0x0005; - } else { - /* compression failed */ - if (verbose) { printf("storing..."); fflush(stdout); } - lseek(srcfd, srcposn, S_ABS); /* reposn files */ - lseek(dstfd, dstposn, S_ABS); - FCopy(srcfd, dstfd, length, buffer, TRUE); - packedSize = length; - retval = 0x0000; - } -#endif - break; - - default: - fprintf(stderr, "\nUnknown compression method %d\n", thread_format); - fprintf(stderr, "Aborting.\n"); - Quit(-1); - } - - return (retval); -} - - -/* - * Extract a range of bytes from one file into another, unpacking them. - * - * (hacked to unpack disks, also. Forces the thread_eof to be the total - * size of the disk, since ShrinkIt doesn't really define it, esp for DOS 3.3 - * disks). - * - * Set up stuff, then call the appropriate unpack routine. Leaves the srcfd - * positioned past the data to be unpacked; the calling routine should not - * have to do any seeks. - * - * Returns TRUE if able to unpack, FALSE if not able to. Note that srcfd - * WILL be seeked even if the compression method is not handled. - * - * New uncompression routines should have the following characteristics: - * - they should be able to uncompress a range of bytes from one file - * to another given two seeked file descriptors and a length parameter. - * - they should return TRUE if they succeed and FALSE otherwise. Special - * condition codes can be handled in the switch statement below. - */ -int UnpackFile(srcfd, dstfd, THptr, thread_format, buffer) -int srcfd; /* source file descriptor (must be open & lseek()ed) */ -int dstfd; /* destination file descriptor (must be open & lseek()ed) */ -THblock *THptr; /* pointer to thread structure */ -int thread_format; /* how to unpack the bytes (NOT THptr->thread_format) */ -onebyt *buffer; -{ - long length; - fourbyt thread_eof, /* #of bytes to output */ - comp_thread_eof; /* #of bytes in source */ - twobyt thread_crc; - BOOLEAN retval = TRUE; /* default to success */ - static char *procName = "UnpackFile"; - - thread_eof = THptr->thread_eof; - comp_thread_eof = THptr->comp_thread_eof; - thread_crc = THptr->thread_crc; /* never used? */ - length = (long) comp_thread_eof; /* type checking goes easier */ - - switch (thread_format) { - case 0x0000: /* uncompressed */ - if (verbose) { printf("extracting...", thread_format); fflush(stdout);} - FCopy(srcfd, dstfd, length, buffer, TRUE); - break; - - case 0x0001: /* unSQUeeze */ -#ifdef NO_BLU - if (verbose) { - printf("[can't unsqueeze - aborting]..."); - fflush(stdout); - } else { - printf("ERROR: can't unsqueeze; 'squ' files not extracted\n"); - } - lseek(srcfd, length, S_REL); /* set file posn */ - retval = FALSE; -#else - if (verbose) { printf("unsqueezing..."); fflush(stdout); } - unpak_SQU(srcfd, dstfd, length); /* thread_eof not needed */ -#endif - break; - - case 0x0002: /* LZW (ShrinkIt) */ - if (verbose) { printf("unshrinking (I)..."); fflush(stdout); } - unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, FALSE); - break; - - case 0x0003: /* LZW II (ShrinkIt) */ -#ifdef TRY_II - if (verbose) { printf("unshrinking (II)..."); fflush(stdout); } - unpak_SHK(srcfd, dstfd, comp_thread_eof, thread_eof, buffer, TRUE); -#else - if (verbose) { - printf("[can't unshrink type II - aborting]..."); - fflush(stdout); - } else { - printf( - "ERROR: can't unshrink type II; 'sh2' files not extracted\n"); - } - lseek(srcfd, length, S_REL); /* set file posn */ - retval = FALSE; -#endif - break; - - case 0x0004: /* 12-bit UNIX compress */ -#ifdef NO_UCOMP - if (verbose) { - printf("[can't undo 12-bit UNIX compress - aborting]..."); - fflush(stdout); - } else { - printf( - "ERROR: can't undo 12-bit UNIX compress; 'u12' files not extracted\n"); - } - lseek(srcfd, length, S_REL); /* set file posn */ - retval = FALSE; -#else - if (verbose) { printf("uncompressing..."); fflush(stdout); } - if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK) - retval = FALSE; -#endif - break; - - case 0x0005: /* 16-bit UNIX compress */ -#ifdef NO_UCOMP - if (verbose) { - printf("[can't undo 16-bit UNIX compress - aborting]..."); - fflush(stdout); - } else { - printf( - "ERROR: can't undo 16-bit UNIX compress; 'u16' files not extracted\n"); - } - lseek(srcfd, length, S_REL); /* set file posn */ - retval = FALSE; -#else - if (verbose) { printf("uncompressing..."); fflush(stdout); } - if (u_decompress(srcfd, dstfd, (long) comp_thread_eof) != OK) - retval = FALSE; -#endif - break; - - default: - fprintf(stderr, "Unknown uncompression method %d\n", thread_format); - lseek(srcfd, length, S_REL); /* set file posn */ - retval = FALSE; - break; - } - - return (retval); -} - + END OF ARCHIVE