home *** CD-ROM | disk | FTP | other *** search
- From: np@doc.imperial.ac.uk (Nigel Perry)
- Newsgroups: comp.sources.mac
- Subject: AufsTools (part 4 of 4)
- Message-ID: <CSM.91.4>
- Date: 20 Feb 91 21:00:06 GMT
- Approved: bytebug@dhw68k.cts.com (Roger L. Long)
-
- [AufsTools - part 4 of 4]
-
- ---
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 4 (of 4)."
- # Contents: unstuffit/unsit.c
- # Wrapped by np@asun5 on Mon Dec 3 13:15:59 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'unstuffit/unsit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unstuffit/unsit.c'\"
- else
- echo shar: Extracting \"'unstuffit/unsit.c'\" \(31819 characters\)
- sed "s/^X//" >'unstuffit/unsit.c' <<'END_OF_FILE'
- X/* Modified Aug & Dec 90, Nigel Perry, Dept of Computing, Imperial College,
- X London SW7 2BZ, np@doc.ic.ac.uk
- X
- X If called by AUFSNAME (default unstuffit) will input/output to
- X CAPS aufs disc.
- X
- X Will now untiff multiple files.
- X
- X */
- X/*
- X unsit - Macintosh StuffIt file extractor
- X
- X Version 1.5f, for StuffIt 1.5
- X
- X July 23, 1990
- X
- XThis program will unpack a Macintosh StuffIt file into separate files.
- XThe data fork of a StuffIt file contains both the data and resource
- Xforks of the packed files. The program will unpack each Mac file into
- Xeither separate .data, .rsrc., and .info files that can be downloaded
- Xto a Mac using macput and MacTerminal over a tty line, or into a
- Xsingle MacBinary format file. The MacBinary format is generally more
- Xconvenient for those with network connections and FTP capability. The
- Xprogram is much like the "unpit" program for breaking apart Packit
- Xarchive files.
- X
- X ***** IMPORTANT *****
- XTo extract StuffIt files that have been compressed with the Lempel-Ziv
- Xcompression method, unsit pipes the data through the "compress"
- Xprogram with the appropriate switches, rather than incorporate the
- Xuncompression routines within "unsit". Therefore, it is necessary to
- Xhave the "compress" program on the system and in the search path to
- Xmake "unsit" work. "Compress" is available from the comp.sources.unix
- Xarchives.
- X
- XThe program syntax is much like unpit and macput/macget, with some added
- Xoptions:
- X
- X unsit [-rdulM] [-vqfm] stuffit-file.data
- X
- XOnly one of the flags r, d, u, l, or M should be specified. The
- Xdefault mode is to create the three macput/MacTerminal compatible
- Xfile. The -M flag will cause the output to be in MacBinary format (a
- Xsingle file). This can be swapped (default = MacBinary, -M = macput)
- Xby changing the definitions of DEFAULT_MODE and OTHER_MODE below. The
- X-r and -d flags will cause only the resource and data forks to be
- Xwritten. The -u flag will cause only the data fork to be written and
- Xto have carriage return characters changed to Unix newline characters.
- XThe -l flag will make the program only list the files in the StuffIt
- Xfile.
- X
- XThe -v flag causes the program to list the names, sizes, type, and
- Xcreators of the files it is writing. The -q flag causes it to list
- Xthe name, type and size of each file and wait for a 'y' or 'n' for
- Xeither writing that file or skipping it, respectively. The -m flag is
- Xused when the input file in in the MacBinary format instead of just
- Xthe data fork. It causes the program to skip the 128 byte MacBinary
- Xheader before looking for the StuffIt header. It is not necessary to
- Xspecify the -m flag since the program now checks for MacBinary format
- Xinput files and handles them correctly
- X
- XVersion 1.5 of the unsit supports extracting files and folders as
- Ximplemented by StuffIt 1.5's "Hierarchy Maintained Folder" feature.
- XEach folder is extracted as a subdirectory on the Unix system with the
- Xfiles in the folder placed in the corresponding subdirectory. The -f
- Xoption can be used to "flatten" out the hierarchy and unsit will store
- Xall the files in the current directory. If the query option (-q) is
- Xused and a "n" response is given to a folder name, none of the files
- Xor folders in that folder will be extraced.
- X
- XSome of the program is borrowed from the macput.c/macget.c programs.
- XMany, many thanks to Raymond Lau, the author of StuffIt, for including
- Xinformation on the format of the StuffIt archives in the
- Xdocumentation. Several changes and enhancements supplied by David
- XShanks (cde@atelabs.UUCP) have been incorporated into the program for
- Xdoing things like supporting System V and recognizing MacBinary files.
- XChristopher Bingham <kb@umnstat.stat.umn.edu> supplied some Macbinary
- Xpatches. Code was also borrowed from the macbin program by Jim Budler
- Xfor convert macput format files to MacBinary. I'm always glad to
- Xreceive advice, suggestions, or comments about the program so feel free
- Xto send whatever you think would be helpful
- X
- X
- X Author: Allan G. Weber
- X weber@sipi.usc.edu
- X ...!usc!sipi!weber
- X Date: July 23, 1990
- X
- X*/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- Xtypedef long OSType;
- X
- X#include "stuffit.h"
- X
- X/*
- X * Define the following if your Unix can only handle 14 character file names
- X * (e.g. Version 7 and System V).
- X */
- X/* #define SHORTNAMES */
- X
- X/*
- X * The following defines the name of the compress program that is used for the
- X * uncompression of Lempel-Ziv compressed files. If the path is set up to
- X * include the right directory, this should work.
- X */
- X#define COMPRESS "compress"
- X
- X#define IOBUFSIZ 4096
- X
- X#define MACBINHDRSIZE 128L
- X
- X#define INIT_CRC 0L
- Xextern unsigned short updcrc();
- X
- X#define INFOBYTES 128
- X
- X#define BYTEMASK 0xff
- X
- X#define S_SIGNATURE 0
- X#define S_NUMFILES 4
- X#define S_ARCLENGTH 6
- X#define S_SIGNATURE2 10
- X#define S_VERSION 14
- X#define SITHDRSIZE 22
- X
- X#define F_COMPRMETHOD 0
- X#define F_COMPDMETHOD 1
- X#define F_FNAME 2
- X#define F_FTYPE 66
- X#define F_CREATOR 70
- X#define F_FNDRFLAGS 74
- X#define F_CREATIONDATE 76
- X#define F_MODDATE 80
- X#define F_RSRCLENGTH 84
- X#define F_DATALENGTH 88
- X#define F_COMPRLENGTH 92
- X#define F_COMPDLENGTH 96
- X#define F_RSRCCRC 100
- X#define F_DATACRC 102
- X#define F_HDRCRC 110
- X#define FILEHDRSIZE 112
- X
- X#define F_NAMELEN 63
- X#ifdef SHORTNAMES /* short file names */
- X# define I_NAMELEN 15 /* 14 char file names + '\0' terminator */
- X#else
- X# define I_NAMELEN 69 /* 63 + strlen(".info") + 1 */
- X#endif
- X
- X/* The following are copied out of macput.c/macget.c */
- X#define I_NAMEOFF 1
- X/* 65 <-> 80 is the FInfo structure */
- X#define I_TYPEOFF 65
- X#define I_AUTHOFF 69
- X#define I_FLAGOFF 73
- X#define I_LOCKOFF 81
- X#define I_DLENOFF 83
- X#define I_RLENOFF 87
- X#define I_CTIMOFF 91
- X#define I_MTIMOFF 95
- X
- X#define INITED_BUG
- X#define INITED_OFF I_FLAGOFF /* offset to byte with Inited flag */
- X#define INITED_MASK (~1) /* mask to '&' with byte to reset it */
- X
- X#define TEXT 0
- X#define DATA 1
- X#define RSRC 2
- X#define MACPUT 3
- X#define DUMP 4
- X#define MACBINARY 5
- X
- X/* Swap the following definitions if you want the output to default to
- X MacBinary, and the -M switch to create macput file (.data, .rsrc, .info) */
- X#define DEFAULT_MODE MACPUT
- X#define OTHER_MODE MACBINARY
- X
- X/* #define ADDBIN */ /* add .bin to macbinary file names */
- X
- X#define NODECODE 0
- X#define DECODE 1
- X
- X#define H_ERROR -1
- X#define H_EOF 0
- X#define H_WRITE 1
- X#define H_SKIP 2
- X
- X/* if called by this name program works on aufs files */
- X#define AUFSNAME "unstuffit"
- X
- Xstruct node {
- X int flag, byte;
- X struct node *one, *zero;
- X} nodelist[512], *nodeptr, *read_tree(); /* 512 should be big enough */
- X
- Xstruct sitHdr sithdr;
- X
- Xchar f_info[I_NAMELEN];
- Xchar f_data[I_NAMELEN];
- Xchar f_rsrc[I_NAMELEN];
- X
- Xchar info[INFOBYTES];
- Xchar mname[F_NAMELEN+1];
- Xchar uname[F_NAMELEN+1];
- Xchar dname[F_NAMELEN+1]; /* directory name for aufs */
- Xchar iobuf[IOBUFSIZ];
- Xchar zbuf[128]; /* buffer of zeros to pad MacBinary forks */
- X
- Xint mode, txtmode, listonly, verbose, query, flatten;
- Xint bit, chkcrc, numfiles, depth;
- Xint aufs; /* aufs flag */
- Xint debug = 0;
- XFILE *infp;
- X
- Xlong get4();
- Xshort get2();
- Xunsigned short write_file();
- X
- X/********************************************************************************/
- X/* added for aufs, nicked from various places... */
- X
- X/* following from mcvert program */
- X
- X/* Useful, though not particularly Mac related, values */
- Xtypedef unsigned char byte; /* one byte, obviously */
- Xtypedef unsigned short word; /* must be 2 bytes */
- Xtypedef unsigned long ulong; /* 4 bytes */
- X
- X#define NAMELEN 63 /* maximum legal Mac file name length */
- X
- X/* Format of a bin file:
- XA bin file is composed of 128 byte blocks. The first block is the
- Xinfo_header (see below). Then comes the data fork, null padded to fill the
- Xlast block. Then comes the resource fork, padded to fill the last block. A
- Xproposal to follow with the text of the Get Info box has not been implemented,
- Xto the best of my knowledge. Version, zero1 and zero2 are what the receiving
- Xprogram looks at to determine if a MacBinary transfer is being initiated.
- X*/
- Xtypedef struct { /* info file header (128 bytes). Unfortunately, these
- X longs don't align to word boundaries */
- X byte version; /* there is only a version 0 at this time */
- X byte nlen; /* Length of filename. */
- X byte name[NAMELEN]; /* Filename (only 1st nlen are significant)*/
- X byte type[4]; /* File type. */
- X byte auth[4]; /* File creator. */
- X byte flags; /* file flags: LkIvBnSyBzByChIt */
- X byte zero1; /* Locked, Invisible,Bundle, System */
- X /* Bozo, Busy, Changed, Init */
- X byte icon_vert[2]; /* Vertical icon position within window */
- X byte icon_horiz[2]; /* Horizontal icon postion in window */
- X byte window_id[2]; /* Window or folder ID. */
- X byte protect; /* = 1 for protected file, 0 otherwise */
- X byte zero2;
- X byte dflen[4]; /* Data Fork length (bytes) - most sig. */
- X byte rflen[4]; /* Resource Fork length byte first */
- X byte cdate[4]; /* File's creation date. */
- X byte mdate[4]; /* File's "last modified" date. */
- X byte ilen[2]; /* GetInfo message length */
- X byte flags2; /* Finder flags, bits 0-7 */
- X byte unused[14];
- X byte packlen[4]; /* length of total files when unpacked */
- X byte headlen[2]; /* length of secondary header */
- X byte uploadvers; /* Version of MacBinary II that the uploading program is written for */
- X byte readvers; /* Minimum MacBinary II version needed to read this file */
- X byte crc[2]; /* CRC of the previous 124 bytes */
- X byte padding[2]; /* two trailing unused bytes */
- X } info_header;
- X
- X/* end of mcvert stuff */
- X/* from CAP aufs documentation */
- X
- X#define FINFOLEN 32
- X#define MAXCLEN 199
- Xtypedef struct
- X{ /* byte fi_fndr[FINFOLEN]; */ /* finder info */
- X /* what I think the above is... */
- X ulong fndr_type, fndr_creator;
- X word fndr_flags;
- X ulong fndr_loc;
- X word fndr_fldr;
- X word fndr_icon;
- X byte fndr_unused[8];
- X word fndr_comment;
- X ulong fndr_putaway;
- X /* end of fi_fndr */
- X
- X word fi_attr; /* attributes */
- X#define FI_MAGIC1 255
- X byte fi_magic1; /* was: length of comment */
- X#define FI_VERSION 0x10 /* version major 1, minor 0 */
- X /* if more than 8 versions then */
- X /* something wrong anyway */
- X byte fi_version; /* version number */
- X#define FI_MAGIC 0xda
- X byte fi_magic; /* magic word check */
- X byte fi_bitmap; /* bitmap of included info */
- X#define FI_BM_SHORTFILENAME 0x1 /* is this included? */
- X#define FI_BM_MACINTOSHFILENAME 0x2 /* is this included? */
- X byte fi_shortfilename[12+1]; /* possible short file name */
- X byte fi_macfilename[32+1]; /* possible macintosh file name */
- X byte fi_comln; /* comment length */
- X byte fi_comnt[MAXCLEN+1]; /* comment string */
- X} FileInfo;
- X
- XFileInfo fndr_info;
- X
- X/* end aufs */
- X/********************************************************************************/
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int status;
- X int c;
- X extern int optind;
- X extern char *optarg;
- X int errflg;
- X int macbin;
- X
- X mode = DEFAULT_MODE;
- X errflg = 0;
- X macbin = 0;
- X flatten = 0;
- X numfiles = 0;
- X depth = 0;
- X aufs = strcmp(argv[0], AUFSNAME) == 0;
- X
- X while ((c = getopt(argc, argv, "DMdflmqruvx")) != EOF)
- X switch (c) {
- X case 'r': /* extract resource fork only */
- X mode = RSRC;
- X break;
- X case 'd': /* extract data fork only */
- X mode = DATA;
- X break;
- X case 'u': /* extract data fork as Unix text file */
- X mode = TEXT;
- X break;
- X case 'l': /* list contents of archive */
- X listonly++;
- X break;
- X case 'q': /* query user on each extraction */
- X query++;
- X break;
- X case 'v': /* verbose mode */
- X verbose++;
- X break;
- X case 'x': /* don't decode data, just dump to files*/
- X mode = DUMP;
- X break;
- X case 'm': /* input file is in Macbinary format */
- X macbin = 1;
- X break;
- X case 'M': /* output file in OTHER_MODE */
- X mode = OTHER_MODE;
- X break;
- X case 'f': /* don't create flat directory tree */
- X flatten = 1;
- X break;
- X case 'D': /* debugging mode */
- X debug = 1;
- X break;
- X case '?':
- X errflg++;
- X break;
- X }
- X if (errflg) {
- X usage();
- X exit(1);
- X }
- X
- X /* -a incompatible with -M and -u */
- X if(aufs && (mode == MACBINARY || mode == TEXT))
- X { fprintf(stderr, "Aufs mode cannot be combined with MacBinary (-M) or text (-t) mode\n");
- X exit(1);
- X }
- X
- X if (optind == argc) {
- X usage();
- X exit(1);
- X }
- X else
- X while(optind < argc)
- X { if ((infp = fopen(argv[optind], "r")) == NULL)
- X { fprintf(stderr,"Can't open input file \"%s\"\n",argv[optind]);
- X exit(1);
- X }
- X
- X if (macbin) {
- X if (fseek(infp, MACBINHDRSIZE, 0) == -1) {
- X fprintf(stderr, "Can't skip over MacBinary header\n");
- X exit(1);
- X }
- X }
- X
- X if (readsithdr(&sithdr) == 0) {
- X fprintf(stderr, "Can't read file header\n");
- X exit(1);
- X }
- X if (debug) {
- X printf("archive header (%d bytes):\n", SITHDRSIZE);
- X printf("numFiles=%d, arcLength=%ld, version=%d\n",
- X sithdr.numFiles, sithdr.arcLength, sithdr.version & 0xff);
- X }
- X status = extract("", 0);
- X if(status < 0) exit(1);
- X
- X optind++;
- X }
- X
- X exit(0);
- X}
- X
- Xusage()
- X{
- X fprintf(stderr, "Usage: unsit/unstuffit [-rdulM] [-vqfm] filename\n");
- X}
- X
- X/*
- X extract(parent, skip) - Extract all files from the current folder.
- X char *parent; name of parent folder
- X int skip; 1 to skip all files and folders in this one
- X 0 to extract them
- X
- X returns 1 if came an endFolder record
- X 0 if EOF
- X -1 if error (bad fileHdr, bad file, etc.)
- X*/
- X
- Xextract(parent, skip)
- Xchar *parent;
- Xint skip;
- X{
- X struct fileHdr filehdr;
- X struct stat sbuf;
- X int status, rstat, sstat, skipit;
- X char name[256];
- X
- X while (1) {
- X rstat = readfilehdr(&filehdr, skip);
- X if (rstat == H_ERROR || rstat == H_EOF) {
- X status = rstat;
- X break;
- X }
- X if (debug) {
- X printf("file header (%d bytes):\n", FILEHDRSIZE);
- X printf("compRMethod=%d, compDMethod=%d\n",
- X filehdr.compRMethod, filehdr.compDMethod);
- X printf("rsrcLength=%ld, dataLength=%ld\n",
- X filehdr.rsrcLength, filehdr.dataLength);
- X printf("compRLength=%ld, compDLength=%ld\n",
- X filehdr.compRLength, filehdr.compDLength);
- X printf("rsrcCRC=%d=0x%04x, dataCRC=%d=0x%04x\n",
- X filehdr.rsrcCRC, filehdr.rsrcCRC,
- X filehdr.dataCRC, filehdr.dataCRC);
- X }
- X
- X skipit = (rstat == H_SKIP) ? 1 : 0;
- X
- X if (filehdr.compRMethod == endFolder &&
- X filehdr.compDMethod == endFolder) {
- X status = 1; /* finished with this folder */
- X break;
- X }
- X else if (filehdr.compRMethod == startFolder &&
- X filehdr.compDMethod == startFolder) {
- X if (!listonly && rstat == H_WRITE && !flatten) {
- X sstat = stat(uname, &sbuf);
- X if (sstat == -1) { /* directory doesn't exist */
- X if (mkdir(uname, 0777) == -1) {
- X fprintf(stderr,
- X "Can't create subdirectory %s\n", uname);
- X return(-1);
- X }
- X }
- X else { /* something exists with this name */
- X if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
- X fprintf(stderr, "Directory name %s already in use\n",
- X uname);
- X return(-1);
- X }
- X }
- X if(aufs) /* create .finderinfo & .resource subdirectories */
- X { strcpy(dname, uname);
- X strcat(dname, "/.finderinfo");
- X sstat = stat(dname, &sbuf);
- X if (sstat == -1) { /* directory doesn't exist */
- X if (mkdir(dname, 0777) == -1) {
- X fprintf(stderr,
- X "Can't create subdirectory %s\n", dname);
- X return(-1);
- X }
- X }
- X else { /* something exists with this name */
- X if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
- X fprintf(stderr, "Directory name %s already in use\n",
- X dname);
- X return(-1);
- X }
- X }
- X strcpy(dname, uname);
- X strcat(dname, "/.resource");
- X sstat = stat(dname, &sbuf);
- X if (sstat == -1) { /* directory doesn't exist */
- X if (mkdir(dname, 0777) == -1) {
- X fprintf(stderr,
- X "Can't create subdirectory %s\n", dname);
- X return(-1);
- X }
- X }
- X else { /* something exists with this name */
- X if ((sbuf.st_mode & S_IFMT) != S_IFDIR) {
- X fprintf(stderr, "Directory name %s already in use\n",
- X dname);
- X return(-1);
- X }
- X }
- X }
- X if (chdir(uname) == -1) {
- X fprintf(stderr, "Can't chdir to %s\n", uname);
- X return(-1);
- X }
- X sprintf(name,"%s:%s", parent, uname);
- X }
- X depth++;
- X status = extract(name, skipit);
- X depth--;
- X if (status != 1)
- X break; /* problem with folder */
- X if (depth == 0) /* count how many top-level files done */
- X numfiles++;
- X if (!flatten)
- X chdir("..");
- X }
- X else {
- X if ((status = extractfile(&filehdr, skipit)) != 1)
- X break;
- X if (depth == 0) /* count how many top-level files done */
- X numfiles++;
- X }
- X if (numfiles == sithdr.numFiles)
- X break;
- X }
- X return(status);
- X}
- X
- Xextractfile(fh, skip)
- Xstruct fileHdr *fh;
- Xint skip;
- X{
- X unsigned short crc;
- X FILE *fp, *fp1;
- X int n;
- X
- X f_data[0] = f_rsrc[0] = f_info[0] = '\0'; /* assume no output files */
- X /* figure out what file names to use and what to do */
- X if (!listonly && !skip) {
- X switch (mode) {
- X case MACPUT: /* do both rsrc and data forks */
- X if(aufs)
- X { sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
- X sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
- X sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
- X }
- X else
- X { sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
- X sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
- X sprintf(f_info, "%.*s.info", I_NAMELEN - 6, uname);
- X }
- X break;
- X case RSRC: /* rsrc fork only */
- X if(aufs)
- X { sprintf(f_rsrc, ".resource/%.*s", I_NAMELEN - 1, uname);
- X sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
- X }
- X else
- X sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
- X break;
- X case DATA: /* data fork only */
- X if(aufs)
- X { sprintf(f_data, "%.*s", I_NAMELEN - 1, uname);
- X sprintf(f_info, ".finderinfo/%.*s", I_NAMELEN - 1, uname);
- X }
- X else
- X sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
- X break;
- X case TEXT:
- X sprintf(f_data, "%.*s.text", I_NAMELEN - 6, uname);
- X break;
- X case DUMP: /* for debugging, dump data as is */
- X sprintf(f_data, "%.*s.ddump", I_NAMELEN - 7, uname);
- X sprintf(f_rsrc, "%.*s.rdump", I_NAMELEN - 7, uname);
- X fh->compRMethod = fh->compDMethod = noComp;
- X break;
- X case MACBINARY: /* output file in MacBinary format */
- X sprintf(f_data, "%.*s.data", I_NAMELEN - 6, uname);
- X sprintf(f_rsrc, "%.*s.rsrc", I_NAMELEN - 6, uname);
- X#ifndef ADDBIN
- X sprintf(f_info, "%.*s", I_NAMELEN - 1, uname);
- X#else
- X sprintf(f_info, "%.*s.bin", I_NAMELEN - 5, uname);
- X#endif /*ADDBIN*/
- X break;
- X }
- X }
- X
- X fp = NULL; /* so we can tell if a file is open */
- X if (f_info[0] != '\0' && check_access(f_info) != -1) {
- X fp = fopen(f_info, "w");
- X if (fp == NULL) {
- X perror(f_info);
- X exit(1);
- X }
- X if(aufs) /* convert info structure */
- X { register info_header *pinfo;
- X
- X pinfo = (info_header *)info;
- X
- X /* make the .finderinfo file */
- X bzero(&fndr_info, sizeof(FileInfo));
- X bcopy(pinfo->type, &fndr_info.fndr_type, 4);
- X bcopy(pinfo->auth, &fndr_info.fndr_creator, 4);
- X bcopy(&pinfo->flags, &fndr_info.fndr_flags, 2);
- X fndr_info.fi_magic1 = FI_MAGIC1;
- X fndr_info.fi_version = FI_VERSION;
- X fndr_info.fi_magic = FI_MAGIC;
- X fndr_info.fi_bitmap = FI_BM_MACINTOSHFILENAME;
- X bcopy(pinfo->name, fndr_info.fi_macfilename, pinfo->nlen);
- X
- X fwrite(&fndr_info, sizeof(FileInfo), 1, fp);
- X }
- X else
- X { if (mode == MACBINARY) { /* convert to MacBinary header */
- X /* taken from the macbin program */
- X if (info[74] & 0x40) info[81] = '\1'; /* protected */
- X info[74] = '\0'; /* clear zero2 */
- X info[82] = '\0'; /* force zero3 clear */
- X }
- X fwrite(info, 1, INFOBYTES, fp);
- X }
- X }
- X
- X if (f_rsrc[0] != '\0') {
- X txtmode = 0;
- X crc = write_file(f_rsrc, fh->compRLength,
- X fh->rsrcLength, fh->compRMethod);
- X if (chkcrc && fh->rsrcCRC != crc) {
- X fprintf(stderr,
- X "CRC error on resource fork: need 0x%04x, got 0x%04x\n",
- X fh->rsrcCRC, crc);
- X return(-1);
- X }
- X }
- X else {
- X fseek(infp, (long) fh->compRLength, 1);
- X }
- X if (f_data[0] != '\0') {
- X txtmode = (mode == TEXT);
- X crc = write_file(f_data, fh->compDLength,
- X fh->dataLength, fh->compDMethod);
- X if (chkcrc && fh->dataCRC != crc) {
- X fprintf(stderr,
- X "CRC error on data fork: need 0x%04x, got 0x%04x\n",
- X fh->dataCRC, crc);
- X return(-1);
- X }
- X }
- X else {
- X fseek(infp, (long) fh->compDLength, 1);
- X }
- X if (fp != NULL) {
- X /* if Macbinary output, copy the data and resource forks to the
- X end of the info file, and pad each to multiples of 128 bytes. */
- X if (mode == MACBINARY) {
- X fp1 = fopen(f_data, "r"); /* re-open the file we just wrote */
- X if (fp1 == NULL) {
- X perror(f_data);
- X exit(1);
- X }
- X while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
- X fwrite(iobuf, 1, n, fp); /* append it to the info file */
- X /* pad out to multiple of 128 if in MacBinary format */
- X n = fh->dataLength % 128;
- X if (n > 0)
- X outc(zbuf, 128 - n, fp);
- X fclose(fp1);
- X unlink(f_data);
- X fp1 = fopen(f_rsrc, "r"); /* re-open the file we just wrote */
- X if (fp1 == NULL) {
- X perror(f_rsrc);
- X exit(1);
- X }
- X while ((n = fread(iobuf, 1, IOBUFSIZ, fp1)) > 0)
- X fwrite(iobuf, 1, n, fp); /* append it to the info file */
- X /* pad out to multiple of 128 if in MacBinary format */
- X n = fh->rsrcLength % 128;
- X if (n > 0)
- X outc(zbuf, 128 - n, fp);
- X fclose(fp1);
- X unlink(f_rsrc);
- X }
- X fclose(fp);
- X }
- X return(1);
- X}
- X
- Xreadsithdr(s)
- Xstruct sitHdr *s;
- X{
- X char temp[FILEHDRSIZE];
- X int count = 0;
- X
- X for (;;) {
- X if (fread(temp, 1, SITHDRSIZE, infp) != SITHDRSIZE) {
- X fprintf(stderr, "Can't read file header\n");
- X return(0);
- X }
- X
- X if (strncmp(temp + S_SIGNATURE, "SIT!", 4) == 0 &&
- X strncmp(temp + S_SIGNATURE2, "rLau", 4) == 0) {
- X s->numFiles = get2(temp + S_NUMFILES);
- X s->arcLength = get4(temp + S_ARCLENGTH);
- X return(1);
- X }
- X
- X if (++count == 2) {
- X fprintf(stderr, "Not a StuffIt file\n");
- X return(0);
- X }
- X
- X if (fread(&temp[SITHDRSIZE], 1, FILEHDRSIZE - SITHDRSIZE, infp) !=
- X FILEHDRSIZE - SITHDRSIZE) {
- X fprintf(stderr, "Can't read file header\n");
- X return(0);
- X }
- X
- X if (strncmp(temp + I_TYPEOFF, "SIT!", 4) == 0 &&
- X strncmp(temp + I_AUTHOFF, "SIT!", 4) == 0) { /* MacBinary format */
- X fseek(infp, (long)(INFOBYTES-FILEHDRSIZE), 1); /* Skip over header */
- X }
- X }
- X}
- X
- X/*
- X readfilehdr - reads the file header for each file and the folder start
- X and end records.
- X
- X returns: H_ERROR = error
- X H_EOF = EOF
- X H_WRITE = write file/folder
- X H_SKIP = skip file/folder
- X*/
- X
- Xreadfilehdr(f, skip)
- Xstruct fileHdr *f;
- Xint skip;
- X{
- X unsigned short crc;
- X int i, n, write_it, isfolder;
- X char hdr[FILEHDRSIZE];
- X char ch, *mp, *up;
- X char *tp, temp[10];
- X
- X for (i = 0; i < INFOBYTES; i++)
- X info[i] = '\0';
- X
- X /* read in the next file header, which could be folder start/end record */
- X n = fread(hdr, 1, FILEHDRSIZE, infp);
- X if (n == 0) /* return 0 on EOF */
- X return(H_EOF);
- X else if (n != FILEHDRSIZE) {
- X fprintf(stderr, "Can't read file header\n");
- X return(H_ERROR);
- X }
- X
- X /* check the CRC for the file header */
- X crc = INIT_CRC;
- X crc = updcrc(crc, hdr, FILEHDRSIZE - 2);
- X f->hdrCRC = get2(hdr + F_HDRCRC);
- X if (f->hdrCRC != crc) {
- X fprintf(stderr, "Header CRC mismatch: got 0x%04x, need 0x%04x\n",
- X f->hdrCRC, crc);
- X return(H_ERROR);
- X }
- X
- X /* grab the name of the file or folder */
- X n = hdr[F_FNAME] & BYTEMASK;
- X if (n > F_NAMELEN)
- X n = F_NAMELEN;
- X info[I_NAMEOFF] = n;
- X copy(info + I_NAMEOFF + 1, hdr + F_FNAME + 1, n);
- X strncpy(mname, hdr + F_FNAME + 1, n);
- X mname[n] = '\0';
- X /* copy to a string with no illegal Unix characters in the file name */
- X mp = mname;
- X up = uname;
- X while ((ch = *mp++) != '\0') {
- X if (ch <= ' ' || ch > '~' || index("/!()[]*<>?\\\"$\';&`", ch) != NULL)
- X ch = '_';
- X *up++ = ch;
- X }
- X *up = '\0';
- X
- X /* get lots of other stuff from the header */
- X f->compRMethod = hdr[F_COMPRMETHOD];
- X f->compDMethod = hdr[F_COMPDMETHOD];
- X f->rsrcLength = get4(hdr + F_RSRCLENGTH);
- X f->dataLength = get4(hdr + F_DATALENGTH);
- X f->compRLength = get4(hdr + F_COMPRLENGTH);
- X f->compDLength = get4(hdr + F_COMPDLENGTH);
- X f->rsrcCRC = get2(hdr + F_RSRCCRC);
- X f->dataCRC = get2(hdr + F_DATACRC);
- X
- X /* if it's an end folder record, don't need to do any more */
- X if (f->compRMethod == endFolder && f->compDMethod == endFolder)
- X return(H_WRITE);
- X
- X /* prepare an info file in case its needed */
- X
- X copy(info + I_TYPEOFF, hdr + F_FTYPE, 4);
- X copy(info + I_AUTHOFF, hdr + F_CREATOR, 4);
- X copy(info + I_FLAGOFF, hdr + F_FNDRFLAGS, 2);
- X#ifdef INITED_BUG
- X info[INITED_OFF] &= INITED_MASK; /* reset init bit */
- X#endif
- X copy(info + I_DLENOFF, hdr + F_DATALENGTH, 4);
- X copy(info + I_RLENOFF, hdr + F_RSRCLENGTH, 4);
- X copy(info + I_CTIMOFF, hdr + F_CREATIONDATE, 4);
- X copy(info + I_MTIMOFF, hdr + F_MODDATE, 4);
- X
- X isfolder = f->compRMethod == startFolder && f->compDMethod == startFolder;
- X
- X /* list the file name if verbose or listonly mode, also if query mode */
- X if (skip) /* skip = 1 if skipping all in this folder */
- X write_it = 0;
- X else {
- X write_it = 1;
- X if (listonly || verbose || query) {
- X for (i = 0; i < depth; i++)
- X putchar(' ');
- X if (isfolder)
- X printf("Folder: \"%s\"", uname);
- X else
- X printf("name=\"%s\", type=%4.4s, author=%4.4s, data=%ld, rsrc=%ld",
- X uname, hdr + F_FTYPE, hdr + F_CREATOR,
- X f->dataLength, f->rsrcLength);
- X if (query) { /* if querying, check with the boss */
- X printf(" ? ");
- X fgets(temp, sizeof(temp) - 1, stdin);
- X tp = temp;
- X write_it = 0;
- X while (*tp != '\0') {
- X if (*tp == 'y' || *tp == 'Y') {
- X write_it = 1;
- X break;
- X }
- X else
- X tp++;
- X }
- X }
- X else /* otherwise, terminate the line */
- X putchar('\n');
- X }
- X }
- X return(write_it ? H_WRITE : H_SKIP);
- X}
- X
- Xcheck_access(fname) /* return 0 if OK to write on file fname, -1 otherwise */
- Xchar *fname;
- X{
- X char temp[10], *tp;
- X
- X if (access(fname, 0) == -1) {
- X return(0);
- X }
- X else {
- X printf("%s exists. Overwrite? ", fname);
- X fgets(temp, sizeof(temp) - 1, stdin);
- X tp = temp;
- X while (*tp != '\0') {
- X if (*tp == 'y' || *tp == 'Y') {
- X return(0);
- X }
- X else
- X tp++;
- X }
- X }
- X return(-1);
- X}
- X
- Xunsigned short write_file(fname, ibytes, obytes, type)
- Xchar *fname;
- Xunsigned long ibytes, obytes;
- Xunsigned char type;
- X{
- X unsigned short crc;
- X int i, n, ch, lastch;
- X FILE *outf;
- X char temp[256];
- X
- X crc = INIT_CRC;
- X chkcrc = 1; /* usually can check the CRC */
- X
- X if (check_access(fname) == -1) {
- X fseek(infp, ibytes, 1);
- X chkcrc = 0; /* inhibit crc check if file not written */
- X return(-1);
- X }
- X
- X switch (type) {
- X case noComp: /* no compression */
- X outf = fopen(fname, "w");
- X if (outf == NULL) {
- X perror(fname);
- X exit(1);
- X }
- X while (ibytes > 0) {
- X n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
- X n = fread(iobuf, 1, n, infp);
- X if (n == 0)
- X break;
- X crc = updcrc(crc, iobuf, n);
- X outc(iobuf, n, outf);
- X ibytes -= n;
- X }
- X fclose(outf);
- X break;
- X case rleComp: /* run length encoding */
- X outf = fopen(fname, "w");
- X if (outf == NULL) {
- X perror(fname);
- X exit(1);
- X }
- X while (ibytes > 0) {
- X ch = getc(infp) & 0xff;
- X ibytes--;
- X if (ch == 0x90) { /* see if its the repeat marker */
- X n = getc(infp) & 0xff; /* get the repeat count */
- X ibytes--;
- X if (n == 0) { /* 0x90 was really an 0x90 */
- X iobuf[0] = 0x90;
- X crc = updcrc(crc, iobuf, 1);
- X outc(iobuf, 1, outf);
- X }
- X else {
- X n--;
- X for (i = 0; i < n; i++)
- X iobuf[i] = lastch;
- X crc = updcrc(crc, iobuf, n);
- X outc(iobuf, n, outf);
- X }
- X }
- X else {
- X iobuf[0] = ch;
- X crc = updcrc(crc, iobuf, 1);
- X lastch = ch;
- X outc(iobuf, 1, outf);
- X }
- X }
- X fclose(outf);
- X break;
- X case lzwComp: /* LZW compression */
- X sprintf(temp, "%s%s", COMPRESS, " -d -c -n -b 14 ");
- X if (txtmode) {
- X strcat(temp, "| tr \'\\015\' \'\\012\' ");
- X chkcrc = 0; /* can't check CRC in this case */
- X }
- X strcat(temp, "> '");
- X strcat(temp, fname);
- X strcat(temp, "'");
- X outf = popen(temp, "w");
- X if (outf == NULL) {
- X perror(fname);
- X exit(1);
- X }
- X while (ibytes > 0) {
- X n = (ibytes > IOBUFSIZ) ? IOBUFSIZ : ibytes;
- X n = fread(iobuf, 1, n, infp);
- X if (n == 0)
- X break;
- X fwrite(iobuf, 1, n, outf);
- X ibytes -= n;
- X }
- X pclose(outf);
- X if (chkcrc) {
- X outf = fopen(fname, "r"); /* read the file to get CRC value */
- X if (outf == NULL) {
- X perror(fname);
- X exit(1);
- X }
- X while (1) {
- X n = fread(iobuf, 1, IOBUFSIZ, outf);
- X if (n == 0)
- X break;
- X crc = updcrc(crc, iobuf, n);
- X }
- X fclose(outf);
- X }
- X break;
- X case hufComp: /* Huffman compression */
- X outf = fopen(fname, "w");
- X if (outf == NULL) {
- X perror(fname);
- X exit(1);
- X }
- X nodeptr = nodelist;
- X bit = 0; /* put us on a byte boundary */
- X read_tree();
- X while (obytes > 0) {
- X n = (obytes > IOBUFSIZ) ? IOBUFSIZ : obytes;
- X for (i = 0; i < n; i++)
- X iobuf[i] = gethuffbyte(DECODE);
- X crc = updcrc(crc, iobuf, n);
- X outc(iobuf, n, outf);
- X obytes -= n;
- X }
- X fclose(outf);
- X break;
- X default:
- X fprintf(stderr, "Unknown compression method\n");
- X chkcrc = 0; /* inhibit crc check if file not written */
- X return(-1);
- X }
- X
- X return(crc & 0xffff);
- X}
- X
- Xoutc(p, n, fp)
- Xchar *p;
- Xint n;
- XFILE *fp;
- X{
- X register char *p1;
- X register int i;
- X if (txtmode) {
- X for (i = 0, p1 = p; i < n; i++, p1++)
- X if ((*p1 & BYTEMASK) == '\r')
- X *p1 = '\n';
- X }
- X fwrite(p, 1, n, fp);
- X}
- X
- Xlong get4(bp)
- Xchar *bp;
- X{
- X register int i;
- X long value = 0;
- X
- X for (i = 0; i < 4; i++) {
- X value <<= 8;
- X value |= (*bp & BYTEMASK);
- X bp++;
- X }
- X return(value);
- X}
- X
- Xshort get2(bp)
- Xchar *bp;
- X{
- X register int i;
- X int value = 0;
- X
- X for (i = 0; i < 2; i++) {
- X value <<= 8;
- X value |= (*bp & BYTEMASK);
- X bp++;
- X }
- X return(value);
- X}
- X
- Xcopy(p1, p2, n)
- Xchar *p1, *p2;
- Xint n;
- X{
- X while (n-- > 0)
- X *p1++ = *p2++;
- X}
- X
- X/* This routine recursively reads the Huffman encoding table and builds
- X and decoding tree. */
- X
- Xstruct node *read_tree()
- X{
- X struct node *np;
- X np = nodeptr++;
- X if (getbit() == 1) {
- X np->flag = 1;
- X np->byte = gethuffbyte(NODECODE);
- X }
- X else {
- X np->flag = 0;
- X np->zero = read_tree();
- X np->one = read_tree();
- X }
- X return(np);
- X}
- X
- X/* This routine returns the next bit in the input stream (MSB first) */
- X
- Xgetbit()
- X{
- X static char b;
- X if (bit == 0) {
- X b = getc(infp) & 0xff;
- X bit = 8;
- X }
- X bit--;
- X return((b >> bit) & 1);
- X}
- X
- X/* This routine returns the next 8 bits. If decoding is on, it finds the
- Xbyte in the decoding tree based on the bits from the input stream. If
- Xdecoding is not on, it either gets it directly from the input stream or
- Xputs it together from 8 calls to getbit(), depending on whether or not we
- Xare currently on a byte boundary
- X*/
- Xgethuffbyte(decode)
- Xint decode;
- X{
- X register struct node *np;
- X register int i, b;
- X if (decode == DECODE) {
- X np = nodelist;
- X while (np->flag == 0)
- X np = (getbit()) ? np->one : np->zero;
- X b = np->byte;
- X }
- X else {
- X if (bit == 0) /* on byte boundary? */
- X b = getc(infp) & 0xff;
- X else { /* no, put a byte together */
- X b = 0;
- X for (i = 8; i > 0; i--) {
- X b = (b << 1) + getbit();
- X }
- X }
- X }
- X return(b);
- X}
- END_OF_FILE
- if test 31819 -ne `wc -c <'unstuffit/unsit.c'`; then
- echo shar: \"'unstuffit/unsit.c'\" unpacked with wrong size!
- fi
- # end of 'unstuffit/unsit.c'
- fi
- echo shar: End of archive 4 \(of 4\).
- cp /dev/null ark4isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --- end of part 4 ---
-