Submitted-by: Jawaid Bazyar (bazyar@cs.uiuc.edu) Posting-number: Volume 1, Source:44 Archive-name: util/gs/shell/orca/tar Architecture: ONLY_2gs Version-number: 1.2 This package will unpack tar archives. Requires Orca shell. Enjoy. ################################### =tar.doc -=========== - TAR -=========== -version 1.2 - -tar -options [archive]\n" - -options: t - list files in archive (test) - x - extract files from archive - f - use file [archive] instead of tape - v - verbose mode - - tar is the standard Unix Tape ARchive utility. This GS version only -supports reading file-based tar files. As soon as I get my hands on -a SCSI tape drive, I'll include support for those. - - Also in the works is support for creating archives. - ------ - -Jawaid Bazyar -Derek Taubert - -Copyright 1990 by Procyon Software -Freeware - distribute but don't sell! - -This utility is FreeWare. Distribute them as much as you like, just -don't sell them or distribute modified versions. Send me your comments - -I'm eager to hear from you for suggestions and improvements. - -Also, if you make any modifications to the code please do not redistribute -them. Instead, send me the changed source along with an explanation and -I will consider including your change in the next version. - - Jawaid Bazyar - 1120 Maple Street - Mt. Vernon, IL 62864 - - Internet/ARPAnet bazyar@cs.uiuc.edu - GEnie J.BAZYAR - =tar.c - -/* - - tar.c - a GS version of the venerable Unix tape archive - utility. - - Copyright 1991, Procyon Software - This code and the executable derived from it are hereby - put in the public domain. - Distribution/modification is free, pursuant to the rules - outlined in the SHELLSTUFF.DOC file. - -*/ - -#include -#include -#include -#include -#include -#include - -byte buffer[1024]; -char filename[255]; -FILE *tarfile; - -int optVerbose, optFile, optExtract, - optTest; - -/* pull a file out of the archive one block at a time */ - -GSString255Ptr MakeGSString1(char *s) -{ -GSString255Ptr n; - n = malloc(sizeof(GSString255)); - strcpy((char *) n->text,s); - n->length = strlen(s); - return n; -} - -int extractFile(char *name, longword blocks, longword length) -{ -word excess; -int got,get,i,e; -FILE *output; -char *d,dirName[256]; -CreateRecGS c; -FileInfoRecGS inf; - - if (optVerbose) printf("extracting %s (%d blocks)\n",name, blocks); - blocks = length / 1024; - excess = length % 1024; - if (excess) blocks++; - - if (name[0] == '/') { - fprintf(stderr, "Can't extract to a volume name!\n"); - exit(1); - } - d = name; - while ((d = strchr(d, '/')) != NULL) { - - strncpy(dirName, name, d-name); - dirName[(int) (d-name)] = '\0'; - - inf.pCount = 3; - inf.pathname = MakeGSString1(dirName); - GetFileInfoGS(&inf); - if (e = toolerror()) { - switch (e) { - case 0x46: - case 0x44: break; - default: fprintf(stderr, "error statting file %s (%x)\n", - dirName,e); - exit(1); break; - } - } - else if (inf.fileType != 0x0F) { - fprintf(stderr, "can't overwrite file %s\n", dirName); - exit(1); - } - - if (e) { - c.pCount = 3; - c.pathname = inf.pathname; - c.access = 0xC3; - c.fileType = 0x0F; - CreateGS(&c); - if (e = toolerror()) { - fprintf(stderr, "fatal GS/OS error %x\n",e); - exit(1); - } - } - free(inf.pathname); - while (*d == '/') d++; - } - - if (!blocks) return 0; - output = fopen(name, "wb"); - for (i = 0; i < blocks; i++) { - if ((i == blocks-1) && excess) get = excess; - else get = 1024; - got = fread(buffer, sizeof(byte), (size_t) get, tarfile); - if (got != get) { fprintf(stderr, "read error\n"); exit(1); } - - if (fwrite(buffer, sizeof(byte), (size_t) got, output) < get) - { fprintf(stderr, "write error\n"); exit(1); } - } - fclose(output); -} - -int testFile(char *name, longword blocks, longword length) -{ - printf("%s (%ld blocks)\n",name, blocks); -} - -void usage(void) -{ - fprintf(stderr,"Usage: tar -options [archive]\n" - " options: t - list files in archive (test)\n" - " x - extract files from archive\n" - " f - use file [archive] instead of tape\n" - " v - verbose mode\n"); - exit(1); -} - -void parseOpts(char *opts) -{ -char *i = opts; - - while (*i != '\0') { - switch (*i) { - case 'x': if (optTest) usage(); - optExtract = 1; break; - case 't': if (optExtract) usage(); - optTest = 1; break; - case 'f': optFile = 1; break; - case 'v': optVerbose = 1; break; - default: usage(); - } - i++; - } -} - -int main(int argc, char *argv[]) -{ -longword block; -longword size; -longword fileBlocks; -word got; -int SessionPB = 0; - - block = 0; - optVerbose = optFile = optExtract = optTest = 0; - - if (argc == 1) usage(); - if (argv[1][0] == '-') parseOpts(&argv[1][1]); - else parseOpts(argv[1]); - - if (optFile) tarfile = fopen(argv[2], "rb"); - else { fprintf(stderr, "no SCSI tape found\n"); exit(1); } - - if (!(optExtract || optTest)) usage(); - BeginSession(&SessionPB); - - do { - if (fseek(tarfile, (long) block*512, SEEK_SET)) { - fprintf(stderr, "Seek error- aborting\n"); exit(1); - } - got = fread(buffer, sizeof(byte), (size_t) 512, tarfile); - if (!buffer[0]) break; - if (got == 0) { fprintf(stderr, "Read error- aborting\n"); exit(1); } - if (got == 512) { - sscanf(buffer+0174, "%lo", &size); - - fileBlocks = (size / 512); - if (size % 512) fileBlocks++; - - block += fileBlocks + 1; - strcpy(filename, (char *) buffer); /* copy the filename for future - reeference */ - if (optExtract) extractFile(filename, fileBlocks, size); - else if (optTest) testFile(filename, fileBlocks, size); - - buffer[0] = 0; - } - } while (got == 512); - fclose(tarfile); - EndSession(&SessionPB); - return 0; -} - + END OF ARCHIVE