X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftar.c;h=fcd23a8fc5f4b045bb1399a0f669d86f5d9c38f2;hb=614f749ff77c5e9817897ff8166bddd26915a78e;hp=dfbeca8eb70f90a9e49b510537f4c2cad4060d9b;hpb=859a4ec01f9174de4d3baea65b20b69c440ff8d0;p=chaz%2Ftar diff --git a/src/tar.c b/src/tar.c index dfbeca8..fcd23a8 100644 --- a/src/tar.c +++ b/src/tar.c @@ -1,5 +1,5 @@ /* A tar (tape archiver) program. - Copyright 1988, 92,93,94,95,96,97, 1999 Free Software Foundation, Inc. + Copyright 1988, 92,93,94,95,96,97,99, 2000 Free Software Foundation, Inc. Written by John Gilmore, starting 1985-08-25. This program is free software; you can redistribute it and/or modify it @@ -37,7 +37,10 @@ time_t time (); #define GLOBAL #include "common.h" -#include "xstrtol.h" +#include +#include +#include +#include time_t get_date (); @@ -51,17 +54,14 @@ time_t get_date (); # define DEFAULT_BLOCKING 20 #endif -static void usage PARAMS ((int)); +static void usage PARAMS ((int)) __attribute__ ((noreturn)); /* Miscellaneous. */ -/*----------------------------------------------. -| Doesn't return if stdin already requested. | -`----------------------------------------------*/ - /* Name of option using stdin. */ static const char *stdin_used_by; +/* Doesn't return if stdin already requested. */ void request_stdin (const char *option) { @@ -72,10 +72,7 @@ request_stdin (const char *option) stdin_used_by = option; } -/*--------------------------------------------------------. -| Returns true if and only if the user typed 'y' or 'Y'. | -`--------------------------------------------------------*/ - +/* Returns true if and only if the user typed 'y' or 'Y'. */ int confirm (const char *message_action, const char *message_name) { @@ -85,18 +82,19 @@ confirm (const char *message_action, const char *message_name) if (!confirm_file) { if (archive == 0 || stdin_used_by) - confirm_file = fopen (TTY_NAME, "r"); + { + confirm_file = fopen (TTY_NAME, "r"); + if (! confirm_file) + open_fatal (TTY_NAME); + } else { request_stdin ("-w"); confirm_file = stdin; } - - if (!confirm_file) - FATAL_ERROR ((0, 0, _("Cannot read confirmation from user"))); } - fprintf (stdlis, "%s %s?", message_action, message_name); + fprintf (stdlis, "%s %s?", message_action, quote (message_name)); fflush (stdlis); { @@ -136,6 +134,7 @@ enum NEWER_MTIME_OPTION, NO_RECURSE_OPTION, NULL_OPTION, + OVERWRITE_OPTION, OWNER_OPTION, POSIX_OPTION, PRESERVE_OPTION, @@ -164,7 +163,7 @@ static int show_help; /* If nonzero, print the version on standard output and exit. */ static int show_version; -struct option long_options[] = +static struct option long_options[] = { {"absolute-names", no_argument, 0, 'P'}, {"absolute-paths", no_argument, 0, OBSOLETE_ABSOLUTE_NAMES}, @@ -176,7 +175,7 @@ struct option long_options[] = {"block-number", no_argument, 0, 'R'}, {"block-size", required_argument, 0, OBSOLETE_BLOCKING_FACTOR}, {"blocking-factor", required_argument, 0, 'b'}, - {"bzip2", no_argument, 0, 'I'}, + {"bzip2", no_argument, 0, 'j'}, {"catenate", no_argument, 0, 'A'}, {"checkpoint", no_argument, &checkpoint_option, 1}, {"compare", no_argument, 0, 'd'}, @@ -223,6 +222,7 @@ struct option long_options[] = {"numeric-owner", no_argument, &numeric_owner_option, 1}, {"old-archive", no_argument, 0, 'o'}, {"one-file-system", no_argument, 0, 'l'}, + {"overwrite", no_argument, 0, OVERWRITE_OPTION}, {"owner", required_argument, 0, OWNER_OPTION}, {"portability", no_argument, 0, 'o'}, {"posix", no_argument, 0, POSIX_OPTION}, @@ -262,10 +262,7 @@ struct option long_options[] = {0, 0, 0, 0} }; -/*---------------------------------------------. -| Print a usage message and exit with STATUS. | -`---------------------------------------------*/ - +/* Print a usage message and exit with STATUS. */ static void usage (int status) { @@ -308,7 +305,8 @@ Main operation mode:\n\ Operation modifiers:\n\ -W, --verify attempt to verify the archive after writing it\n\ --remove-files remove files after adding them to the archive\n\ - -k, --keep-old-files don't overwrite existing files when extracting\n\ + -k, --keep-old-files don't replace existing files when extracting\n\ + --overwrite overwrite existing files when extracting\n\ -U, --unlink-first remove each file prior to extracting over it\n\ --recursive-unlink empty hierarchies prior to extracting directory\n\ -S, --sparse handle sparse files efficiently\n\ @@ -364,7 +362,7 @@ Archive format selection:\n\ PATTERN at list/extract time, a globbing PATTERN\n\ -o, --old-archive, --portability write a V7 format archive\n\ --posix write a POSIX format archive\n\ - -I, --bzip2 filter the archive through bzip2\n\ + -j, --bzip2 filter the archive through bzip2\n\ -z, --gzip, --ungzip filter the archive through gzip\n\ -Z, --compress, --uncompress filter the archive through compress\n\ --use-compress-program=PROG filter through PROG (must accept -d)\n"), @@ -373,7 +371,7 @@ Archive format selection:\n\ \n\ Local file selection:\n\ -C, --directory=DIR change to directory DIR\n\ - -T, --files-from=NAME get names to extract or create from file NAME\n\ + -T, -I, --files-from=NAME get names to extract or create from file NAME\n\ --null -T reads null-terminated names, disable -C\n\ --exclude=PATTERN exclude files, given as a globbing PATTERN\n\ -X, --exclude-from=FILE exclude globbing patterns listed in FILE\n\ @@ -428,17 +426,19 @@ or a device. *This* `tar' defaults to `-f%s -b%d'.\n"), exit (status); } -/*----------------------------. -| Parse the options for tar. | -`----------------------------*/ +/* Parse the options for tar. */ -/* Available option letters are DEHJQY and aejnqy. Some are reserved: +/* Available option letters are DEHJQY and aenqy. Some are reserved: + e exit immediately with a nonzero exit status if unexpected errors occur + E use extended headers (draft POSIX headers, that is) + n the archive is quickly seekable, so don't worry about random seeks + q stop after extracting the first occurrence of the named file y per-file gzip compression Y per-block gzip compression */ #define OPTION_STRING \ - "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hiklmoprstuvwxz" + "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hijklmoprstuvwxz" static void set_subcommand_option (enum subcommand subcommand) @@ -473,7 +473,7 @@ add_filtered_exclude (struct exclude *dummy, char const *pattern) } static void -decode_options (int argc, char *const *argv) +decode_options (int argc, char **argv) { int optchar; /* option letter */ int input_files; /* number of input files */ @@ -554,6 +554,8 @@ decode_options (int argc, char *const *argv) input_files = 0; + prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv); + while (optchar = getopt_long (argc, argv, OPTION_STRING, long_options, 0), optchar != -1) switch (optchar) @@ -591,7 +593,8 @@ decode_options (int argc, char *const *argv) && u == (blocking_factor = u) && 0 < blocking_factor && u == (record_size = u * BLOCKSIZE) / BLOCKSIZE)) - USAGE_ERROR ((0, 0, _("Invalid blocking factor"))); + USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg), + _("Invalid blocking factor"))); } break; @@ -670,14 +673,13 @@ decode_options (int argc, char *const *argv) ignore_zeros_option = 1; break; - case 'I': + case 'j': set_use_compress_program_option ("bzip2"); break; case 'k': - /* Don't overwrite existing files. */ - - keep_old_files_option = 1; + /* Don't replace existing files. */ + old_files_option = KEEP_OLD_FILES; break; case 'K': @@ -696,7 +698,8 @@ decode_options (int argc, char *const *argv) { uintmax_t u; if (xstrtoumax (optarg, 0, 10, &u, "") != LONGINT_OK) - USAGE_ERROR ((0, 0, _("Invalid tape length"))); + USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg), + _("Invalid tape length"))); tape_length_option = 1024 * (tarlong) u; multi_volume_option = 1; } @@ -728,8 +731,8 @@ decode_options (int argc, char *const *argv) newer_mtime_option = get_date (optarg, 0); if (newer_mtime_option == (time_t) -1) - WARN ((0, 0, _("Substituting %s for unknown date format `%s'"), - tartime (newer_mtime_option), optarg)); + WARN ((0, 0, _("Substituting %s for unknown date format %s"), + tartime (newer_mtime_option), quote (optarg))); break; #endif /* not MSDOS */ @@ -792,6 +795,7 @@ decode_options (int argc, char *const *argv) break; case 'T': + case 'I': /* for compatibility with Solaris tar */ files_from_option = optarg; break; @@ -800,7 +804,7 @@ decode_options (int argc, char *const *argv) break; case 'U': - unlink_first_option = 1; + old_files_option = UNLINK_FIRST_OLD_FILES; break; case 'v': @@ -825,7 +829,10 @@ decode_options (int argc, char *const *argv) case 'X': if (add_exclude_file (add_filtered_exclude, 0, optarg, '\n') != 0) - FATAL_ERROR ((0, errno, "%s", optarg)); + { + int e = errno; + FATAL_ERROR ((0, e, "%s", quotearg_colon (optarg))); + } break; case 'z': @@ -863,7 +870,8 @@ decode_options (int argc, char *const *argv) && g == (gid_t) g) group_option = g; else - FATAL_ERROR ((0, 0, _("Invalid group given on option"))); + FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg), + _("%s: Invalid group"))); } break; @@ -874,7 +882,7 @@ decode_options (int argc, char *const *argv) if (mode_option == MODE_INVALID) FATAL_ERROR ((0, 0, _("Invalid mode given on option"))); if (mode_option == MODE_MEMORY_EXHAUSTED) - FATAL_ERROR ((0, 0, _("Memory exhausted"))); + xalloc_die (); break; case NO_RECURSE_OPTION: @@ -885,6 +893,10 @@ decode_options (int argc, char *const *argv) filename_terminator = '\0'; break; + case OVERWRITE_OPTION: + old_files_option = OVERWRITE_OLD_FILES; + break; + case OWNER_OPTION: if (! (strlen (optarg) < UNAME_FIELD_SIZE && uname_to_uid (optarg, &owner_option))) @@ -894,7 +906,8 @@ decode_options (int argc, char *const *argv) && u == (uid_t) u) owner_option = u; else - FATAL_ERROR ((0, 0, _("Invalid owner given on option"))); + FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg), + _("Invalid owner"))); } break; @@ -922,7 +935,8 @@ decode_options (int argc, char *const *argv) uintmax_t u; if (! (xstrtoumax (optarg, 0, 10, &u, "") == LONGINT_OK && u == (size_t) u)) - USAGE_ERROR ((0, 0, _("Invalid record size"))); + USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg), + _("Invalid record size"))); record_size = u; if (record_size % BLOCKSIZE != 0) USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."), @@ -1039,7 +1053,7 @@ decode_options (int argc, char *const *argv) if (show_version) { printf ("tar (GNU %s) %s\n%s\n%s\n%s\n", PACKAGE, VERSION, - "Copyright 1999 Free Software Foundation, Inc.", + "Copyright 2000 Free Software Foundation, Inc.", _("\ This program comes with NO WARRANTY, to the extent permitted by law.\n\ You may redistribute it under the terms of the GNU General Public License;\n\ @@ -1095,7 +1109,7 @@ see the file named COPYING for details."), /* If ready to unlink hierarchies, so we are for simpler files. */ if (recursive_unlink_option) - unlink_first_option = 1; + old_files_option = UNLINK_FIRST_OLD_FILES; /* Forbid using -c with no input files whatsoever. Check that `-f -', explicit or implied, is used correctly. */ @@ -1145,12 +1159,9 @@ see the file named COPYING for details."), /* Tar proper. */ -/*-----------------------. -| Main routine for tar. | -`-----------------------*/ - +/* Main routine for tar. */ int -main (int argc, char *const *argv) +main (int argc, char **argv) { #if HAVE_CLOCK_GETTIME if (clock_gettime (CLOCK_REALTIME, &start_timespec) != 0) @@ -1163,6 +1174,7 @@ main (int argc, char *const *argv) exit_status = TAREXIT_SUCCESS; filename_terminator = '\n'; + set_quoting_style (0, escape_quoting_style); /* Pre-allocate a few structures. */ @@ -1215,6 +1227,7 @@ main (int argc, char *const *argv) case EXTRACT_SUBCOMMAND: extr_init (); read_and (extract_archive); + extract_finish (); break; case LIST_SUBCOMMAND: