From e72e1c891f38fafdef339577af0f267a6d7a7a2d Mon Sep 17 00:00:00 2001 From: gdr-ftp Date: Fri, 10 Apr 1998 19:30:29 +0000 Subject: [PATCH] Initial checkin of what is believed to be tar v2.0. There was a tar v2.0.1 binary distributed on the 'net that claimed to have fixed an unspecified bug in this version, but neither the sources nor the originator of that fix are available. It may be appropriate to completely replace this implementation. --- bin/tar/Makefile | 5 + bin/tar/tar.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 bin/tar/Makefile create mode 100644 bin/tar/tar.c diff --git a/bin/tar/Makefile b/bin/tar/Makefile new file mode 100644 index 0000000..349b4d3 --- /dev/null +++ b/bin/tar/Makefile @@ -0,0 +1,5 @@ +tar.a: tar.c + compile tar.c keep=tar + +tar: tar.a + link tar keep=tar diff --git a/bin/tar/tar.c b/bin/tar/tar.c new file mode 100644 index 0000000..032d2ea --- /dev/null +++ b/bin/tar/tar.c @@ -0,0 +1,242 @@ +/* + + tar.c - a GS version of the venerable Unix tape archive + utility. + + 7/12/93 - changed to use read/write instead of fread/fwrite. + Some performance improvement. + Copyright 1991-1993 Procyon Enterprises, Inc. + This code and the executable derived from it are hereby + put in the public domain. + +*/ + +#pragma stacksize 1024 +#pragma optimize 9 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TBLOCK 512 +#define NAMSIZ 100 + +union hblock { + char dummy[TBLOCK]; + struct header { + char name[NAMSIZ]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char linkflag; + char linkname[NAMSIZ]; + FileInfoRecGS fInfo; + } dbuf; +}; + +byte buffer[1024]; +char filename[255]; +int 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; +} + +static char fixed[NAMSIZ]; +char *fixName(char *n) +{ +int i,j; + + for (i = 0, j = 0; n[i] != 0;) { + if (n[i] == '/') { + fixed[j++] = '/'; + while (n[i] == '/') i++; + } + else fixed[j++] = n[i++]; + } + fixed[j] = 0; + return fixed; +} + +int extractFile(char *name, longword blocks, longword length) +{ +word excess; +int got,get,i,e; +int output; +char *d,dirName[256]; +CreateRecGS c; +FileInfoRecGS inf; + + if (optVerbose) printf("extracting %s (%ld blocks)\n",name, blocks); + blocks = length / 1024; + excess = length % 1024; + if (excess) blocks++; + + for (i = 0; i < strlen(name); i++) + if (!( isalnum(name[i]) || (name[i] == '.') || (name[i] == '/') )) + name[i] = '.'; + + 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; + name=fixName(name); + output = open(name, O_WRONLY|O_CREAT,0666); + for (i = 0; i < blocks; i++) { + if ((i == blocks-1) && excess) get = excess; + else get = 1024; + got = read(tarfile, buffer, (size_t) get); + if (got != get) { fprintf(stderr, "read error\n"); exit(1); } + + if (write(output, buffer, (size_t) got) < get) + { fprintf(stderr, "write error\n"); exit(1); } + } + close(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; +int err; + + 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 = open(argv[2], O_RDONLY); + else { fprintf(stderr, "no SCSI tape found\n"); exit(1); } + + if (tarfile == 0) { + perror("Couldn't open archive"); + exit(1); + } + + if (!(optExtract || optTest)) usage(); + BeginSession(&SessionPB); + + do { + if (lseek(tarfile, (long) block*512, SEEK_SET) == -1) { + err = errno; + fprintf(stderr, "Seek error(%s)- aborting\n",strerror(err)); + exit(1); + } + got = read(tarfile, buffer, (size_t) 512); + 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); + close(tarfile); + EndSession(&SessionPB); + return 0; +}