Annotation of coherent/e/bin/pax/pax.c, revision 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.