diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/cmd/pax/pax.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/pax/pax.c')
-rwxr-xr-x | sys/src/ape/cmd/pax/pax.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/sys/src/ape/cmd/pax/pax.c b/sys/src/ape/cmd/pax/pax.c new file mode 100755 index 000000000..25e22b962 --- /dev/null +++ b/sys/src/ape/cmd/pax/pax.c @@ -0,0 +1,530 @@ +/* $Source: /u/mark/src/pax/RCS/pax.c,v $ + * + * $Revision: 1.2 $ + * + * DESCRIPTION + * + * Pax is the archiver described in IEEE P1003.2. It is an archiver + * which understands both tar and cpio archives and has a new interface. + * + * SYNOPSIS + * + * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] + * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...] + * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...] + * [-t device][-x format][pathname...] + * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory + * + * DESCRIPTION + * + * PAX - POSIX conforming tar and cpio archive handler. This + * program implements POSIX conformant versions of tar, cpio and pax + * archive handlers for UNIX. These handlers have defined befined + * by the IEEE P1003.2 commitee. + * + * COMPILATION + * + * A number of different compile time configuration options are + * available, please see the Makefile and config.h for more details. + * + * AUTHOR + * + * Mark H. Colburn, NAPS International (mark@jhereg.mn.org) + * + * + * Sponsored by The USENIX Association for public distribution. + * + * Copyright (c) 1989 Mark H. Colburn. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice is duplicated in all such + * forms and that any documentation, advertising materials, and other + * materials related to such distribution and use acknowledge that the + * software was developed * by Mark H. Colburn and sponsored by The + * USENIX Association. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Log: pax.c,v $ + * Revision 1.2 89/02/12 10:05:17 mark + * 1.2 release fixes + * + * Revision 1.1 88/12/23 18:02:23 mark + * Initial revision + * + */ + +#ifndef lint +static char *ident = "$Id: pax.c,v 1.2 89/02/12 10:05:17 mark Exp $"; +static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n"; +#endif /* ! lint */ + + +/* Headers */ + +#define NO_EXTERN +#include "pax.h" + + +/* Globally Available Identifiers */ + +char *ar_file; /* File containing name of archive */ +char *bufend; /* End of data within archive buffer */ +char *bufstart; /* Archive buffer */ +char *bufidx; /* Archive buffer index */ +char *myname; /* name of executable (argv[0]) */ +char **n_argv; /* Argv used by name routines */ +int n_argc; /* Argc used by name routines */ +int archivefd; /* Archive file descriptor */ +int blocking; /* Size of each block, in records */ +int gid; /* Group ID */ +int head_standard; /* true if archive is POSIX format */ +int ar_interface; /* defines interface we are using */ +int ar_format; /* defines current archve format */ +int mask; /* File creation mask */ +int ttyf; /* For interactive queries */ +int uid; /* User ID */ +int names_from_stdin; /* names for files are from stdin */ +OFFSET total; /* Total number of bytes transferred */ +short f_access_time; /* Reset access times of input files */ +short areof; /* End of input volume reached */ +short f_dir_create; /* Create missing directories */ +short f_append; /* Add named files to end of archive */ +short f_create; /* create a new archive */ +short f_extract; /* Extract named files from archive */ +short f_follow_links; /* follow symbolic links */ +short f_interactive; /* Interactivly extract files */ +short f_linksleft; /* Report on unresolved links */ +short f_list; /* List files on the archive */ +short f_modified; /* Don't restore modification times */ +short f_verbose; /* Turn on verbose mode */ +short f_link; /* link files where possible */ +short f_owner; /* extract files as the user */ +short f_pass; /* pass files between directories */ +short f_newer; /* append files to archive if newer */ +short f_disposition; /* ask for file disposition */ +short f_reverse_match; /* Reverse sense of pattern match */ +short f_mtime; /* Retain file modification time */ +short f_unconditional; /* Copy unconditionally */ +time_t now = 0; /* Current time */ +uint arvolume; /* Volume number */ +uint blocksize = BLOCKSIZE; /* Archive block size */ +FILE *msgfile; /* message outpu file stdout/stderr */ +Replstr *rplhead = (Replstr *)NULL; /* head of replstr list */ +Replstr *rpltail; /* pointer to tail of replstr list */ + + +/* Function Prototypes */ + +#ifdef __STDC__ + +static void usage(void); +static OFFSET pax_optsize(char *); + +#else /* !__STDC__ */ + +static void usage(); +static OFFSET pax_optsize(); + +#endif /* __STDC__ */ + + +/* main - main routine for handling all archive formats. + * + * DESCRIPTION + * + * Set up globals and call the proper interface as specified by the user. + * + * PARAMETERS + * + * int argc - count of user supplied arguments + * char **argv - user supplied arguments + * + * RETURNS + * + * Returns an exit code of 0 to the parent process. + */ + +#ifdef __STDC__ + +int main(int argc, char **argv) + +#else + +int main(argc, argv) +int argc; +char **argv; + +#endif +{ + /* strip the pathname off of the name of the executable */ + if ((myname = strrchr(argv[0], '/')) != (char *)NULL) { + myname++; + } else { + myname = argv[0]; + } + + /* set upt for collecting other command line arguments */ + name_init(argc, argv); + + /* get all our necessary information */ + mask = umask(0); + uid = getuid(); + gid = getgid(); + now = time((time_t *) 0); + + /* open terminal for interactive queries */ + ttyf = open_tty(); + + if (strcmp(myname, "tar")==0) { + do_tar(argc, argv); + } else if (strcmp(myname, "cpio")==0) { + do_cpio(argc, argv); + } else { + do_pax(argc, argv); + } + exit(0); + /* NOTREACHED */ +} + + +/* do_pax - provide a PAX conformant user interface for archive handling + * + * DESCRIPTION + * + * Process the command line parameters given, doing some minimal sanity + * checking, and then launch the specified archiving functions. + * + * PARAMETERS + * + * int ac - A count of arguments in av. Should be passed argc + * from main + * char **av - A pointer to an argument list. Should be passed + * argv from main + * + * RETURNS + * + * Normally returns 0. If an error occurs, -1 is returned + * and state is set to reflect the error. + * + */ + +#ifdef __STDC__ + +int do_pax(int ac, char **av) + +#else + +int do_pax(ac, av) +int ac; /* argument counter */ +char **av; /* arguments */ + +#endif +{ + int c; + char *dirname; + Stat st; + + /* default input/output file for PAX is STDIN/STDOUT */ + ar_file = "-"; + + /* + * set up the flags to reflect the default pax inteface. Unfortunately + * the pax interface has several options which are completely opposite + * of the tar and/or cpio interfaces... + */ + f_unconditional = 1; + f_mtime = 1; + f_dir_create = 1; + f_list = 1; + blocksize = 0; + blocking = 0; + ar_interface = PAX; + ar_format = TAR; /* default interface if none given for -w */ + msgfile=stdout; + + while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) { + switch (c) { + case 'a': + f_append = 1; + f_list = 0; + break; + case 'b': + if ((blocksize = pax_optsize(optarg)) == 0) { + fatal("Bad block size"); + } + break; + case 'c': + f_reverse_match = 1; + break; + case 'd': + f_dir_create = 0; + break; + case 'f': + if (blocksize == 0) { + blocking = 1; + blocksize = 1 * BLOCKSIZE; + } + ar_file = optarg; + break; + case 'i': + f_interactive = 1; + break; + case 'l': + f_link = 1; + break; + case 'm': + f_mtime = 0; + break; + case 'o': + f_owner = 1; + break; + case 'p': + f_access_time = 1; + break; + case 'r': + if (f_create) { + f_create = 0; + f_pass = 1; + } else { + f_list = 0; + f_extract = 1; + } + msgfile=stderr; + break; + case 's': + add_replstr(optarg); + break; + case 't': + if (blocksize == 0) { + blocking = 1; + blocksize = 10 * BLOCKSIZE; + } + ar_file = optarg; + break; + case 'u': + f_unconditional = 1; + break; + case 'v': + f_verbose = 1; + break; + case 'w': + if (f_extract) { + f_extract = 0; + f_pass = 1; + } else { + f_list = 0; + f_create = 1; + } + msgfile=stderr; + break; + case 'x': + if (strcmp(optarg, "ustar") == 0) { + ar_format = TAR; + } else if (strcmp(optarg, "cpio") == 0) { + ar_format = CPIO; + } else { + usage(); + } + break; + case 'y': + f_disposition = 1; + break; + default: + usage(); + } + } + + if (blocksize == 0) { + blocking = 1; + blocksize = blocking * BLOCKSIZE; + } + buf_allocate((OFFSET) blocksize); + + if (f_extract || f_list) { + open_archive(AR_READ); + get_archive_type(); + read_archive(); + } else if (f_create) { + if (optind >= n_argc) { + names_from_stdin++; /* args from stdin */ + } + open_archive(AR_WRITE); + create_archive(); + } else if (f_append) { + open_archive(AR_APPEND); + get_archive_type(); + append_archive(); + } else if (f_pass && optind < n_argc) { + dirname = n_argv[--n_argc]; + if (LSTAT(dirname, &st) < 0) { + fatal(strerror()); + } + if ((st.sb_mode & S_IFMT) != S_IFDIR) { + fatal("Not a directory"); + } + if (optind >= n_argc) { + names_from_stdin++; /* args from stdin */ + } + pass(dirname); + } else { + usage(); + } + + return (0); +} + + +/* get_archive_type - determine input archive type from archive header + * + * DESCRIPTION + * + * reads the first block of the archive and determines the archive + * type from the data. If the archive type cannot be determined, + * processing stops, and a 1 is returned to the caller. If verbose + * mode is on, then the archive type will be printed on the standard + * error device as it is determined. + * + * FIXME + * + * be able to understand TAR and CPIO magic numbers + */ + +#ifdef __STDC__ + +void get_archive_type(void) + +#else + +void get_archive_type() + +#endif +{ + if (ar_read() != 0) { + fatal("Unable to determine archive type."); + } + if (strncmp(bufstart, "070707", 6) == 0) { + ar_format = CPIO; + if (f_verbose) { + fputs("CPIO format archive\n", stderr); + } + } else if (strncmp(&bufstart[257], "ustar", 5) == 0) { + ar_format = TAR; + if (f_verbose) { + fputs("USTAR format archive\n", stderr); + } + } else { + ar_format = TAR; + } +} + + +/* pax_optsize - interpret a size argument + * + * DESCRIPTION + * + * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes. + * Also handles simple expressions containing '+' for addition. + * + * PARAMETERS + * + * char *str - A pointer to the string to interpret + * + * RETURNS + * + * Normally returns the value represented by the expression in the + * the string. + * + * ERRORS + * + * If the string cannot be interpretted, the program will fail, since + * the buffering will be incorrect. + * + */ + +#ifdef __STDC__ + +static OFFSET pax_optsize(char *str) + +#else + +static OFFSET pax_optsize(str) +char *str; /* pointer to string to interpret */ + +#endif +{ + char *idx; + OFFSET number; /* temporary storage for current number */ + OFFSET result; /* cumulative total to be returned to caller */ + + result = 0; + idx = str; + for (;;) { + number = 0; + while (*idx >= '0' && *idx <= '9') + number = number * 10 + *idx++ - '0'; + switch (*idx++) { + case 'b': + result += number * 512L; + continue; + case 'k': + result += number * 1024L; + continue; + case 'm': + result += number * 1024L * 1024L; + continue; + case '+': + result += number; + continue; + case '\0': + result += number; + break; + default: + break; + } + break; + } + if (*--idx) { + fatal("Unrecognizable value"); + } + return (result); +} + + +/* usage - print a helpful message and exit + * + * DESCRIPTION + * + * Usage prints out the usage message for the PAX interface and then + * exits with a non-zero termination status. This is used when a user + * has provided non-existant or incompatible command line arguments. + * + * RETURNS + * + * Returns an exit status of 1 to the parent process. + * + */ + +#ifdef __STDC__ + +static void usage(void) + +#else + +static void usage() + +#endif +{ + fprintf(stderr, "Usage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", + myname); + fprintf(stderr, " %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n", + myname); + fprintf(stderr, " %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n [-t device] [-x format] [pathname...]\n", + myname); + fprintf(stderr, " %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n", + myname); + exit(1); +} |