Annotation of coherent/g/usr/bin/pax/pax.c, revision 1.1.1.1

1.1       root        1: /* $Source: /src386/usr/bin/pax/pax.c,v $
                      2:  *
                      3:  * $Revision: 1.1 $
                      4:  *
                      5:  * DESCRIPTION
                      6:  *
                      7:  *     Pax is the archiver described in IEEE P1003.2.  It is an archiver
                      8:  *     which understands both tar and cpio archives and has a new interface.
                      9:  *
                     10:  * SYNOPSIS
                     11:  *
                     12:  *     pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
                     13:  *     pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
                     14:  *     pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
                     15:  *            [-t device][-x format][pathname...]
                     16:  *     pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
                     17:  *
                     18:  * DESCRIPTION
                     19:  *
                     20:  *     PAX - POSIX conforming tar and cpio archive handler.  This
                     21:  *     program implements POSIX conformant versions of tar, cpio and pax
                     22:  *     archive handlers for UNIX.  These handlers have defined befined
                     23:  *     by the IEEE P1003.2 commitee.
                     24:  *
                     25:  * COMPILATION
                     26:  *
                     27:  *     A number of different compile time configuration options are
                     28:  *     available, please see the Makefile and config.h for more details.
                     29:  *
                     30:  * AUTHOR
                     31:  *
                     32:  *     Mark H. Colburn, NAPS International ([email protected])
                     33:  *
                     34:  *
                     35:  * Sponsored by The USENIX Association for public distribution. 
                     36:  *
                     37:  * Copyright (c) 1989 Mark H. Colburn.
                     38:  * All rights reserved.
                     39:  *
                     40:  * Redistribution and use in source and binary forms are permitted
                     41:  * provided that the above copyright notice is duplicated in all such 
                     42:  * forms and that any documentation, advertising materials, and other 
                     43:  * materials related to such distribution and use acknowledge that the 
                     44:  * software was developed * by Mark H. Colburn and sponsored by The 
                     45:  * USENIX Association. 
                     46:  *
                     47:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     48:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     49:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     50:  *
                     51:  * $Log:       pax.c,v $
                     52:  * Revision 1.1  92/08/28  08:02:49  bin
                     53:  * Initial revision
                     54:  * 
                     55:  * Revision 1.1  89/02/14  16:48:29  jep
                     56:  * Initial revision
                     57:  * 
                     58:  * Revision 1.1  88/12/23  18:02:23  mark
                     59:  * Initial revision
                     60:  * 
                     61:  */
                     62: 
                     63: #ifndef lint
                     64: static char *ident = "$Id: pax.c,v 1.1 92/08/28 08:02:49 bin Exp Locker: bin $";
                     65: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     66: #endif /* ! lint */
                     67: 
                     68: 
                     69: /* Headers */
                     70: 
                     71: #define NO_EXTERN
                     72: #include "pax.h"
                     73: 
                     74: 
                     75: /* Globally Available Identifiers */
                     76: 
                     77: char           *ar_file;               /* File containing name of archive */
                     78: char           *bufend;                        /* End of data within archive buffer */
                     79: char           *bufstart;              /* Archive buffer */
                     80: char           *bufidx;                        /* Archive buffer index */
                     81: char           *myname;                        /* name of executable (argv[0]) */
                     82: char          **n_argv;                        /* Argv used by name routines */
                     83: int             n_argc;                        /* Argc used by name routines */
                     84: int             archivefd;             /* Archive file descriptor */
                     85: int             blocking;              /* Size of each block, in records */
                     86: int             gid;                   /* Group ID */
                     87: int             head_standard;         /* true if archive is POSIX format */
                     88: int             ar_interface;          /* defines interface we are using */
                     89: int             ar_format;             /* defines current archve format */
                     90: int             mask;                  /* File creation mask */
                     91: int             ttyf;                  /* For interactive queries */
                     92: int             uid;                   /* User ID */
                     93: int            names_from_stdin;       /* names for files are from stdin */
                     94: OFFSET          total;                 /* Total number of bytes transferred */
                     95: short           f_access_time;         /* Reset access times of input files */
                     96: short           areof;                 /* End of input volume reached */
                     97: short           f_dir_create;          /* Create missing directories */
                     98: short           f_append;              /* Add named files to end of archive */
                     99: short           f_create;              /* create a new archive */
                    100: short           f_extract;             /* Extract named files from archive */
                    101: short           f_follow_links;                /* follow symbolic links */
                    102: short           f_interactive;         /* Interactivly extract files */
                    103: short           f_linksleft;           /* Report on unresolved links */
                    104: short           f_list;                        /* List files on the archive */
                    105: short           f_modified;            /* Don't restore modification times */
                    106: short           f_verbose;             /* Turn on verbose mode */
                    107: short          f_link;                 /* link files where possible */
                    108: short          f_owner;                /* extract files as the user */
                    109: short          f_pass;                 /* pass files between directories */
                    110: short           f_newer;               /* append files to archive if newer */
                    111: short          f_disposition;          /* ask for file disposition */
                    112: short           f_reverse_match;       /* Reverse sense of pattern match */
                    113: short           f_mtime;               /* Retain file modification time */
                    114: short           f_unconditional;       /* Copy unconditionally */
                    115: time_t          now = 0;               /* Current time */
                    116: uint            arvolume;              /* Volume number */
                    117: uint            blocksize = BLOCKSIZE; /* Archive block size */
                    118: FILE          *msgfile;                /* message outpu file stdout/stderr */
                    119: Replstr        *rplhead = (Replstr *)NULL;     /*  head of replstr list */
                    120: Replstr        *rpltail;               /* pointer to tail of replstr list */
                    121: 
                    122: 
                    123: /* Function Prototypes */
                    124: 
                    125: #if __STDC__
                    126: 
                    127: static void    usage(void);
                    128: static OFFSET   pax_optsize(char *);
                    129: 
                    130: #else /* !__STDC__ */
                    131: 
                    132: static void    usage();
                    133: static OFFSET   pax_optsize();
                    134: 
                    135: #endif /* __STDC__ */
                    136: 
                    137: 
                    138: /* main - main routine for handling all archive formats.
                    139:  *
                    140:  * DESCRIPTION
                    141:  *
                    142:  *     Set up globals and call the proper interface as specified by the user.
                    143:  *
                    144:  * PARAMETERS
                    145:  *
                    146:  *     int argc        - count of user supplied arguments
                    147:  *     char **argv     - user supplied arguments 
                    148:  *
                    149:  * RETURNS
                    150:  *
                    151:  *     Returns an exit code of 0 to the parent process.
                    152:  */
                    153: 
                    154: #if __STDC__
                    155: 
                    156: int main(int argc, char **argv)
                    157: 
                    158: #else
                    159: 
                    160: int main(argc, argv)
                    161: int             argc;
                    162: char          **argv;
                    163: 
                    164: #endif
                    165: {
                    166:     /* strip the pathname off of the name of the executable */
                    167:     if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
                    168:        myname++;
                    169:     } else {
                    170:        myname = argv[0];
                    171:     }
                    172: 
                    173:     /* set upt for collecting other command line arguments */
                    174:     name_init(argc, argv);
                    175: 
                    176:     /* get all our necessary information */
                    177:     mask = umask(0);
                    178:     uid = getuid();
                    179:     gid = getgid();
                    180:     now = time((time_t *) 0);
                    181: 
                    182:     /* open terminal for interactive queries */
                    183:     ttyf = open_tty();
                    184: 
                    185:     if (strcmp(myname, "ustar")==0 || strcmp(myname, "tar")==0) {
                    186:        do_tar(argc, argv);
                    187:     } else if (strcmp(myname, "cpio")==0) {
                    188:        do_cpio(argc, argv);
                    189:     } else {
                    190:        do_pax(argc, argv);
                    191:     }
                    192:     exit(0);
                    193:     /* NOTREACHED */
                    194: }
                    195: 
                    196: 
                    197: /* do_pax - provide a PAX conformant user interface for archive handling
                    198:  *
                    199:  * DESCRIPTION
                    200:  *
                    201:  *     Process the command line parameters given, doing some minimal sanity
                    202:  *     checking, and then launch the specified archiving functions.
                    203:  *
                    204:  * PARAMETERS
                    205:  *
                    206:  *    int ac           - A count of arguments in av.  Should be passed argc 
                    207:  *                       from main
                    208:  *    char **av                - A pointer to an argument list.  Should be passed 
                    209:  *                       argv from main
                    210:  *
                    211:  * RETURNS
                    212:  *
                    213:  *    Normally returns 0.  If an error occurs, -1 is returned 
                    214:  *    and state is set to reflect the error.
                    215:  *
                    216:  */
                    217: 
                    218: #if __STDC__
                    219: 
                    220: int do_pax(int ac, char **av)
                    221: 
                    222: #else
                    223: 
                    224: int do_pax(ac, av)
                    225: int             ac;            /* argument counter */
                    226: char          **av;            /* arguments */
                    227: 
                    228: #endif
                    229: {
                    230:     int             c;
                    231:     char          *dirname;
                    232:     Stat           st;
                    233: 
                    234:     /* default input/output file for PAX is STDIN/STDOUT */
                    235:     ar_file = "-";
                    236: 
                    237:     /*
                    238:      * set up the flags to reflect the default pax inteface.  Unfortunately
                    239:      * the pax interface has several options which are completely opposite
                    240:      * of the tar and/or cpio interfaces...
                    241:      */
                    242:     f_unconditional = 1;
                    243:     f_mtime = 1;
                    244:     f_dir_create = 1;
                    245:     f_list = 1;
                    246:     blocksize = 0;
                    247:     blocking = 0;
                    248:     ar_interface = PAX;
                    249:     ar_format = TAR;   /* default interface if none given for -w */
                    250:     msgfile=stdout;
                    251: 
                    252:     while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) {
                    253:        switch (c) {
                    254:        case 'a':
                    255:            f_append = 1;
                    256:            f_list = 0;
                    257:            break;
                    258:        case 'b':
                    259:            if ((blocksize = pax_optsize(optarg)) == 0) {
                    260:                fatal("Bad block size");
                    261:            }
                    262:            break;
                    263:        case 'c':
                    264:            f_reverse_match = 1;
                    265:            break;
                    266:        case 'd':
                    267:            f_dir_create = 0;
                    268:            break;
                    269:        case 'f':
                    270:            if (blocksize == 0) {
                    271:                blocking = 1;
                    272:                blocksize = 1 * BLOCKSIZE;
                    273:            }
                    274:            ar_file = optarg;
                    275:            break;
                    276:        case 'i':
                    277:            f_interactive = 1;
                    278:            break;
                    279:        case 'l':
                    280:            f_link = 1;
                    281:            break;
                    282:        case 'm':
                    283:            f_mtime = 0;
                    284:            break;
                    285:        case 'o':
                    286:            f_owner = 1;
                    287:            break;
                    288:        case 'p':
                    289:            f_access_time = 1;
                    290:            break;
                    291:        case 'r':
                    292:            if (f_create) {
                    293:                f_create = 0;
                    294:                f_pass = 1;
                    295:            } else {
                    296:                f_list = 0;
                    297:                f_extract = 1;
                    298:            } 
                    299:            msgfile=stderr;
                    300:            break;
                    301:        case 's':
                    302:            add_replstr(optarg);
                    303:            break;
                    304:        case 't':
                    305:            if (blocksize == 0) {
                    306:                blocking = 1;
                    307:                blocksize = 10 * BLOCKSIZE;
                    308:            }
                    309:            ar_file = optarg;
                    310:            break;
                    311:        case 'u':
                    312:            f_unconditional = 1;
                    313:            break;
                    314:        case 'v':
                    315:            f_verbose = 1;
                    316:            break;
                    317:        case 'w':
                    318:            if (f_extract) {
                    319:                f_extract = 0;
                    320:                f_pass = 1;
                    321:            } else {
                    322:                f_list = 0;
                    323:                f_create = 1;
                    324:            } 
                    325:            msgfile=stderr;
                    326:            break;
                    327:        case 'x':
                    328:            if (strcmp(optarg, "ustar") == 0) {
                    329:                ar_format = TAR;
                    330:            } else if (strcmp(optarg, "cpio") == 0) {
                    331:                ar_format = CPIO;
                    332:            } else {
                    333:                usage();
                    334:            }
                    335:            break;
                    336:        case 'y':
                    337:            f_disposition = 1;
                    338:            break;
                    339:        default:
                    340:            usage();
                    341:        }
                    342:     }
                    343: 
                    344:     if (blocksize == 0) {
                    345:        blocking = 1;
                    346:        blocksize = blocking * BLOCKSIZE;
                    347:     }
                    348:     buf_allocate((OFFSET) blocksize);
                    349: 
                    350:     if (f_extract || f_list) {
                    351:        open_archive(AR_READ);
                    352:        get_archive_type();
                    353:        read_archive();
                    354:     } else if (f_create) {
                    355:        if (optind >= n_argc) {
                    356:            names_from_stdin++;         /* args from stdin */
                    357:        }
                    358:        open_archive(AR_WRITE);
                    359:        create_archive();
                    360:     } else if (f_append) {
                    361:        open_archive(AR_APPEND);
                    362:        get_archive_type();
                    363:        append_archive();
                    364:     } else if (f_pass && optind < n_argc) {
                    365:        dirname = n_argv[--n_argc];
                    366:        if (LSTAT(dirname, &st) < 0) {
                    367:            fatal(strerror());
                    368:        }
                    369:        if ((st.sb_mode & S_IFMT) != S_IFDIR) {
                    370:            fatal("Not a directory");
                    371:        }
                    372:        if (optind >= n_argc) {
                    373:            names_from_stdin++;         /* args from stdin */
                    374:        }
                    375:        pass(dirname);
                    376:     } else {
                    377:        usage();
                    378:     }
                    379: 
                    380:     return (0);
                    381: }
                    382: 
                    383: 
                    384: /* get_archive_type - determine input archive type from archive header
                    385:  *
                    386:  * DESCRIPTION
                    387:  *
                    388:  *     reads the first block of the archive and determines the archive 
                    389:  *     type from the data.  If the archive type cannot be determined, 
                    390:  *     processing stops, and a 1 is returned to the caller.  If verbose
                    391:  *     mode is on, then the archive type will be printed on the standard
                    392:  *     error device as it is determined.
                    393:  *
                    394:  * FIXME 
                    395:  *
                    396:  *     be able to understand TAR and CPIO magic numbers
                    397:  */
                    398: 
                    399: #if __STDC__
                    400: 
                    401: void get_archive_type(void)
                    402: 
                    403: #else
                    404: 
                    405: void get_archive_type()
                    406: 
                    407: #endif
                    408: {
                    409:     if (ar_read() != 0) {
                    410:        fatal("Unable to determine archive type.");
                    411:     }
                    412:     if (strncmp(bufstart, "070707", 6) == 0) {
                    413:        ar_format = CPIO;
                    414:        if (f_verbose) {
                    415:            fputs("CPIO format archive\n", stderr);
                    416:        }
                    417:     } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
                    418:        ar_format = TAR;
                    419:        if (f_verbose) {
                    420:            fputs("USTAR format archive\n", stderr);
                    421:        }
                    422:     } else {
                    423:        ar_format = TAR;
                    424:        if (f_verbose) 
                    425:            fputs("TAR(v7) format archive\n", stderr);
                    426:     }
                    427: }
                    428: 
                    429: 
                    430: /* pax_optsize - interpret a size argument
                    431:  *
                    432:  * DESCRIPTION
                    433:  *
                    434:  *     Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.  
                    435:  *     Also handles simple expressions containing '+' for addition.
                    436:  *
                    437:  * PARAMETERS
                    438:  *
                    439:  *    char     *str    - A pointer to the string to interpret
                    440:  *
                    441:  * RETURNS
                    442:  *
                    443:  *    Normally returns the value represented by the expression in the 
                    444:  *    the string.
                    445:  *
                    446:  * ERRORS
                    447:  *
                    448:  *     If the string cannot be interpretted, the program will fail, since
                    449:  *     the buffering will be incorrect.
                    450:  *
                    451:  */
                    452: 
                    453: #if __STDC__
                    454: 
                    455: static OFFSET pax_optsize(char *str)
                    456: 
                    457: #else
                    458: 
                    459: static OFFSET pax_optsize(str)
                    460: char   *str;           /* pointer to string to interpret */
                    461: 
                    462: #endif
                    463: {
                    464:     char           *idx;
                    465:     OFFSET          number;    /* temporary storage for current number */
                    466:     OFFSET          result;    /* cumulative total to be returned to caller */
                    467: 
                    468:     result = 0;
                    469:     idx = str;
                    470:     for (;;) {
                    471:        number = 0;
                    472:        while (*idx >= '0' && *idx <= '9')
                    473:            number = number * 10 + *idx++ - '0';
                    474:        switch (*idx++) {
                    475:        case 'b':
                    476:            result += number * 512L;
                    477:            continue;
                    478:        case 'k':
                    479:            result += number * 1024L;
                    480:            continue;
                    481:        case 'm':
                    482:            result += number * 1024L * 1024L;
                    483:            continue;
                    484:        case '+':
                    485:            result += number;
                    486:            continue;
                    487:        case '\0':
                    488:            result += number;
                    489:            break;
                    490:        default:
                    491:            break;
                    492:        }
                    493:        break;
                    494:     }
                    495:     if (*--idx) {
                    496:        fatal("Unrecognizable value");
                    497:     }
                    498:     return (result);
                    499: }
                    500: 
                    501: 
                    502: /* usage - print a helpful message and exit
                    503:  *
                    504:  * DESCRIPTION
                    505:  *
                    506:  *     Usage prints out the usage message for the PAX interface and then
                    507:  *     exits with a non-zero termination status.  This is used when a user
                    508:  *     has provided non-existant or incompatible command line arguments.
                    509:  *
                    510:  * RETURNS
                    511:  *
                    512:  *     Returns an exit status of 1 to the parent process.
                    513:  *
                    514:  */
                    515: 
                    516: #if __STDC__
                    517: 
                    518: static void usage(void)
                    519: 
                    520: #else
                    521: 
                    522: static void usage()
                    523: 
                    524: #endif
                    525: {
                    526:     fprintf(stderr, "Usage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
                    527:        myname);
                    528:     fprintf(stderr, "       %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
                    529:        myname);
                    530:     fprintf(stderr, "       %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n              [-t device] [-x format] [pathname...]\n",
                    531:        myname);
                    532:     fprintf(stderr, "       %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
                    533:        myname);
                    534:     exit(1);
                    535: }

unix.superglobalmegacorp.com

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