home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / std_unix / pax / 4 / extract.c next >
C/C++ Source or Header  |  1989-01-07  |  14KB  |  594 lines

  1. /* $Source: /u/mark/src/pax/RCS/extract.c,v $
  2.  *
  3.  * $Revision: 1.1 $
  4.  *
  5.  * extract.c - Extract files from a tar archive. 
  6.  *
  7.  * DESCRIPTION
  8.  *
  9.  * AUTHOR
  10.  *
  11.  *    Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  12.  *
  13.  * Sponsored by The USENIX Association for public distribution. 
  14.  *
  15.  * Copyright (c) 1989 Mark H. Colburn.
  16.  * All rights reserved.
  17.  *
  18.  * Redistribution and use in source and binary forms are permitted
  19.  * provided that the above copyright notice is duplicated in all such 
  20.  * forms and that any documentation, advertising materials, and other 
  21.  * materials related to such distribution and use acknowledge that the 
  22.  * software was developed * by Mark H. Colburn and sponsored by The 
  23.  * USENIX Association. 
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  26.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  27.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  28.  *
  29.  * $Log:    extract.c,v $
  30.  * Revision 1.1  88/12/23  18:02:07  mark
  31.  * Initial revision
  32.  * 
  33.  */
  34.  
  35. #ifndef lint
  36. static char *ident = "$Id: extract.c,v 1.1 88/12/23 18:02:07 mark Rel $";
  37. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  38. #endif /* ! lint */
  39.  
  40.  
  41. /* Headers */
  42.  
  43. #include "pax.h"
  44.  
  45.  
  46. /* Defines */
  47.  
  48. /*
  49.  * Swap bytes. 
  50.  */
  51. #define    SWAB(n)    ((((ushort)(n) >> 8) & 0xff) | (((ushort)(n) << 8) & 0xff00))
  52.  
  53.  
  54. /* Function Prototypes */
  55.  
  56. #ifdef __STDC__
  57.  
  58. static int inbinary(char *, char *, Stat *);
  59. static int inascii(char *, char *, Stat *);
  60. static int inswab(char *, char *, Stat *);
  61. static int readtar(char *, Stat *);
  62. static int readcpio(char *, Stat *);
  63.  
  64. #else /* !__STDC__ */
  65.  
  66. static int inbinary();
  67. static int inascii();
  68. static int inswab();
  69. static int readtar();
  70. static int readcpio();
  71.  
  72. #endif /* __STDC__ */
  73.  
  74.  
  75. /* read_archive - read in an archive
  76.  *
  77.  * DESCRIPTION
  78.  *
  79.  *    Read_archive is the central entry point for reading archives.
  80.  *    Read_archive determines the proper archive functions to call
  81.  *    based upon the archive type being processed.
  82.  *
  83.  * RETURNS
  84.  *
  85.  */
  86.  
  87. #ifdef __STDC__
  88.  
  89. int read_archive(void)
  90.  
  91. #else
  92.     
  93. int read_archive()
  94.  
  95. #endif
  96. {
  97.     Stat            sb;
  98.     char            name[PATH_MAX + 1];
  99.     int             match;
  100.     int            pad;
  101.  
  102.     name_gather();        /* get names from command line */
  103.     name[0] = '\0';
  104.     while (get_header(name, &sb) == 0) {
  105.     match = name_match(name) ^ f_reverse_match;
  106.     if (f_list) {        /* only wanted a table of contents */
  107.         if (match) {
  108.         print_entry(name, &sb);
  109.         }
  110.         if (((ar_format == TAR) 
  111.         ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  112.         : buf_skip((OFFSET) sb.sb_size)) < 0) {
  113.         warn(name, "File data is corrupt");
  114.         }
  115.     } else if (match) {
  116.         if (rplhead != NULL) {
  117.         rpl_name(name);
  118.         if (strlen(name) == 0) {
  119.             continue;
  120.         }
  121.         }
  122.         if (get_disposition("extract", name) || 
  123.                 get_newname(name, sizeof(name))) {
  124.         /* skip file... */
  125.         if (((ar_format == TAR) 
  126.             ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  127.             : buf_skip((OFFSET) sb.sb_size)) < 0) {
  128.             warn(name, "File data is corrupt");
  129.         }
  130.         continue;
  131.         } 
  132.         if (inentry(name, &sb) < 0) {
  133.         warn(name, "File data is corrupt");
  134.         }
  135.         if (f_verbose) {
  136.         print_entry(name, &sb);
  137.         }
  138.         if (ar_format == TAR && sb.sb_nlink > 1) {
  139.         /*
  140.          * This kludge makes sure that the link table is cleared
  141.          * before attempting to process any other links.
  142.          */
  143.         if (sb.sb_nlink > 1) {
  144.             linkfrom(name, &sb);
  145.         }
  146.         }
  147.         if (ar_format == TAR && (pad = sb.sb_size % BLOCKSIZE) != 0) {
  148.         pad = BLOCKSIZE - pad;
  149.         buf_skip((OFFSET) pad);
  150.         }
  151.     } else {
  152.         if (((ar_format == TAR) 
  153.         ? buf_skip(ROUNDUP((OFFSET) sb.sb_size, BLOCKSIZE)) 
  154.         : buf_skip((OFFSET) sb.sb_size)) < 0) {
  155.         warn(name, "File data is corrupt");
  156.         }
  157.     }
  158.     }
  159.  
  160.     close_archive();
  161. }
  162.  
  163.  
  164.  
  165. /* get_header - figures which type of header needs to be read.
  166.  *
  167.  * DESCRIPTION
  168.  *
  169.  *    This is merely a single entry point for the two types of archive
  170.  *    headers which are supported.  The correct header is selected
  171.  *    depending on the archive type.
  172.  *
  173.  * PARAMETERS
  174.  *
  175.  *    char    *name    - name of the file (passed to header routine)
  176.  *    Stat    *asb    - Stat block for the file (passed to header routine)
  177.  *
  178.  * RETURNS
  179.  *
  180.  *    Returns the value which was returned by the proper header
  181.  *    function.
  182.  */
  183.  
  184. #ifdef __STDC__
  185.  
  186. int get_header(char *name, Stat *asb)
  187.  
  188. #else
  189.     
  190. int get_header(name, asb)
  191. char *name;
  192. Stat *asb;
  193.  
  194. #endif
  195. {
  196.     if (ar_format == TAR) {
  197.     return(readtar(name, asb));
  198.     } else {
  199.     return(readcpio(name, asb));
  200.     }
  201. }
  202.  
  203.  
  204. /* readtar - read a tar header
  205.  *
  206.  * DESCRIPTION
  207.  *
  208.  *    Tar_head read a tar format header from the archive.  The name
  209.  *    and asb parameters are modified as appropriate for the file listed
  210.  *    in the header.   Name is assumed to be a pointer to an array of
  211.  *    at least PATH_MAX bytes.
  212.  *
  213.  * PARAMETERS
  214.  *
  215.  *    char    *name     - name of the file for which the header is
  216.  *              for.  This is modified and passed back to
  217.  *              the caller.
  218.  *    Stat    *asb    - Stat block for the file for which the header
  219.  *              is for.  The fields of the stat structure are
  220.  *              extracted from the archive header.  This is
  221.  *              also passed back to the caller.
  222.  *
  223.  * RETURNS
  224.  *
  225.  *    Returns 0 if a valid header was found, or -1 if EOF is
  226.  *    encountered.
  227.  */
  228.  
  229. #ifdef __STDC__
  230.  
  231. static int readtar(char *name, Stat *asb)
  232.  
  233. #else
  234.     
  235. static int readtar(name, asb)
  236. char    *name;
  237. Stat    *asb;
  238.  
  239. #endif
  240. {
  241.     int             status = 3;    /* Initial status at start of archive */
  242.     static int      prev_status;
  243.  
  244.     for (;;) {
  245.     prev_status = status;
  246.     status = read_header(name, asb);
  247.     switch (status) {
  248.     case 1:        /* Valid header */
  249.         return(0);
  250.     case 0:        /* Invalid header */
  251.         switch (prev_status) {
  252.         case 3:        /* Error on first record */
  253.         warn(ar_file, "This doesn't look like a tar archive");
  254.         /* FALLTHRU */
  255.         case 2:        /* Error after record of zeroes */
  256.         case 1:        /* Error after header rec */
  257.         warn(ar_file, "Skipping to next file...");
  258.         /* FALLTHRU */
  259.         default:
  260.         case 0:        /* Error after error */
  261.         break;
  262.         }
  263.         break;
  264.  
  265.     case 2:            /* Record of zeroes */
  266.     case EOF:        /* End of archive */
  267.     default:
  268.         return(-1);
  269.     }
  270.     }
  271. }
  272.  
  273.  
  274. /* readcpio - read a CPIO header 
  275.  *
  276.  * DESCRIPTION
  277.  *
  278.  *    Read in a cpio header.  Understands how to determine and read ASCII, 
  279.  *    binary and byte-swapped binary headers.  Quietly translates 
  280.  *    old-fashioned binary cpio headers (and arranges to skip the possible 
  281.  *    alignment byte). Returns zero if successful, -1 upon archive trailer. 
  282.  *
  283.  * PARAMETERS
  284.  *
  285.  *    char    *name     - name of the file for which the header is
  286.  *              for.  This is modified and passed back to
  287.  *              the caller.
  288.  *    Stat    *asb    - Stat block for the file for which the header
  289.  *              is for.  The fields of the stat structure are
  290.  *              extracted from the archive header.  This is
  291.  *              also passed back to the caller.
  292.  *
  293.  * RETURNS
  294.  *
  295.  *    Returns 0 if a valid header was found, or -1 if EOF is
  296.  *    encountered.
  297.  */
  298.  
  299. #ifdef __STDC__
  300.  
  301. static int readcpio(char *name, Stat *asb)
  302.  
  303. #else
  304.     
  305. static int readcpio(name, asb)
  306. char           *name;
  307. Stat           *asb;
  308.  
  309. #endif
  310. {
  311.     OFFSET          skipped;
  312.     char            magic[M_STRLEN];
  313.     static int      align;
  314.  
  315.     if (align > 0) {
  316.     buf_skip((OFFSET) align);
  317.     }
  318.     align = 0;
  319.     for (;;) {
  320.     buf_read(magic, M_STRLEN);
  321.     skipped = 0;
  322.     while ((align = inascii(magic, name, asb)) < 0
  323.            && (align = inbinary(magic, name, asb)) < 0
  324.            && (align = inswab(magic, name, asb)) < 0) {
  325.         if (++skipped == 1) {
  326.         if (total - sizeof(magic) == 0) {
  327.             fatal("Unrecognizable archive");
  328.         }
  329.         warnarch("Bad magic number", (OFFSET) sizeof(magic));
  330.         if (name[0]) {
  331.             warn(name, "May be corrupt");
  332.         }
  333.         }
  334.         memcpy(magic, magic + 1, sizeof(magic) - 1);
  335.         buf_read(magic + sizeof(magic) - 1, 1);
  336.     }
  337.     if (skipped) {
  338.         warnarch("Apparently resynchronized", (OFFSET) sizeof(magic));
  339.         warn(name, "Continuing");
  340.     }
  341.     if (strcmp(name, TRAILER) == 0) {
  342.         return (-1);
  343.     }
  344.     if (nameopt(name) >= 0) {
  345.         break;
  346.     }
  347.     buf_skip((OFFSET) asb->sb_size + align);
  348.     }
  349. #ifdef    S_IFLNK
  350.     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  351.     if (buf_read(asb->sb_link, (uint) asb->sb_size) < 0) {
  352.         warn(name, "Corrupt symbolic link");
  353.         return (readcpio(name, asb));
  354.     }
  355.     asb->sb_link[asb->sb_size] = '\0';
  356.     asb->sb_size = 0;
  357.     }
  358. #endif                /* S_IFLNK */
  359.  
  360.     /* destroy absolute pathnames for security reasons */
  361.     if (name[0] == '/') {
  362.     if (name[1]) {
  363.         while (name[0] = name[1]) {
  364.         ++name;
  365.         }
  366.     } else {
  367.         name[0] = '.';
  368.     }
  369.     }
  370.     asb->sb_atime = asb->sb_ctime = asb->sb_mtime;
  371.     if (asb->sb_nlink > 1) {
  372.     linkto(name, asb);
  373.     }
  374.     return (0);
  375. }
  376.  
  377.  
  378. /* inswab - read a reversed by order binary header
  379.  *
  380.  * DESCRIPTIONS
  381.  *
  382.  *    Reads a byte-swapped CPIO binary archive header
  383.  *
  384.  * PARMAMETERS
  385.  *
  386.  *    char    *magic    - magic number to match
  387.  *    char    *name    - name of the file which is stored in the header.
  388.  *              (modified and passed back to caller).
  389.  *    Stat    *asb    - stat block for the file (modified and passed back
  390.  *              to the caller).
  391.  *
  392.  *
  393.  * RETURNS
  394.  *
  395.  *     Returns the number of trailing alignment bytes to skip; -1 if 
  396.  *    unsuccessful. 
  397.  *
  398.  */
  399.  
  400. #ifdef __STDC__
  401.  
  402. static int inswab(char *magic, char *name, Stat *asb)
  403.  
  404. #else
  405.     
  406. static int inswab(magic, name, asb)
  407. char           *magic;
  408. char           *name;
  409. Stat           *asb;
  410.  
  411. #endif
  412. {
  413.     ushort          namesize;
  414.     uint            namefull;
  415.     Binary          binary;
  416.  
  417.     if (*((ushort *) magic) != SWAB(M_BINARY)) {
  418.     return (-1);
  419.     }
  420.     memcpy((char *) &binary,
  421.           magic + sizeof(ushort),
  422.           M_STRLEN - sizeof(ushort));
  423.     if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
  424.          sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
  425.     warnarch("Corrupt swapped header",
  426.          (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  427.     return (-1);
  428.     }
  429.     asb->sb_dev = (dev_t) SWAB(binary.b_dev);
  430.     asb->sb_ino = (ino_t) SWAB(binary.b_ino);
  431.     asb->sb_mode = SWAB(binary.b_mode);
  432.     asb->sb_uid = SWAB(binary.b_uid);
  433.     asb->sb_gid = SWAB(binary.b_gid);
  434.     asb->sb_nlink = SWAB(binary.b_nlink);
  435.     asb->sb_rdev = (dev_t) SWAB(binary.b_rdev);
  436.     asb->sb_mtime = SWAB(binary.b_mtime[0]) << 16 | SWAB(binary.b_mtime[1]);
  437.     asb->sb_size = SWAB(binary.b_size[0]) << 16 | SWAB(binary.b_size[1]);
  438.     if ((namesize = SWAB(binary.b_name)) == 0 || namesize >= PATH_MAX) {
  439.     warnarch("Bad swapped pathname length",
  440.          (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  441.     return (-1);
  442.     }
  443.     if (buf_read(name, namefull = namesize + namesize % 2) < 0) {
  444.     warnarch("Corrupt swapped pathname", (OFFSET) namefull);
  445.     return (-1);
  446.     }
  447.     if (name[namesize - 1] != '\0') {
  448.     warnarch("Bad swapped pathname", (OFFSET) namefull);
  449.     return (-1);
  450.     }
  451.     return (asb->sb_size % 2);
  452. }
  453.  
  454.  
  455. /* inascii - read in an ASCII cpio header
  456.  *
  457.  * DESCRIPTION
  458.  *
  459.  *    Reads an ASCII format cpio header
  460.  *
  461.  * PARAMETERS
  462.  *
  463.  *    char    *magic    - magic number to match
  464.  *    char    *name    - name of the file which is stored in the header.
  465.  *              (modified and passed back to caller).
  466.  *    Stat    *asb    - stat block for the file (modified and passed back
  467.  *              to the caller).
  468.  *
  469.  * RETURNS
  470.  *
  471.  *     Returns zero if successful; -1 otherwise. Assumes that  the entire 
  472.  *    magic number has been read. 
  473.  */
  474.  
  475. #ifdef __STDC__
  476.  
  477. static int inascii(char *magic, char *name, Stat *asb)
  478.  
  479. #else
  480.     
  481. static int inascii(magic, name, asb)
  482. char           *magic;
  483. char           *name;
  484. Stat           *asb;
  485.  
  486. #endif
  487. {
  488.     uint            namelen;
  489.     char            header[H_STRLEN + 1];
  490.  
  491.     if (strncmp(magic, M_ASCII, M_STRLEN) != 0) {
  492.     return (-1);
  493.     }
  494.     if (buf_read(header, H_STRLEN) < 0) {
  495.     warnarch("Corrupt ASCII header", (OFFSET) H_STRLEN);
  496.     return (-1);
  497.     }
  498.     header[H_STRLEN] = '\0';
  499.     if (sscanf(header, H_SCAN, &asb->sb_dev,
  500.            &asb->sb_ino, &asb->sb_mode, &asb->sb_uid,
  501.            &asb->sb_gid, &asb->sb_nlink, &asb->sb_rdev,
  502.            &asb->sb_mtime, &namelen, &asb->sb_size) != H_COUNT) {
  503.     warnarch("Bad ASCII header", (OFFSET) H_STRLEN);
  504.     return (-1);
  505.     }
  506.     if (namelen == 0 || namelen >= PATH_MAX) {
  507.     warnarch("Bad ASCII pathname length", (OFFSET) H_STRLEN);
  508.     return (-1);
  509.     }
  510.     if (buf_read(name, namelen) < 0) {
  511.     warnarch("Corrupt ASCII pathname", (OFFSET) namelen);
  512.     return (-1);
  513.     }
  514.     if (name[namelen - 1] != '\0') {
  515.     warnarch("Bad ASCII pathname", (OFFSET) namelen);
  516.     return (-1);
  517.     }
  518.     return (0);
  519. }
  520.  
  521.  
  522. /* inbinary - read a binary header
  523.  *
  524.  * DESCRIPTION
  525.  *
  526.  *    Reads a CPIO format binary header.
  527.  *
  528.  * PARAMETERS
  529.  *
  530.  *    char    *magic    - magic number to match
  531.  *    char    *name    - name of the file which is stored in the header.
  532.  *              (modified and passed back to caller).
  533.  *    Stat    *asb    - stat block for the file (modified and passed back
  534.  *              to the caller).
  535.  *
  536.  * RETURNS
  537.  *
  538.  *     Returns the number of trailing alignment bytes to skip; -1 if 
  539.  *    unsuccessful. 
  540.  */
  541.  
  542. #ifdef __STDC__
  543.  
  544. static int inbinary(char *magic, char *name, Stat *asb)
  545.  
  546. #else
  547.     
  548. static int inbinary(magic, name, asb)
  549. char           *magic;
  550. char           *name;
  551. Stat           *asb;
  552.  
  553. #endif
  554. {
  555.     uint            namefull;
  556.     Binary          binary;
  557.  
  558.     if (*((ushort *) magic) != M_BINARY) {
  559.     return (-1);
  560.     }
  561.     memcpy((char *) &binary,
  562.           magic + sizeof(ushort),
  563.           M_STRLEN - sizeof(ushort));
  564.     if (buf_read((char *) &binary + M_STRLEN - sizeof(ushort),
  565.          sizeof(binary) - (M_STRLEN - sizeof(ushort))) < 0) {
  566.     warnarch("Corrupt binary header",
  567.          (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  568.     return (-1);
  569.     }
  570.     asb->sb_dev = binary.b_dev;
  571.     asb->sb_ino = binary.b_ino;
  572.     asb->sb_mode = binary.b_mode;
  573.     asb->sb_uid = binary.b_uid;
  574.     asb->sb_gid = binary.b_gid;
  575.     asb->sb_nlink = binary.b_nlink;
  576.     asb->sb_rdev = binary.b_rdev;
  577.     asb->sb_mtime = binary.b_mtime[0] << 16 | binary.b_mtime[1];
  578.     asb->sb_size = binary.b_size[0] << 16 | binary.b_size[1];
  579.     if (binary.b_name == 0 || binary.b_name >= PATH_MAX) {
  580.     warnarch("Bad binary pathname length",
  581.          (OFFSET) sizeof(binary) - (M_STRLEN - sizeof(ushort)));
  582.     return (-1);
  583.     }
  584.     if (buf_read(name, namefull = binary.b_name + binary.b_name % 2) < 0) {
  585.     warnarch("Corrupt binary pathname", (OFFSET) namefull);
  586.     return (-1);
  587.     }
  588.     if (name[binary.b_name - 1] != '\0') {
  589.     warnarch("Bad binary pathname", (OFFSET) namefull);
  590.     return (-1);
  591.     }
  592.     return (asb->sb_size % 2);
  593. }
  594.