Annotation of coherent/d/usr/bin/pax/shipping/extract.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.