home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 341b.lha / uucp1_v1.03d / src / compress / tarsplit.c < prev    next >
C/C++ Source or Header  |  1990-01-28  |  4KB  |  216 lines

  1.  
  2. /*
  3.  * TarSplit -- split up tar files (creating directories as needed)
  4.  *
  5.  * usage: TarSplit [pathname]
  6.  *
  7.  * semantics: splits up tar file taken from stdin (or pathname, if
  8.  * specified) and creates the files therein under the working data
  9.  * directory.
  10.  *
  11.  * AmigaDOS Version - no support for stdin.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include "/version.h"
  16.  
  17. IDENT(".00");
  18.  
  19. #ifdef    AMIGA
  20. #include <stdlib.h>
  21. #include <exec/types.h>
  22. #include <proto/all.h>
  23. typedef int    bool ;
  24. bool    ChkSumOK() ;
  25. #include <libraries/dosextens.h>
  26. #else
  27. #include <modes.h>
  28. #include <bool.h>
  29. #define DIRMODE     (S_IREAD | S_IWRITE | S_IEXEC | S_IOREAD | S_IOEXEC)
  30. #endif
  31. #define TBLOCK    512
  32. #define NAMSIZ    100
  33.  
  34. union hblock {
  35.     char dummy[TBLOCK];
  36.     struct header {
  37.         char name[NAMSIZ];
  38.         char mode[8];
  39.         char uid[8];
  40.         char gid[8];
  41.         char size[12];
  42.         char mtime[12];
  43.         char chksum[8];
  44.         char linkflag;
  45.         char linkname[NAMSIZ];
  46.     } dbuf;
  47. };
  48.  
  49. #define BLKSIZE     (sizeof (union hblock))
  50. #define HARDLINK    '1'
  51. #define SYMBLINK    '2'
  52. #define NORMAL        '\0'
  53.  
  54. void DoFile();
  55.  
  56. main(argc, argv)
  57. int    argc;
  58. char    *argv[];
  59. {
  60.     FILE        *TarFP;
  61.     union hblock    TarBlock;
  62.  
  63. #ifndef AMIGA
  64.     /* make the compiler happy about formatted I/O for longs... */
  65.     pflinit();
  66. #endif
  67.  
  68.     switch(argc) {
  69. #ifndef AMIGA
  70.     case 1:
  71.         TarFP = stdin;
  72.         break;
  73. #endif
  74.     case 2:
  75.         if ((TarFP = fopen(argv[1], "r")) == NULL) {
  76.             fprintf(stderr, "TarSplit: can't open %s\n", argv[1]);
  77.             exit(1);
  78.         }
  79.         break;
  80.     default:
  81.         fprintf(stderr, "usage: TarSplit [pathname]\n");
  82.         exit(1);
  83.     }
  84.  
  85.     for (;;) {
  86.         if (fread((char *)&TarBlock, BLKSIZE, 1, TarFP) == NULL) {
  87.             fprintf(stderr, "TarSplit: premature EOF\n");
  88.             exit(1);
  89.         } else if (IsZero(&TarBlock)) {
  90.             while (fread((char *)&TarBlock, BLKSIZE, 1, TarFP) != NULL)
  91.                 ;
  92.             break;
  93.         } else
  94.             DoFile(&TarBlock, TarFP);
  95.     }
  96.  
  97. }
  98.  
  99. bool
  100. IsZero(block)
  101. union hblock    *block;
  102. {
  103.     int    i;
  104.     char    *cblock;
  105.  
  106.     cblock = block->dummy;
  107.     for (i = 0; i < TBLOCK; i++)
  108.         if (*cblock++ != '\0')
  109.             return(FALSE);
  110.  
  111.     return (TRUE);
  112.  
  113. }
  114.  
  115. void
  116. DoFile(block, TarFP)
  117. union hblock    *block;
  118. FILE        *TarFP;
  119. {
  120.     long    FSize;
  121.     char    FName[NAMSIZ], *RefName;
  122.     int    i;
  123.     bool    IsDir, OpenOK;
  124.     FILE    *NewFP;
  125.  
  126.     if (!ChkSumOK(block)) {
  127.         fprintf(stderr, "TarSplit: bad checksum, name %s?\n",
  128.             block->dbuf.name);
  129.         exit(1);
  130.     }
  131.  
  132.     switch(block->dbuf.linkflag) {
  133.     case HARDLINK:
  134.     case SYMBLINK:
  135.         fprintf(stderr, "TarSplit: can't handle links\n");
  136.         exit(1);
  137.     case NORMAL:
  138.         break;
  139.     default:
  140.         fprintf(stderr, "TarSplit: unknown linkflag\n");
  141.         exit(1);
  142.     }
  143.  
  144. #ifdef    AMIGA
  145.     if (sscanf(block->dbuf.size, "%12lo", &FSize) != 1) {
  146. #else
  147.     if (sscanf(block->dbuf.size, "%12O", &FSize) != 1) {
  148. #endif
  149.         fprintf(stderr, "TarSplit: bad size\n");
  150.         exit(1);
  151.     }
  152.  
  153.     for (i = 0, RefName = block->dbuf.name; *RefName; i++, RefName++)
  154.         FName[i] = *RefName;
  155.  
  156.     if (IsDir = (*(RefName - 1) == '/')) {
  157.         FName[i - 1] = '\0';
  158.         if (strcmp(FName, ".") == 0)
  159.             OpenOK = TRUE;
  160.         else
  161. #ifdef    AMIGA
  162.             {
  163.                 BPTR Lock;
  164.                 OpenOK = (Lock = CreateDir(FName)) != 0;
  165.                 UnLock(Lock) ;
  166.             }
  167. #else
  168.             OpenOK = mknod(FName, DIRMODE) == 0;
  169. #endif
  170.     } else {
  171.         FName[i] = '\0';
  172.         OpenOK = (NewFP = fopen(FName, "w")) != NULL;
  173.     }
  174.  
  175.     if (!OpenOK) {
  176.         fprintf(stderr, "TarSplit: can't create %s\n", FName);
  177.         exit(1);
  178.     }
  179.  
  180.     for (; FSize > 0; FSize -= TBLOCK) {
  181.         if (fread((char *)block, BLKSIZE, 1, TarFP) == NULL) {
  182.             fprintf(stderr, "TarSplit: premature EOF\n");
  183.             exit(1);
  184.         }
  185.         if (!IsDir)
  186.             fwrite(block->dummy, 1,
  187.                 (FSize > TBLOCK ? TBLOCK : (int) FSize), NewFP);
  188.     }
  189.  
  190.     if (!IsDir)
  191.         fclose(NewFP);
  192. }
  193.  
  194. bool
  195. ChkSumOK(block)
  196. union hblock    *block;
  197. {
  198.     long    Accum, ChkSumVal;
  199.     int    i;
  200.  
  201. #ifdef    AMIGA
  202.     sscanf(block->dbuf.chksum, "%8lo", &ChkSumVal);
  203. #else
  204.     sscanf(block->dbuf.chksum, "%8O", &ChkSumVal);
  205. #endif
  206.     for (i = 0; i < 8; i++)
  207.         block->dbuf.chksum[i] = ' ';
  208.  
  209.     Accum = 0;
  210.     for (i = 0; i < TBLOCK; i++)
  211.         Accum += 0xff & block->dummy[i];
  212.  
  213.     return(Accum == ChkSumVal);
  214.  
  215. }
  216.