home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / unix / tarsplit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-24  |  5.6 KB  |  286 lines

  1. /*
  2. **  TARSPLIT.C
  3. **
  4. ** TarSplit -- split up tar files (creating directories as needed)
  5. **
  6. ** usage: TarSplit [pathname]
  7. **
  8. ** semantics: splits up tar file taken from stdin (or pathname, if
  9. ** specified) and creates the files therein under the working data
  10. ** directory.
  11. **
  12. ** AmigaDOS Version - no support for stdin.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include "version.h"
  18. #include "config.h"
  19.  
  20. IDENT (".02");
  21.  
  22. #if defined (__AMIGA) && !defined (AMIGA)
  23. /* make GCC with -ansi happy */
  24. #define AMIGA
  25. #endif
  26.  
  27. #if defined (_AMIGA) && !defined (AMIGA)
  28. #define AMIGA
  29. #endif
  30.  
  31. #if defined (AMIGA)
  32. #include <stdlib.h>
  33. #include "protos.h"
  34. typedef int    bool ;
  35. #else
  36. #include <modes.h>
  37. #include <bool.h>
  38. #define DIRMODE     (S_IREAD | S_IWRITE | S_IEXEC | S_IOREAD | S_IOEXEC)
  39. #endif
  40.  
  41. #define TBLOCK    512
  42. #define NAMSIZ    100
  43.  
  44. union hblock {
  45.     char dummy[TBLOCK];
  46.     struct header {
  47.         char name[NAMSIZ];
  48.         char mode[8];
  49.         char uid[8];
  50.         char gid[8];
  51.         char size[12];
  52.         char mtime[12];
  53.         char chksum[8];
  54.         char linkflag;
  55.         char linkname[NAMSIZ];
  56.     } dbuf;
  57. };
  58.  
  59. #define BLKSIZE     (sizeof (union hblock))
  60. #define HARDLINK    '1'
  61. #define SYMBLINK    '2'
  62. #define NORMAL        '\0'
  63.  
  64. bool IsZero (union hblock *block);
  65. void DoFile (union hblock *block, FILE *TarFP);
  66. bool ChkSumOK (union hblock *block);
  67. #if defined (AMIGA)
  68. int CreateAmigaDir (char *fileName);
  69. #endif
  70.  
  71. int
  72. main (int argc, char **argv)
  73. {
  74.     FILE        *TarFP;
  75.     union hblock    TarBlock;
  76.  
  77. #if !defined (AMIGA)
  78.     /* make the compiler happy about formatted I/O for longs... */
  79.     pflinit();
  80. #endif
  81.  
  82.     switch(argc) {
  83. #if !defined (AMIGA)
  84.     case 1:
  85.         TarFP = stdin;
  86.         break;
  87. #endif
  88.     case 2:
  89.         if ((TarFP = fopen(argv[1], "r")) == NULL) {
  90.             fprintf(stderr, "TarSplit: can't open %s\n", argv[1]);
  91.             exit(1);
  92.         }
  93.         break;
  94.     default:
  95.         fprintf(stderr, "usage: TarSplit [pathname]\n");
  96.         exit(1);
  97.     }
  98.  
  99.     for (;;) {
  100.         if (!fread ((char *) &TarBlock, BLKSIZE, 1, TarFP)) {
  101.             fprintf(stderr, "TarSplit: premature EOF\n");
  102.             exit(1);
  103.         } else if (IsZero(&TarBlock)) {
  104.             while (fread ((char *) &TarBlock, BLKSIZE, 1, TarFP))
  105.                 ;
  106.             break;
  107.         } else
  108.             DoFile(&TarBlock, TarFP);
  109.     }
  110.  
  111. }
  112.  
  113. bool
  114. IsZero (union hblock *block)
  115. {
  116.     int    i;
  117.     char    *cblock;
  118.  
  119.     cblock = block->dummy;
  120.     for (i = 0; i < TBLOCK; i++)
  121.         if (*cblock++ != '\0')
  122.             return(FALSE);
  123.  
  124.     return (TRUE);
  125.  
  126. }
  127.  
  128. void
  129. DoFile (union hblock *block, FILE *TarFP)
  130. {
  131.     long    FSize;
  132.     char    FName[NAMSIZ], *RefName;
  133.     int    i;
  134.     bool    nodeIsDir, OpenOK;
  135.     FILE    *NewFP;
  136.  
  137.     if (!ChkSumOK(block)) {
  138.         fprintf(stderr, "TarSplit: bad checksum, name %s?\n",
  139.             block->dbuf.name);
  140.         exit(1);
  141.     }
  142.  
  143.     switch(block->dbuf.linkflag) {
  144.     case HARDLINK:
  145.     case SYMBLINK:
  146.         fprintf(stderr, "TarSplit: can't handle link for '%s'\n",
  147.         block->dbuf.name);
  148.         return;
  149.     case NORMAL:
  150.         break;
  151.     default:
  152.         fprintf(stderr, "TarSplit: unknown linkflag\n");
  153.         exit(1);
  154.     }
  155.  
  156. #if defined (AMIGA)
  157.     if (sscanf(block->dbuf.size, "%12lo", &FSize) != 1) {
  158. #else
  159.     if (sscanf(block->dbuf.size, "%12O", &FSize) != 1) {
  160. #endif
  161.         fprintf(stderr, "TarSplit: bad size\n");
  162.         exit(1);
  163.     }
  164.  
  165.     for (i = 0, RefName = block->dbuf.name; *RefName; i++, RefName++)
  166.         FName[i] = *RefName;
  167.  
  168.     if (nodeIsDir = (*(RefName - 1) == '/')) {
  169.         FName[i - 1] = '\0';
  170.         if (strcmp(FName, ".") == 0)
  171.             OpenOK = TRUE;
  172.         else
  173. #if defined (AMIGA)
  174.             {
  175.                 BPTR Lock;
  176.                 OpenOK = (Lock = CreateDir ((UBYTE *) FName)) != 0;
  177.                 if (! OpenOK) {
  178.                 /* We may be splitting into an existing hierarchy.
  179.                  * Don't punish us for that! This event is not
  180.                  * currently reported to the user, though it might
  181.                  * be a good idea.
  182.                  */
  183.                 if (IoErr() == ERROR_OBJECT_EXISTS && IsDir(FName))
  184.                     OpenOK = TRUE;
  185.                 }
  186.                 if (Lock) UnLock(Lock);
  187.             }
  188. #else
  189.             OpenOK = mknod(FName, DIRMODE) == 0;
  190. #endif
  191.     } else {
  192.         FName[i] = '\0';
  193.         OpenOK = (NewFP = fopen(FName, "w")) != NULL;
  194. #if defined (AMIGA)
  195.     /* 05-06-91, MRR:
  196.      * Some tar programs (e.g. Interactive) don't write the directory
  197.      * nodes to the archive. If we get a 205 error (OBJECT_NOT_FOUND)
  198.      * when creating a file, it's a pretty safe bet that the failure
  199.      * was caused by a missing directory node. Try to create the
  200.      * directory and see if it helps.
  201.      */
  202.     if (! OpenOK) {
  203.         if (! CreateAmigaDir(FName)) {
  204.         OpenOK = (NewFP = fopen(FName, "w")) != NULL;
  205.         }
  206.     }
  207. #endif
  208.     }
  209.  
  210.     if (!OpenOK) {
  211.         fprintf(stderr, "TarSplit: can't create %s\n", FName);
  212.         exit(1);
  213.     }
  214.  
  215.     for (; FSize > 0; FSize -= TBLOCK) {
  216.         if (!fread ((char *) block, BLKSIZE, 1, TarFP)) {
  217.             fprintf(stderr, "TarSplit: premature EOF\n");
  218.             exit(1);
  219.         }
  220.         if (!nodeIsDir)
  221.             fwrite(block->dummy, 1,
  222.                 (FSize > TBLOCK ? TBLOCK : (int) FSize), NewFP);
  223.     }
  224.  
  225.     if (!nodeIsDir)
  226.         fclose(NewFP);
  227. }
  228.  
  229. bool
  230. ChkSumOK (union hblock *block)
  231. {
  232.     long    Accum, ChkSumVal;
  233.     int    i;
  234.  
  235. #if defined  (AMIGA)
  236.     sscanf(block->dbuf.chksum, "%8lo", &ChkSumVal);
  237. #else
  238.     sscanf(block->dbuf.chksum, "%8O", &ChkSumVal);
  239. #endif
  240.     for (i = 0; i < 8; i++)
  241.         block->dbuf.chksum[i] = ' ';
  242.  
  243.     Accum = 0;
  244.     for (i = 0; i < TBLOCK; i++)
  245.         Accum += 0xff & block->dummy[i];
  246.  
  247.     return(Accum == ChkSumVal);
  248.  
  249. }
  250.  
  251. #if defined (AMIGA)
  252. int
  253. CreateAmigaDir (char *fileName)
  254. {
  255.     static char     dirName[256];
  256.     static char     partial[256];
  257.     BPTR    lock;
  258.     char    *p;
  259.     int     result = 0;
  260.  
  261.     strcpy(dirName, fileName);
  262.     p = strrchr(dirName, '/');
  263.     if (p) {
  264.     *p = '\0';           /* Drop leaf node. */
  265.     *partial = '\0';
  266.     for (p = strtok(dirName, "/"); p; p = strtok(NULL, "/")) {
  267.         if (*p == '.') continue;
  268.         if (*partial) strcat(partial,"/");
  269.         strcat(partial, p);
  270.         if (lock = Lock ((UBYTE *) partial,SHARED_LOCK)) {
  271.         UnLock(lock);
  272.         continue;
  273.         }
  274.         lock = CreateDir ((UBYTE *) partial);
  275.         if (! lock) {
  276.         result = IoErr();
  277.         break;
  278.         }
  279.         else
  280.         UnLock(lock);
  281.     }
  282.     }
  283.     return result;
  284. }
  285. #endif
  286.