home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / file / extar_1 / extar / extar.c next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  4.9 KB  |  287 lines

  1. /* vi:tabstop=4:shiftwidth=4:smartindent
  2.  *
  3.  * tar.c
  4.  *
  5.  */
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <time.h>
  10. #include "tar.h"
  11.  
  12. #define DIRSEP    '/'
  13. #define ARCSEP    '.'
  14.  
  15. /* Filenames for which the end two parts are swapped. e.g. c.fred -> fred.c
  16.  * This is overridden by the environment variable ARCSWAP
  17.  */
  18. #define ARCSWAP    "a:c:f:h:i:l:o:p:s:y:w:vim:info"
  19. char    *swap = ARCSWAP;
  20.  
  21. /* Filenames for which the last two parts make a filename.extension.
  22.  * e.g. tmp.fred.tex -> tmp/fred.tex
  23.  * This is overridden by the environment variable ARCDOT
  24.  */
  25. #define ARCDOT        "txt:tex:dvi:eps:ps:bib:sty:bst:log:blg:aux:bbl:lof:lot:toc"
  26. char    *dot = ARCDOT;
  27.  
  28. int octal(char *str, int len);
  29. char *munge(char *file);
  30.  
  31. int main(int argc, char **argv)
  32. {
  33.     FILE            *fp, *fo;
  34.     char            buf[TBLOCK], *p;
  35.     union hblock    header;
  36.     char            *filename, *linkname;
  37.     int                mode, uid, gid, size, cksum, link, nblocks, ex;
  38.     time_t            mtime;
  39.  
  40.     if ((argc != 3) || (argv[1][1] != '\0') ||
  41.         ((argv[1][0] != 't') && (argv[1][0] != 'x')))
  42.     {
  43.         fprintf(stderr, "Usage: %s [xt] tarfile\n", *argv);
  44.         exit(1);
  45.     }
  46.  
  47.     ex = (argv[1][0] == 'x');
  48.  
  49.     /* Get the environment variables
  50.      */
  51.     if ((p=getenv("ARCSWAP")) != NULL)
  52.     {
  53.         swap = p;
  54.     }
  55.  
  56.     if ((p=getenv("ARCDOT")) != NULL)
  57.     {
  58.         dot = p;
  59.     }
  60.  
  61.     fp = fopen(argv[2], "rb");
  62.     if (fp == NULL)
  63.     {
  64.         fprintf(stderr, "Can't open %s\n", argv[1]);
  65.         exit(1);
  66.     }
  67.  
  68.     while (fread(&header, 1, TBLOCK, fp) == TBLOCK)
  69.     {
  70.         int i, z;
  71.  
  72.         z=0;
  73.         for (i=0; i<TBLOCK; i++)
  74.         {
  75.             z |= header.dummy[i];
  76.         }
  77.         if (z == 0)
  78.         {
  79.             fread(&header, 1, TBLOCK, fp);
  80.             for (i=0; i<TBLOCK; i++)
  81.             {
  82.                 z |= header.dummy[i];
  83.             }
  84.             if (z == 0)
  85.             {
  86.                 break;
  87.             }
  88.         }
  89.  
  90.         filename=header.dbuf.name;
  91.  
  92.         mode = octal(header.dbuf.mode, 6);
  93.         uid  = octal(header.dbuf.uid, 6);
  94.         gid  = octal(header.dbuf.gid, 6);
  95.         size = octal(header.dbuf.size, 11);
  96.         mtime= octal(header.dbuf.mtime, 11);
  97.         cksum= octal(header.dbuf.chksum, 6);
  98.         link = octal(&header.dbuf.linkflag, 1);
  99.  
  100.         linkname=header.dbuf.linkname;
  101.  
  102.         /* Don't do anything with non-files. Directories will be
  103.          * created when needed to store things.
  104.          */
  105.         if (!link)
  106.         {
  107.             /* Doing things simply. So don't bother about the checksum,
  108.              * id, mode or time.
  109.              */
  110.             printf("%-8d %30s", size, filename);
  111.             nblocks = (size + TBLOCK - 1) / TBLOCK;
  112.  
  113.             /* Fiddle the filename into the other machine's format
  114.              */
  115.             filename = munge(filename);
  116.             
  117.             /* Make the directory in which it resides
  118.              */
  119.             if (ex)
  120.             {
  121.                 for (p=filename; *p; p++)
  122.                 {
  123.                     if (*p == DIRSEP)
  124.                     {
  125.                         *p = '\0';
  126.                         mkdir(filename);
  127.                         *p = DIRSEP;
  128.                     }
  129.                 }
  130.             }
  131.  
  132.             printf(" -> %s\n", filename);
  133.             if (nblocks != 0)
  134.             {
  135.                 if (ex)
  136.                 {
  137.                     fo = fopen(filename, "wb");
  138.                     if (fo == NULL)
  139.                     {
  140.                         printf("Can't write %s", filename);
  141.                         perror(": ");
  142.                     }
  143.                 }
  144.                 else
  145.                 {
  146.                     fo = NULL;
  147.                 }
  148.  
  149.                 for (i=0; i<nblocks; i++)
  150.                 {
  151.                     fread(buf, 1, TBLOCK, fp);
  152.                     if (fo != NULL)
  153.                     {
  154.                         fwrite(buf, 1, (size > TBLOCK) ? TBLOCK : size, fo);
  155.                     }
  156.                     size -= TBLOCK;
  157.                 }
  158.  
  159.                 if (fo != NULL)
  160.                 {
  161.                     fclose(fo);
  162.                 }
  163.             }
  164.         }
  165.     }
  166.     exit(0);
  167. }
  168.  
  169. int octal(char *str, int len)
  170. {
  171.     int i, n = 0;
  172.  
  173.     for (i=0; i<len; i++)
  174.     {
  175.         if ((str[i] >= '0') && (str[i] <= '8'))
  176.         {
  177.             n = (n << 3) | (str[i] - '0');
  178.         }
  179.     }
  180.  
  181.     return n;
  182. }
  183.  
  184. char *munge(char *file)
  185. {
  186.     static char new[1024];
  187.     char        *ld, *lld, tmp[1024], *s, *t;
  188.     int            i;
  189.  
  190.     /* Find the last dot in the name
  191.      */
  192.     ld = strrchr(file, ARCSEP);
  193.     if (ld == NULL)
  194.     {
  195.         /* No change to be made.
  196.          */
  197.         return file;
  198.     }
  199.  
  200.     /* Trailing dots get zapped.
  201.      */
  202.     if (ld[1] == '\0')
  203.     {
  204.         ld[0] = '\0';
  205.         ld = strrchr(file, ARCSEP);
  206.         if (ld == NULL)
  207.         {
  208.             return file;
  209.         }
  210.     }
  211.  
  212.     /* Find the second last dot if there is one.
  213.      */
  214.     *ld = '\0';
  215.     lld = strrchr(file, ARCSEP);
  216.     *ld = ARCSEP;
  217.  
  218.     /* For every dot in the name up to and including the second last
  219.      * we may copy the filename, changing ARCSEP to DIRSEP.
  220.      */
  221.     new[0] = 0;
  222.     if (lld)
  223.     {
  224.         for (i=0; file+i<=lld; i++)
  225.         {
  226.             new[i] = (file[i] == ARCSEP ? DIRSEP : file[i]);
  227.         }
  228.         new[i] = '\0';
  229.         file = lld+1;
  230.     }
  231.  
  232.     /* We now have file=possible leaf name to be checked and
  233.      * new containing the possible dir name
  234.      */
  235.     *ld++ = '\0';
  236.  
  237.     /* Now file=part before the dot and ld=part after it.
  238.      * Check the two parts for matches in dot and swap.
  239.      * swap takes precedence.
  240.      */
  241.     strcpy(tmp, swap);
  242.  
  243.     /* Before final conversion, replace '/' with '.'
  244.      * in both dirname and filename
  245.      */
  246.     for (s=file; *s; s++)
  247.     {
  248.         if (*s == '/')
  249.         {
  250.             *s = '.';
  251.         }
  252.     }
  253.     for (s=ld; *s; s++)
  254.     {
  255.         if (*s == '/')
  256.         {
  257.             *s = '.';
  258.         }
  259.     }
  260.  
  261.     t = tmp;
  262.     while ((s=strtok(t, ":")) != NULL)
  263.     {
  264.         t=NULL;
  265.         if (!strcmp(s, file))
  266.         {
  267.             sprintf(new+strlen(new), "%s.%s", ld, file);
  268.             return new;
  269.         }
  270.     }
  271.  
  272.     strcpy(tmp, dot);
  273.     t = tmp;
  274.     while ((s=strtok(t, ":")) != NULL)
  275.     {
  276.         t=NULL;
  277.         if (!strcmp(s, ld))
  278.         {
  279.             sprintf(new+strlen(new), "%s.%s", file, ld);
  280.             return new;
  281.         }
  282.     }
  283.  
  284.     sprintf(new+strlen(new), "%s%c%s", file, DIRSEP, ld);
  285.     return new;
  286. }
  287.