home *** CD-ROM | disk | FTP | other *** search
- From: jac@paul.rutgers.edu (Jonathan A. Chandross)
- Newsgroups: comp.sources.apple2
- Subject: v001SRC028: Unix Archiving Tools (Part 2/2)
- Message-ID: <Feb.16.22.44.19.1991.3114@paul.rutgers.edu>
- Date: 17 Feb 91 03:44:19 GMT
- Approved: jac@paul.rutgers.edu
-
-
- Submitted-by: marcel@duteca.tudelft.nl
- Posting-number: Volume 1, Source:28
- Archive-name: archive/unix/marcel/part2
- Architecture: UNIX
- Version-number: 1.00
-
- This is part 2 of a 2 part posting.
-
- =sciibin.c
- -/* @(#) sciibin.c 3.01 12Feb91 */
- -/*************************************************************************
- - ** **
- - ** Name : sciibin **
- - ** Author : Marcel J.E. Mol **
- - ** Date : 06Mar89 (first release) **
- - ** Version : 2.00 **
- - ** Files : sciibin.c Main source file **
- - ** Purpose : Extract or view BinSCII files **
- - ** **
- - ** ------------------------- Revision List ------------------------- **
- - ** Ver Date Name Remarks **
- - ** 1.00 06Mar89 Marcel Mol First release **
- - ** 1.10 27Mar89 Marcel Mol Fished things up, error routine, **
- - ** linecount, all info fields filled **
- - ** in, changed info layout. **
- - ** 2.00 03Jun89 Marcel Mol Bug fixes: alphabet to unsigned **
- - ** (Dave Whitney) char. Some OS's need types.h. **
- - ** Fixed CRE/MOD order. **
- - ** Output filenames can be wrong **
- - ** when multiple files are **
- - ** extracted. Made crc and file- **
- - ** type arrays in seperate includes **
- - ** 3.00 22Mar90 Marcel Mol Includeed ports of Bruce Kahn **
- - ** 1.30 27 Feb 90 Bruce Kahn Ported to AOS/VS C 4.01 and MSC 5.1 **
- - ** Added explicit long definitions **
- - ** needed. **
- - ** Redid layouts for dates to be US. **
- - ** Modified the open routines for MSC **
- - ** to include binary mode, not text. **
- - ** Changed the way 8 bit integers are **
- - ** handled (redone MM). **
- - ** Added getopt() (see below MM). **
- - ** 3.01 22Feb91 Marcel Mol Fixed bug: only close output **
- - ** when output is generated. **
- - ** ================================================================= **
- - ** **
- - ** Compile as follows: **
- - ** If you don't have getopt, compile and link the given getopt.c **
- - ** **
- - ** UNIX: cc sciibin.c -Oso sciibin **
- - ** **
- - ** MSC 5.1: cl /c /Ox sciibin.c **
- - ** (add /DMSDOS, if MSC didn't do it) **
- - ** link /CO /STACK:10000 sciibin; **
- - ** **
- - ** AOS/VS: cc sciibin.c **
- - ** ccl sciibin **
- - ** **
- - ** Defining DEBUG gives some debug information. **
- - ** Defining DEBUGALL gives input and output of the decode routine. **
- - ** **
- - ** Usage: sciibin [-hvtc] [-o<outputfile>] <infiles> **
- - ** **
- - ** -v show only info on file, do not create output. **
- - ** -t test file, do not create output. **
- - ** -c do not check checksums. **
- - ** -o create given filename instead of the one in **
- - ** binscii file. Use this only if the input files **
- - ** contain only one output file. **
- - ** -h help. **
- - ** **
- - ** **
- - ** This software is freeware. We can not be held responsible to **
- - ** any damage this program may coase you or anyone or anything else. **
- - ** **
- - ** Mail bugs to: marcel@duteca.tudelft.nl **
- - ** **
- - ************************************************************************/
- -
- -
- -#include <stdio.h>
- -#include <sys/types.h> /* keep sun OS happy */
- -#include <sys/stat.h> /* mostly includes types.h ... */
- -#if defined(MSDOS)
- -#include <memory.h> /* For the memset function */
- -#endif
- -#include "crc.h"
- -#include "filetype.h"
- -
- -#define BUFLEN 256
- -#define FILENAME_LEN 15
- -#define BINSCII_HEADER "FiLeStArTfIlEsTaRt\n"
- -#define MAXSEGLEN 0x3000
- -
- -#if defined(INT8)
- -typedef long int16;
- -#else
- -typedef int int16;
- -#endif
- -
- -/* ==> Expect int variables to be at least 16 bits
- - * Global variables ==> and longs to be at least 32 bits
- - * ==> If not, you have some work to do...
- - */ /* MSDOS has 16 bit ints. */
- -char buf[BUFLEN+1];
- -unsigned char dec[BUFLEN+1];
- -unsigned char alphabet[BUFLEN+1]; /* need $FF in alphabet */
- -char outfilename[BUFLEN+1];
- -
- -
- -unsigned char outflag = 0, /* the -o option */
- - crcflag = 0, /* the -c option */
- - infoflag = 0, /* the -v option */
- - testflag = 0, /* the -t option */
- - makeoutput, /* ! (-t | -v) */
- - crcok; /* -t | -c */
- -FILE *outfp; /* output file */
- -
- -unsigned char filetype, stortype,
- - file_access; /* access -> file_access for MSDOS */
- -unsigned char modyear, modmonth, modday, modhour, modmin,
- - creyear, cremonth, creday, crehour, cremin;
- -int namlen, linecount,
- - numblocks, auxtype;
- -long filesize, startbyte, segmentlen;
- -char * infilename;
- -
- -char * progname;
- -
- -
- -/*
- - * function declarations
- - */
- -int main ();
- -int sciibin ();
- -int getheader ();
- -int decode ();
- -int decodestring ();
- -char *myfgets ();
- -void usage ();
- -void error ();
- -
- -
- -char * copyright = "@(#) sciibin.c 3.01 12Feb91 (c) 1989, 1991 M.J.E. Mol";
- -
- -main(argc, argv)
- -int argc;
- -char **argv;
- -{
- - FILE *fp;
- - int c;
- - extern int optind; /* For getopt */
- - extern char * optarg; /* For getopt */
- - int flag; /* Flag for getopt */
- -
- - progname = *argv;
- -
- - while ((flag = getopt(argc, argv, "hvcto:")) != EOF) { /* Process options */
- - switch (flag) {
- - case 'v': infoflag = 1; /* Want only info of file */
- - break;
- - case 'h': usage(); /* Give help */
- - exit(0);
- - case 'c': crcflag = 1;
- - break;
- - case 't': testflag = 1;
- - break;
- - case 'o':
- -#if defined(MSDOS)
- - memset(outfilename, NULL, FILENAME_LEN + 1);
- -#endif
- - strcpy(outfilename, optarg);
- - outflag = 1;
- - break;
- - default : fprintf(stderr, "%s: skipping unkown flag %c, use -h.\n",
- - progname, flag);
- - break;
- - }
- - }
- -
- - makeoutput = !(testflag | infoflag);
- - crcok = testflag | crcflag;
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "make output: %d, crcok: %d\n", makeoutput, crcok);
- -#endif
- -
- - if (optind >= argc) { /* No files given, use stdin */
- - infilename = "stdin";
- - linecount = 0;
- - sciibin(stdin);
- - }
- - else
- - while (optind < argc) {
- - infilename = argv[optind];
- - optind++;
- - if ((fp = fopen(infilename, "r")) == NULL) {
- - perror(infilename);
- - continue;
- - }
- - linecount = 0;
- - sciibin(fp);
- - fclose(fp);
- - }
- -
- - exit(0);
- -
- -} /* main */
- -
- -
- -
- -/*
- - * Walk over the file processing all segments in it
- - */
- -sciibin(fp)
- -FILE *fp;
- -{
- - int processed = 0; /* number of processed binscii segments */
- - int status = 0; /* return codes of calls to decode */
- -
- - while (myfgets(buf, BUFLEN, fp) != NULL) {
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) get start:%s", infilename, buf);
- -#endif
- -
- - if (!strncmp(buf, BINSCII_HEADER, strlen(BINSCII_HEADER))) {
- - if (!getheader(fp) && !infoflag) /* if header ok and not -v flag */
- - status |= decode(fp);
- - processed++;
- - }
- - }
- -
- - if (processed == 0) {
- - error("not a BinSCII file");
- - return 1;
- - }
- -
- - return status;
- -
- -} /* sciibin */
- -
- -
- -
- -/*
- - * Build the alphabet, get the output file info and open output file
- - * if necessary.
- - * Still contains lots of debug code to find out the header structure.
- - * (every bit is known now...)
- - */
- -getheader(fp)
- -FILE *fp;
- -{
- - register int i, j;
- - register int16 crc = 0;
- - struct stat statbuf; /* MUST know if file exists */
- - char *iomod; /* write or readwrite a file */
- -
- - /*
- - * Get the alphabet
- - */
- - if (myfgets(buf, BUFLEN, fp) == NULL) {
- - error("reading alphabet: unexpected end of file");
- - return 1;
- - }
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) alphabet:%s", infilename, buf);
- -#endif
- -
- - if (strlen(buf) != 65) {
- - error("alphabet corrupted");
- - return 1;
- - }
- -
- - /*
- - * Process the alphabet
- - */
- - for (i = 0; i < BUFLEN; i++)
- - alphabet[i] = 0xff;
- -
- - for (i = 0; i < 64; i++) {
- - j = buf[i];
- - if (alphabet[j] != 0xff)
- - error("Warning: double character in alphabet");
- - alphabet[j] = i;
- - }
- -
- -#if defined(DEBUG)
- - for (i = 0; i < BUFLEN; i+=16) {
- - fprintf(stderr, "(%s) alphabet[%3d] =", infilename, i);
- - for (j = 0; j < 16; j++)
- - fprintf(stderr, " %02X", alphabet[i+j]);
- - putc('\n', stderr);
- - }
- -#endif
- -
- - /*
- - * Get the file header
- - */
- - if (myfgets(buf, BUFLEN, fp) == NULL) {
- - error("reading fileheader: unexpected end of file");
- - return 1;
- - }
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) fileheader:%s", infilename, buf);
- -#endif
- -
- - /*
- - * Extract output filename if needed
- - */
- - if (!outflag) {
- - namlen = *buf - 'A' + 1; /* IS +1 NEEDED ?? */
- -#if defined(MSDOS)
- - memset(outfilename, NULL, FILENAME_LEN + 1);
- -#endif
- - strncpy(outfilename, buf+1, namlen);
- - outfilename[namlen] = '\0';
- - }
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) filename:**%s**\n", infilename, outfilename);
- - fprintf(stderr, "(%s) fileinfo:**%s**", infilename, buf+16);
- -#endif
- -
- - /*
- - * Decode and process the file header information
- - */
- - if ((i = decodestring(buf+FILENAME_LEN+1, dec)) != 27)
- - error("warning: corrupted file header length");
- -
- - for (i = 0; i < 24; i++)
- - crc = updcrc(dec[i], crc);
- -
- - if (crc != (dec[24] | (dec[25] << 8))) {
- - if (crcok)
- - error("warning: CRC error in file header");
- - else {
- - error("error: CRC error in file header");
- - return 1;
- - }
- - }
- -
- - /* Calculate file length */
- - filesize = dec[0] + (dec[1]<<8) + ((long) dec[2]<<16);
- - startbyte = dec[3] + (dec[4]<<8) + ((long) dec[5]<<16);
- -
- - /* Calculate file attributes and size */
- - file_access= dec[6];
- - filetype = dec[7];
- - auxtype = dec[8] + (dec[9] << 8);
- - stortype = dec[10];
- - numblocks = dec[11] + (dec[12]<<8);
- -
- - /* Calculate creation and modification dates */
- -#define MOD 13
- -#define CRE 17 /* perhaps creation and modification date are swapped */
- - creday = dec[CRE] & 0x1f;
- - cremonth = ((dec[CRE+1] & 0x01) << 3) | (dec[CRE] >> 5);
- - creyear = dec[CRE+1] >>1;
- - cremin = dec[CRE+2] & 0x3f;
- - crehour = dec[CRE+3] & 0x1f;
- - modday = dec[MOD] & 0x1f;
- - modmonth = ((dec[MOD+1] & 0x01) << 3) | (dec[MOD] >> 5);
- - modyear = dec[MOD+1] >>1;
- - modmin = dec[MOD+2] & 0x3f;
- - modhour = dec[MOD+3] & 0x1f;
- -
- - segmentlen = dec[21] + (dec[22]<<8) + ((long) dec[23]<<16);
- - if (segmentlen > MAXSEGLEN)
- - error("warning: segmentlen probably to long");
- -
- -#define READ 0x01
- -#define WRITE 0x02
- -#define BACKUP 0x20
- -#define RENAME 0x40
- -#define DESTROY 0x80
- -
- - if (infoflag) {
- -
- - /* Display the files name, type and auxtype */
- - printf("%-15s %3s aux: $%04X ",
- - outfilename, filetypes[filetype], auxtype);
- -
- - /* Display the file access type */
- - putchar(file_access & READ ? 'r' : '-');
- - putchar(file_access & WRITE ? 'w' : '-');
- - putchar(file_access & RENAME ? 'n' : '-');
- - putchar(file_access & DESTROY ? 'd' : '-');
- - putchar(file_access & BACKUP ? 'b' : '-');
- -
- - /* Display the type of file this is - ProDOS Specific */
- - switch (stortype) {
- - case 0x0F : printf(" voldir"); break;
- - case 0x0D : printf(" dir"); break;
- - case 0x01 : printf(" seed"); break;
- - case 0x02 : printf(" sap"); break;
- - case 0x03 : printf(" tree"); break;
- - default : printf(" ???"); break;
- - }
- -
- - /* Display modification and creation information */
- - printf(" %02d/%02d/%02d(%02d:%02d) -", modmonth, modday, modyear,
- - modhour, modmin);
- - printf(" %02d/%02d/%02d(%02d:%02d)\n", cremonth, creday, creyear,
- - crehour, cremin);
- -
- - /* Display segment information */
- - printf("Part %4d of %4d,", (int) (startbyte / MAXSEGLEN) + 1,
- - (int) ((filesize + MAXSEGLEN-1) / MAXSEGLEN));
- - printf(" bytes %7ld to %7ld of %7ld bytes, %5d blocks\n",
- - startbyte, startbyte+segmentlen, filesize, numblocks);
- -
- - } /* if (infoflag) */
- -
- - if (makeoutput) {
- - /* will creating output, not just information so verify the access */
- -#if defined(MSDOS)
- - iomod = (stat(outfilename, &statbuf) == 0) ? "r+b" : "wb";
- -#else
- - iomod = (stat(outfilename, &statbuf) == 0) ? "r+" : "w";
- -#endif
- - if ((outfp = fopen(outfilename, iomod)) == NULL) {
- - error("unable to open output file");
- - perror(outfilename);
- - return 1;
- - }
- - fseek(outfp, startbyte, 0);
- - } /* if (makeoutput) */
- -
- - return 0;
- -
- -} /* getheader */
- -
- -
- -
- -/*
- - * Do the actual decoding of the bin data.
- - */
- -decode(fp)
- -FILE *fp;
- -{
- - register int i;
- - register int crc = 0;
- - int len;
- -
- - crc = 0;
- - while (segmentlen > 0) {
- - if (myfgets(buf, BUFLEN, fp) == NULL) {
- - error("reading file: unexpected end of file");
- - return 1;
- - }
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) data:%s", infilename, buf);
- -#endif
- -
- - if ((len = decodestring(buf, dec)) != 48)
- - error("warning: corrupted line length");
- - for (i = 0; i < 48; i++)
- - crc = updcrc(dec[i], crc);
- - if (makeoutput)
- - for (i = 0; (i < len) && (segmentlen > 0); i++, segmentlen--)
- - putc(dec[i], outfp); /* COULD CR/NL TXT FILES */
- - else
- - segmentlen -= len;
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) still need %d bytes\n", infilename, segmentlen);
- -#endif
- -
- - }
- -
- - /*
- - * must be at end of segment now, with one remaining line containing
- - * the crc check.
- - */
- - if (myfgets(buf, BUFLEN, fp) == NULL) {
- - error("reading file crc: unexpected end of file");
- - return 1;
- - }
- -
- -#if defined(DEBUG)
- - fprintf(stderr, "(%s) crc:%s", infilename, buf);
- -#endif
- -
- - if ((len = decodestring(buf, dec)) != 3)
- - error("warning: corrupted crc length");
- - if (crc != (dec[0] | (dec[1] << 8))) {
- - if (crcok)
- - error("warning: CRC error in file data");
- - else {
- - error("error: CRC error in file data");
- - return 1;
- - }
- - }
- -
- - if (makeoutput)
- - fclose(outfp);
- -
- - return 0;
- -
- -} /* decode */
- -
- -
- -/*
- - * Decode one string off scii characters to binary data, meanwhile
- - * calculating crc.
- - */
- -decodestring(in, out)
- -register char *in;
- -register unsigned char *out;
- -{
- - register int len = 0;
- -
- -#if defined(DEBUGALL)
- - char *b;
- -
- - fprintf(stderr, "(%s) decode in: %s\n", infilename, in);
- - b = in;
- - while (*b)
- - fprintf(stderr, ".%02X", alphabet[*b++]);
- - putc('\n', stderr);
- - b = out;
- -#endif
- -
- - while (strlen(in) > 3) {
- - *out++ = ((alphabet[in[3]] << 2) | (alphabet[in[2]] >> 4)) & 0xFF;
- - *out++ = ((alphabet[in[2]] << 4) | (alphabet[in[1]] >> 2)) & 0xFF;
- - *out++ = ((alphabet[in[1]] << 6) | (alphabet[in[0]])) & 0xFF;
- - len += 3;
- - in += 4;
- - }
- -
- - *out = '\0';
- - if (*in != '\0' && *in != '\n')
- - error("warning: line not ended by NULL or NEWLINE");
- -
- -#if defined(DEBUGALL)
- - fprintf(stderr, "(%s) decode out:\n", infilename);
- - while (b != out)
- - fprintf(stderr, ".%02X", *b++);
- - putc('\n', stderr);
- -#endif
- -
- - return len;
- -
- -} /* decodestring */
- -
- -
- -
- -char *myfgets(buf, len, fp)
- -char *buf;
- -int len;
- -FILE *fp;
- -{
- -
- - linecount++;
- -
- - return fgets(buf, len, fp);
- -
- -} /* myfgets */
- -
- -
- -
- -void usage()
- -{
- -
- - fprintf(stderr, "%s\n\n", copyright);
- - fprintf(stderr, "Usage: sciibin [-vtch] [-o<outputfile>] <infiles>\n\n");
- - fprintf(stderr, " -v show only info on file, do not create output.\n");
- - fprintf(stderr, " -t test file, do not create output.\n");
- - fprintf(stderr, " -c do not check checksums.\n");
- - fprintf(stderr, " -o create given filename instead of the one in\n");
- - fprintf(stderr, " binscii file. Use this only if the input files\n");
- - fprintf(stderr, " contain only one output file.\n");
- - fprintf(stderr, " -h this help message.\n");
- -
- -} /* usage */
- -
- -
- -
- -void error(str)
- -char *str;
- -{
- -
- - fprintf(stderr, "%s (%s, %d): %s\n",
- - progname, infilename, linecount, str);
- -
- -} /* error */
- -
- =unblu.c
- -/* @(#) unblu.c 2.2 18/06/89 */
- -/*************************************************************************
- - ** **
- - ** Name : unblu **
- - ** Author : Marcel J.E. Mol **
- - ** Date : 10/05/88 (first release) **
- - ** Version : 2.20 **
- - ** Files : unblu.c Main source file **
- - ** **
- - ** ------------------------- Revision List ------------------------- **
- - ** Ver Date Name Remarks **
- - ** 1.00 10/05/88 Marcel Mol Raw copy of a basic program**
- - ** 2.00 03/06/88 Marcel Mol Rewrite after blu info **
- - ** was send to the net **
- - ** 2.10 18/06/88 Marcel Mol Added filetype texts **
- - ** 2.20 23/09/88 Marcel Mol Show mod and creation time **
- - ** **
- - ** ================================================================= **
- - ** **
- - ** Compile as follows: cc unblu.c -Oso unblu **
- - ** **
- - ** Usage: unblu [-vh] <arcfile> [<files-toextract>] **
- - ** **
- - ************************************************************************/
- -
- - /************************************************************************
- - ** **
- - ** NAME **
- - ** unblu - Extract files from an apple binary ][ archive. **
- - ** **
- - ** **
- - ** SYNOPSIS **
- - ** unblu [-vh] arcfile [files-to-extract] **
- - ** **
- - ** **
- - ** DESCRIPTION **
- - ** Unblu list the contents of a binary ][ archive (the -v option) **
- - ** or extracts the listed files from the archive (without the **
- - ** -v option). If no files are listed, the comlete archive is **
- - ** extracted or listed. **
- - ** The -h option gives a help message on the usage of unblu. **
- - ** **
- - ** AUTHOR **
- - ** Marcel J.E. Mol **
- - ** **
- - ** BUGS **
- - ** Mail bugs to: marcel@duteca.tudelft.nl **
- - ** **
- - ************************************************************************/
- -
- -char * copyright = "@(#) unblu.c 2.2 18/06/89 (c) M.J.E. Mol";
- -#include <stdio.h>
- -#include <fcntl.h>
- -#include "filetype.h"
- -
- -#define BUFSIZE 128 /* Blu block length */
- -#define DEBUG
- -
- -/* Global variables */
- -char * progname;
- -char * blufile;
- -int verbose = 0;
- -
- -
- -/* Function declarations */
- -void main ();
- -void unblu ();
- -void process_file ();
- -void extract_file ();
- -void print_global_info ();
- -int want ();
- -void usage ();
- -void printhelp ();
- -
- -
- -void main(argc, argv)
- -int argc;
- -char ** argv;
- -{
- - int flag; /* Flag for getopt */
- - int bfd; /* File descriptor for blu file */
- - extern int optind; /* For getopt */
- - extern char * optarg; /* For getopt */
- -
- - progname = argv[0];
- - while ((flag = getopt(argc, argv, "vh")) != EOF) { /* Process options */
- - switch (flag) {
- - case 'v': verbose = 1; /* Want only listing of archive */
- - break;
- - case 'h': usage(); /* Give help */
- - printhelp();
- - exit(0);
- - default : fprintf(stderr, "%s: skipping unkown flag %c.\n",
- - progname, flag);
- - break;
- - }
- - }
- -
- - if (optind >= argc) { /* No archive given */
- - usage();
- - exit(1);
- - }
- -
- - blufile = argv[optind++]; /* Get archive name */
- - if ((bfd = open(blufile, O_RDONLY)) == -1) {
- - perror(blufile);
- - exit(2);
- - }
- -
- - unblu(bfd, &argv[optind]); /* Process wanted files */
- -
- - close(bfd);
- -
- - exit(0);
- -
- -} /* main */
- -
- -
- -/*
- - * unblu -- process a binary II file fd, and process the filenames
- - * listed in wated. If wanted is \0, all files are processed.
- - */
- -void unblu(fd, wanted)
- -int fd;
- -char ** wanted;
- -{
- - unsigned char buf[BUFSIZE];
- - int firstblock = 1; /* First block needs special processing */
- - int tofollow = 1; /* Files to follow in the archive */
- - int n;
- -
- - while (tofollow && ((n = read(fd, buf, BUFSIZE)) != -1)) {
- - /* If there is a header block */
- - if (n != BUFSIZE) {
- - fprintf(stderr, "%s: %s file size is broken\n", progname, blufile);
- - exit(1);
- - }
- - if ((buf[0] != 10) || (buf[1] != 71) ||
- - (buf[2] != 76) || (buf[18] != 2)) {
- - fprintf(stderr, "%s: %s not a binary II file\n", progname, blufile);
- - exit(1);
- - }
- - tofollow = buf[127]; /* How many files to follow */
- - if (firstblock && verbose) {
- - print_global_info(buf);
- - firstblock = 0;
- - }
- - process_file(fd, buf, wanted); /* process the file for it */
- - }
- - return;
- -
- -} /* unblu */
- -
- -
- -/*
- - * process_file -- retrieve or print file information of file given
- - * in buf
- - */
- -void process_file(fd, buf, wanted)
- -int fd;
- -unsigned char * buf;
- -char ** wanted;
- -{
- - int tf;
- - int ftype;
- - int dflags;
- - int fnamelen;
- - int filelen;
- - char fname[64];
- - int nblocks;
- - int modyear, modmonth, modday;
- - int creyear, cremonth, creday;
- - int modhour, modsec;
- - int crehour, cresec;
- -
- - /*
- - * Get fileinfo
- - */
- - ftype = buf[4]; /* File type */
- - fnamelen = buf[23]; /* filename */
- - strncpy(fname, &buf[24], fnamelen);
- - fname[fnamelen] = '\0';
- - dflags = buf[125]; /* Data flags */
- - tf = buf[127]; /* Number of files to follow */
- - filelen = buf[20] + (buf[21]<<8) + (buf[22]<<16);/* Calculate file length */
- - nblocks = (filelen + BUFSIZE-1) / BUFSIZE;
- - modyear = buf[11] >>1;
- - modday = buf[10] & 0x1f;
- - modmonth= ((buf[11] & 0x01) << 3) + (buf[10] >> 5);
- - modhour = buf[13] & 0x1f;
- - modsec = buf[12] & 0x3f;
- - creyear = buf[15] >>1;
- - creday = buf[14] & 0x1f;
- - cremonth= ((buf[15] & 0x01) << 3) + (buf[14] >> 5);
- - crehour = buf[17] & 0x1f;
- - cresec = buf[16] & 0x3f;
- -
- -
- - if (*wanted == NULL || want(fname, wanted)) {
- - if (verbose) { /* print file information */
- - printf("%-15s %3s", fname, filetypes[ftype]);
- - printf(" %02d/%02d/%02d(%02d:%02d)", modyear, modmonth, modday,
- - modhour, modsec);
- - printf(" - %02d/%02d/%02d(%02d:%02d)", creyear, cremonth, creday,
- - crehour, cresec);
- - printf(" %5d bytes ", filelen);
- - if (dflags == 0)
- - printf("stored");
- - else {
- - if (dflags & 128) {
- - printf("squeezed");
- - }
- - if (dflags & 64) {
- - printf("encrypted");
- - }
- - if (dflags & 1)
- - printf("packed");
- - }
- - putchar('\n');
- -
- - if (ftype != 15) /* If not a directory */
- - lseek(fd, BUFSIZE*nblocks, 1); /* Seek to next file */
- - }
- - else if (ftype != 15)
- - extract_file(fd, fname, filelen);
- - }
- - else if (ftype != 15) /* If not a directory */
- - lseek(fd, BUFSIZE*nblocks, 1); /* Seek to next file */
- -
- - return;
- -
- -} /* process_file */
- -
- -
- -/*
- - * extract_file -- extract file fname from the archive fd. Fname
- - * comtains filelen bytes.
- - */
- -void extract_file(fd, fname, filelen)
- -int fd;
- -char * fname;
- -int filelen;
- -{
- - int ofd;
- - int n;
- - unsigned char buf[BUFSIZE];
- -
- - printf("x - %s\n", fname);
- - if ((ofd = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- - /* Open (PRODOS) file */
- - perror(fname);
- - exit(1);
- - }
- -
- - while (filelen > 0) {
- - if ((n = read(fd, buf, BUFSIZE)) != BUFSIZE) { /* Read 128 bytes */
- - fprintf(stderr, "%s: %s file size is broken\n", progname, blufile);
- - exit(1);
- - }
- - write(ofd, buf, (filelen >= BUFSIZE ? BUFSIZE : filelen));
- - filelen -= BUFSIZE;
- - }
- -
- - close(ofd); /* Close (PRODOS) file */
- - return;
- -
- -} /* extract_file */
- -
- -
- -
- -/*
- - * print_global_info -- print global information of the binary II file
- - */
- -void print_global_info(buf)
- -unsigned char * buf;
- -{
- - int disk_blocks;
- -
- - disk_blocks = buf[117] + (buf[118]<<8) + (buf[119]<<16) + (buf[120]<<24);
- - printf("%s, by Blu %d, ", blufile, buf[126]);
- - printf("%d files, using %d blocks\n", buf[127]+1, disk_blocks);
- - return;
- -
- -} /* print_global_info */
- -
- -
- -
- -/*
- - * want -- return 1 if name exists in array wantlist,
- - * else return 0
- - */
- -want(name, wantlist)
- -char * name;
- -char ** wantlist;
- -{
- - while (*wantlist != NULL) {
- - if (strcmp(name, *wantlist++) == NULL)
- - return(1);
- - }
- - return(0);
- -
- -} /* want */
- -
- -
- -
- -void usage()
- -{
- - fprintf(stderr, "usage: %s [-hv] <blufile> [<filetoextract> ...]\n",
- - progname);
- - return;
- -
- -} /* usage */
- -
- -
- -
- -void printhelp()
- -{
- - fprintf(stderr, "\t-h show this help.\n");
- - fprintf(stderr, "\t-v show contents of archive.\n");
- -}
- + END OF ARCHIVE
-