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

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

unix.superglobalmegacorp.com

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