home *** CD-ROM | disk | FTP | other *** search
- /*
- ** TARSPLIT.C
- **
- ** TarSplit -- split up tar files (creating directories as needed)
- **
- ** usage: TarSplit [pathname]
- **
- ** semantics: splits up tar file taken from stdin (or pathname, if
- ** specified) and creates the files therein under the working data
- ** directory.
- **
- ** AmigaDOS Version - no support for stdin.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include "version.h"
- #include "config.h"
-
- IDENT (".02");
-
- #if defined (__AMIGA) && !defined (AMIGA)
- /* make GCC with -ansi happy */
- #define AMIGA
- #endif
-
- #if defined (_AMIGA) && !defined (AMIGA)
- #define AMIGA
- #endif
-
- #if defined (AMIGA)
- #include <stdlib.h>
- #include "protos.h"
- typedef int bool ;
- #else
- #include <modes.h>
- #include <bool.h>
- #define DIRMODE (S_IREAD | S_IWRITE | S_IEXEC | S_IOREAD | S_IOEXEC)
- #endif
-
- #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];
- } dbuf;
- };
-
- #define BLKSIZE (sizeof (union hblock))
- #define HARDLINK '1'
- #define SYMBLINK '2'
- #define NORMAL '\0'
-
- bool IsZero (union hblock *block);
- void DoFile (union hblock *block, FILE *TarFP);
- bool ChkSumOK (union hblock *block);
- #if defined (AMIGA)
- int CreateAmigaDir (char *fileName);
- #endif
-
- int
- main (int argc, char **argv)
- {
- FILE *TarFP;
- union hblock TarBlock;
-
- #if !defined (AMIGA)
- /* make the compiler happy about formatted I/O for longs... */
- pflinit();
- #endif
-
- switch(argc) {
- #if !defined (AMIGA)
- case 1:
- TarFP = stdin;
- break;
- #endif
- case 2:
- if ((TarFP = fopen(argv[1], "r")) == NULL) {
- fprintf(stderr, "TarSplit: can't open %s\n", argv[1]);
- exit(1);
- }
- break;
- default:
- fprintf(stderr, "usage: TarSplit [pathname]\n");
- exit(1);
- }
-
- for (;;) {
- if (!fread ((char *) &TarBlock, BLKSIZE, 1, TarFP)) {
- fprintf(stderr, "TarSplit: premature EOF\n");
- exit(1);
- } else if (IsZero(&TarBlock)) {
- while (fread ((char *) &TarBlock, BLKSIZE, 1, TarFP))
- ;
- break;
- } else
- DoFile(&TarBlock, TarFP);
- }
-
- }
-
- bool
- IsZero (union hblock *block)
- {
- int i;
- char *cblock;
-
- cblock = block->dummy;
- for (i = 0; i < TBLOCK; i++)
- if (*cblock++ != '\0')
- return(FALSE);
-
- return (TRUE);
-
- }
-
- void
- DoFile (union hblock *block, FILE *TarFP)
- {
- long FSize;
- char FName[NAMSIZ], *RefName;
- int i;
- bool nodeIsDir, OpenOK;
- FILE *NewFP;
-
- if (!ChkSumOK(block)) {
- fprintf(stderr, "TarSplit: bad checksum, name %s?\n",
- block->dbuf.name);
- exit(1);
- }
-
- switch(block->dbuf.linkflag) {
- case HARDLINK:
- case SYMBLINK:
- fprintf(stderr, "TarSplit: can't handle link for '%s'\n",
- block->dbuf.name);
- return;
- case NORMAL:
- break;
- default:
- fprintf(stderr, "TarSplit: unknown linkflag\n");
- exit(1);
- }
-
- #if defined (AMIGA)
- if (sscanf(block->dbuf.size, "%12lo", &FSize) != 1) {
- #else
- if (sscanf(block->dbuf.size, "%12O", &FSize) != 1) {
- #endif
- fprintf(stderr, "TarSplit: bad size\n");
- exit(1);
- }
-
- for (i = 0, RefName = block->dbuf.name; *RefName; i++, RefName++)
- FName[i] = *RefName;
-
- if (nodeIsDir = (*(RefName - 1) == '/')) {
- FName[i - 1] = '\0';
- if (strcmp(FName, ".") == 0)
- OpenOK = TRUE;
- else
- #if defined (AMIGA)
- {
- BPTR Lock;
- OpenOK = (Lock = CreateDir ((UBYTE *) FName)) != 0;
- if (! OpenOK) {
- /* We may be splitting into an existing hierarchy.
- * Don't punish us for that! This event is not
- * currently reported to the user, though it might
- * be a good idea.
- */
- if (IoErr() == ERROR_OBJECT_EXISTS && IsDir(FName))
- OpenOK = TRUE;
- }
- if (Lock) UnLock(Lock);
- }
- #else
- OpenOK = mknod(FName, DIRMODE) == 0;
- #endif
- } else {
- FName[i] = '\0';
- OpenOK = (NewFP = fopen(FName, "w")) != NULL;
- #if defined (AMIGA)
- /* 05-06-91, MRR:
- * Some tar programs (e.g. Interactive) don't write the directory
- * nodes to the archive. If we get a 205 error (OBJECT_NOT_FOUND)
- * when creating a file, it's a pretty safe bet that the failure
- * was caused by a missing directory node. Try to create the
- * directory and see if it helps.
- */
- if (! OpenOK) {
- if (! CreateAmigaDir(FName)) {
- OpenOK = (NewFP = fopen(FName, "w")) != NULL;
- }
- }
- #endif
- }
-
- if (!OpenOK) {
- fprintf(stderr, "TarSplit: can't create %s\n", FName);
- exit(1);
- }
-
- for (; FSize > 0; FSize -= TBLOCK) {
- if (!fread ((char *) block, BLKSIZE, 1, TarFP)) {
- fprintf(stderr, "TarSplit: premature EOF\n");
- exit(1);
- }
- if (!nodeIsDir)
- fwrite(block->dummy, 1,
- (FSize > TBLOCK ? TBLOCK : (int) FSize), NewFP);
- }
-
- if (!nodeIsDir)
- fclose(NewFP);
- }
-
- bool
- ChkSumOK (union hblock *block)
- {
- long Accum, ChkSumVal;
- int i;
-
- #if defined (AMIGA)
- sscanf(block->dbuf.chksum, "%8lo", &ChkSumVal);
- #else
- sscanf(block->dbuf.chksum, "%8O", &ChkSumVal);
- #endif
- for (i = 0; i < 8; i++)
- block->dbuf.chksum[i] = ' ';
-
- Accum = 0;
- for (i = 0; i < TBLOCK; i++)
- Accum += 0xff & block->dummy[i];
-
- return(Accum == ChkSumVal);
-
- }
-
- #if defined (AMIGA)
- int
- CreateAmigaDir (char *fileName)
- {
- static char dirName[256];
- static char partial[256];
- BPTR lock;
- char *p;
- int result = 0;
-
- strcpy(dirName, fileName);
- p = strrchr(dirName, '/');
- if (p) {
- *p = '\0'; /* Drop leaf node. */
- *partial = '\0';
- for (p = strtok(dirName, "/"); p; p = strtok(NULL, "/")) {
- if (*p == '.') continue;
- if (*partial) strcat(partial,"/");
- strcat(partial, p);
- if (lock = Lock ((UBYTE *) partial,SHARED_LOCK)) {
- UnLock(lock);
- continue;
- }
- lock = CreateDir ((UBYTE *) partial);
- if (! lock) {
- result = IoErr();
- break;
- }
- else
- UnLock(lock);
- }
- }
- return result;
- }
- #endif
-