X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftar.c;h=fc7cea5dcc041518bde153d830c8f4d8323cd03c;hb=db783659b0cc4bf162bec41685be23f72f25f721;hp=7d87f80159909f0a34b7c3ff493a0496dee6d5cb;hpb=5a5f4d06e7588bf06411d34aff79b6f0f482a9a7;p=chaz%2Ftar diff --git a/src/tar.c b/src/tar.c index 7d87f80..fc7cea5 100644 --- a/src/tar.c +++ b/src/tar.c @@ -1,7 +1,7 @@ /* A tar (tape archiver) program. - Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001 - Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, + 2001, 2003 Free Software Foundation, Inc. Written by John Gilmore, starting 1985-08-25. @@ -36,14 +36,12 @@ #define GLOBAL #include "common.h" -#include +#include #include #include #include #include -time_t get_date (); - /* Local declarations. */ #ifndef DEFAULT_ARCHIVE @@ -54,7 +52,7 @@ time_t get_date (); # define DEFAULT_BLOCKING 20 #endif -static void usage PARAMS ((int)) __attribute__ ((noreturn)); +static void usage (int) __attribute__ ((noreturn)); /* Miscellaneous. */ @@ -127,42 +125,40 @@ confirm (const char *message_action, const char *message_name) enum { ANCHORED_OPTION = CHAR_MAX + 1, + ATIME_PRESERVE_OPTION, BACKUP_OPTION, + CHECKPOINT_OPTION, DELETE_OPTION, EXCLUDE_OPTION, + FORCE_LOCAL_OPTION, GROUP_OPTION, IGNORE_CASE_OPTION, + IGNORE_FAILED_READ_OPTION, + INDEX_FILE_OPTION, MODE_OPTION, NEWER_MTIME_OPTION, NO_ANCHORED_OPTION, NO_IGNORE_CASE_OPTION, + NO_OVERWRITE_DIR_OPTION, NO_WILDCARDS_OPTION, NO_WILDCARDS_MATCH_SLASH_OPTION, NULL_OPTION, + NUMERIC_OWNER_OPTION, OVERWRITE_OPTION, - OVERWRITE_DIR_OPTION, OWNER_OPTION, POSIX_OPTION, PRESERVE_OPTION, RECORD_SIZE_OPTION, + RECURSIVE_UNLINK_OPTION, + REMOVE_FILES_OPTION, RSH_COMMAND_OPTION, + SHOW_OMITTED_DIRS_OPTION, SUFFIX_OPTION, + TOTALS_OPTION, USE_COMPRESS_PROGRAM_OPTION, VOLNO_FILE_OPTION, WILDCARDS_OPTION, WILDCARDS_MATCH_SLASH_OPTION, - - /* Some cleanup is being made in GNU tar long options. Using old names is - allowed for a while, but will also send a warning to stderr. Take old - names out in 1.14, or in summer 1997, whichever happens last. */ - - OBSOLETE_ABSOLUTE_NAMES, - OBSOLETE_BLOCK_COMPRESS, - OBSOLETE_BLOCKING_FACTOR, - OBSOLETE_BLOCK_NUMBER, - OBSOLETE_READ_FULL_RECORDS, - OBSOLETE_TOUCH, - OBSOLETE_VERSION_CONTROL }; /* If nonzero, display usage information and exit. */ @@ -174,19 +170,17 @@ static int show_version; static struct option long_options[] = { {"absolute-names", no_argument, 0, 'P'}, - {"absolute-paths", no_argument, 0, OBSOLETE_ABSOLUTE_NAMES}, {"after-date", required_argument, 0, 'N'}, {"anchored", no_argument, 0, ANCHORED_OPTION}, {"append", no_argument, 0, 'r'}, - {"atime-preserve", no_argument, &atime_preserve_option, 1}, + {"atime-preserve", no_argument, 0, ATIME_PRESERVE_OPTION}, {"backup", optional_argument, 0, BACKUP_OPTION}, - {"block-compress", no_argument, 0, OBSOLETE_BLOCK_COMPRESS}, {"block-number", no_argument, 0, 'R'}, - {"block-size", required_argument, 0, OBSOLETE_BLOCKING_FACTOR}, {"blocking-factor", required_argument, 0, 'b'}, {"bzip2", no_argument, 0, 'j'}, {"catenate", no_argument, 0, 'A'}, - {"checkpoint", no_argument, &checkpoint_option, 1}, + {"checkpoint", no_argument, 0, CHECKPOINT_OPTION}, + {"check-links", no_argument, &check_links_option, 1}, {"compare", no_argument, 0, 'd'}, {"compress", no_argument, 0, 'Z'}, {"concatenate", no_argument, 0, 'A'}, @@ -202,17 +196,18 @@ static struct option long_options[] = {"extract", no_argument, 0, 'x'}, {"file", required_argument, 0, 'f'}, {"files-from", required_argument, 0, 'T'}, - {"force-local", no_argument, &force_local_option, 1}, + {"force-local", no_argument, 0, FORCE_LOCAL_OPTION}, {"get", no_argument, 0, 'x'}, {"group", required_argument, 0, GROUP_OPTION}, {"gunzip", no_argument, 0, 'z'}, {"gzip", no_argument, 0, 'z'}, {"help", no_argument, &show_help, 1}, {"ignore-case", no_argument, 0, IGNORE_CASE_OPTION}, - {"ignore-failed-read", no_argument, &ignore_failed_read_option, 1}, + {"ignore-failed-read", no_argument, 0, IGNORE_FAILED_READ_OPTION}, {"ignore-zeros", no_argument, 0, 'i'}, /* FIXME: --ignore-end as a new name for --ignore-zeros? */ {"incremental", no_argument, 0, 'G'}, + {"index-file", required_argument, 0, INDEX_FILE_OPTION}, {"info-script", required_argument, 0, 'F'}, {"interactive", no_argument, 0, 'w'}, {"keep-old-files", no_argument, 0, 'k'}, @@ -220,7 +215,6 @@ static struct option long_options[] = {"list", no_argument, 0, 't'}, {"listed-incremental", required_argument, 0, 'g'}, {"mode", required_argument, 0, MODE_OPTION}, - {"modification-time", no_argument, 0, OBSOLETE_TOUCH}, {"multi-volume", no_argument, 0, 'M'}, {"new-volume-script", required_argument, 0, 'F'}, {"newer", required_argument, 0, 'N'}, @@ -228,16 +222,16 @@ static struct option long_options[] = {"null", no_argument, 0, NULL_OPTION}, {"no-anchored", no_argument, 0, NO_ANCHORED_OPTION}, {"no-ignore-case", no_argument, 0, NO_IGNORE_CASE_OPTION}, + {"no-overwrite-dir", no_argument, 0, NO_OVERWRITE_DIR_OPTION}, {"no-wildcards", no_argument, 0, NO_WILDCARDS_OPTION}, {"no-wildcards-match-slash", no_argument, 0, NO_WILDCARDS_MATCH_SLASH_OPTION}, {"no-recursion", no_argument, &recursion_option, 0}, {"no-same-owner", no_argument, &same_owner_option, -1}, {"no-same-permissions", no_argument, &same_permissions_option, -1}, - {"numeric-owner", no_argument, &numeric_owner_option, 1}, + {"numeric-owner", no_argument, 0, NUMERIC_OWNER_OPTION}, {"old-archive", no_argument, 0, 'o'}, {"one-file-system", no_argument, 0, 'l'}, {"overwrite", no_argument, 0, OVERWRITE_OPTION}, - {"overwrite-dir", no_argument, 0, OVERWRITE_DIR_OPTION}, {"owner", required_argument, 0, OWNER_OPTION}, {"portability", no_argument, 0, 'o'}, {"posix", no_argument, 0, POSIX_OPTION}, @@ -245,24 +239,22 @@ static struct option long_options[] = {"preserve-order", no_argument, 0, 's'}, {"preserve-permissions", no_argument, 0, 'p'}, {"recursion", no_argument, &recursion_option, FNM_LEADING_DIR}, - {"recursive-unlink", no_argument, &recursive_unlink_option, 1}, - {"read-full-blocks", no_argument, 0, OBSOLETE_READ_FULL_RECORDS}, + {"recursive-unlink", no_argument, 0, RECURSIVE_UNLINK_OPTION}, {"read-full-records", no_argument, 0, 'B'}, /* FIXME: --partial-blocks might be a synonym for --read-full-records? */ - {"record-number", no_argument, 0, OBSOLETE_BLOCK_NUMBER}, {"record-size", required_argument, 0, RECORD_SIZE_OPTION}, - {"remove-files", no_argument, &remove_files_option, 1}, + {"remove-files", no_argument, 0, REMOVE_FILES_OPTION}, {"rsh-command", required_argument, 0, RSH_COMMAND_OPTION}, {"same-order", no_argument, 0, 's'}, {"same-owner", no_argument, &same_owner_option, 1}, {"same-permissions", no_argument, 0, 'p'}, - {"show-omitted-dirs", no_argument, &show_omitted_dirs_option, 1}, + {"show-omitted-dirs", no_argument, 0, SHOW_OMITTED_DIRS_OPTION}, {"sparse", no_argument, 0, 'S'}, {"starting-file", required_argument, 0, 'K'}, {"suffix", required_argument, 0, SUFFIX_OPTION}, {"tape-length", required_argument, 0, 'L'}, {"to-stdout", no_argument, 0, 'O'}, - {"totals", no_argument, &totals_option, 1}, + {"totals", no_argument, 0, TOTALS_OPTION}, {"touch", no_argument, 0, 'm'}, {"uncompress", no_argument, 0, 'Z'}, {"ungzip", no_argument, 0, 'z'}, @@ -272,11 +264,10 @@ static struct option long_options[] = {"verbose", no_argument, 0, 'v'}, {"verify", no_argument, 0, 'W'}, {"version", no_argument, &show_version, 1}, - {"version-control", required_argument, 0, OBSOLETE_VERSION_CONTROL}, {"volno-file", required_argument, 0, VOLNO_FILE_OPTION}, {"wildcards", no_argument, 0, WILDCARDS_OPTION}, {"wildcards-match-slash", no_argument, 0, WILDCARDS_MATCH_SLASH_OPTION}, - + {0, 0, 0, 0} }; @@ -325,7 +316,7 @@ Operation modifiers:\n\ --remove-files remove files after adding them to the archive\n\ -k, --keep-old-files don't replace existing files when extracting\n\ --overwrite overwrite existing files when extracting\n\ - --overwrite-dir overwrite directory metadata when extracting\n\ + --no-overwrite-dir preserve metadata of existing directories\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\ @@ -379,7 +370,7 @@ Device blocking:\n\ Archive format selection:\n\ -V, --label=NAME create archive with volume name NAME\n\ PATTERN at list/extract time, a globbing PATTERN\n\ - -o, --old-archive, --portability write a V7 format archive\n\ + --old-archive, --portability write a V7 format archive\n\ --posix write a POSIX format archive\n\ -j, --bzip2 filter the archive through bzip2\n\ -z, --gzip, --ungzip filter the archive through gzip\n\ @@ -426,13 +417,22 @@ Informative output:\n\ --version print tar program version number, then exit\n\ -v, --verbose verbosely list files processed\n\ --checkpoint print directory names while reading the archive\n\ + --check-links print a message if not all links are dumped\n\ --totals print total bytes written while creating archive\n\ + --index-file=FILE send verbose output to FILE\n\ -R, --block-number show block number within archive with each message\n\ -w, --interactive ask for confirmation for every action\n\ --confirmation same as -w\n"), stdout); fputs (_("\ \n\ +Compatibility options:\n\ + -o when creating, same as --old-archive\n\ + when extracting, same as --no-same-owner\n"), + stdout); + + fputs (_("\ +\n\ The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\ The version control may be set with --backup or VERSION_CONTROL, values are:\n\ \n\ @@ -449,7 +449,7 @@ ARCHIVE may be FILE, HOST:FILE or USER@HOST:FILE; DATE may be a textual date\n\ or a file name starting with `/' or `.', in which case the file's date is used.\n\ *This* `tar' defaults to `-f%s -b%d'.\n"), DEFAULT_ARCHIVE, DEFAULT_BLOCKING); - fputs (_("\nReport bugs to .\n"), stdout); + printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit (status); } @@ -494,10 +494,12 @@ decode_options (int argc, char **argv) { int optchar; /* option letter */ int input_files; /* number of input files */ - const char *backup_suffix_string; - const char *version_control_string = 0; + char const *textual_date_option = 0; + char const *backup_suffix_string; + char const *version_control_string = 0; int exclude_options = EXCLUDE_WILDCARDS; - + int o_option = 0; + /* Set some default option values. */ subcommand_option = UNKNOWN_SUBCOMMAND; @@ -534,7 +536,7 @@ decode_options (int argc, char **argv) /* Allocate a new argument array, and copy program name in it. */ new_argc = argc - 1 + strlen (argv[1]); - new_argv = xmalloc (new_argc * sizeof (char *)); + new_argv = xmalloc ((new_argc + 1) * sizeof (char *)); in = argv; out = new_argv; *out++ = *in++; @@ -561,6 +563,7 @@ decode_options (int argc, char **argv) while (in < argv + argc) *out++ = *in++; + *out = 0; /* Replace the old option list by the new one. */ @@ -596,14 +599,6 @@ decode_options (int argc, char **argv) set_subcommand_option (CAT_SUBCOMMAND); break; - case OBSOLETE_BLOCK_COMPRESS: - WARN ((0, 0, _("Obsolete option, now implied by --blocking-factor"))); - break; - - case OBSOLETE_BLOCKING_FACTOR: - WARN ((0, 0, _("Obsolete option name replaced by --blocking-factor"))); - /* Fall through. */ - case 'b': { uintmax_t u; @@ -616,11 +611,6 @@ decode_options (int argc, char **argv) } break; - case OBSOLETE_READ_FULL_RECORDS: - WARN ((0, 0, - _("Obsolete option name replaced by --read-full-records"))); - /* Fall through. */ - case 'B': /* Try to reblock input records. For reading 4.2BSD pipes. */ @@ -729,10 +719,6 @@ decode_options (int argc, char **argv) } break; - case OBSOLETE_TOUCH: - WARN ((0, 0, _("Obsolete option name replaced by --touch"))); - /* Fall through. */ - case 'm': touch_option = 1; break; @@ -771,16 +757,15 @@ decode_options (int argc, char **argv) if (newer_mtime_option == (time_t) -1) WARN ((0, 0, _("Substituting %s for unknown date format %s"), tartime (newer_mtime_option), quote (optarg))); + else + textual_date_option = optarg; } break; #endif /* not MSDOS */ case 'o': - if (archive_format == DEFAULT_FORMAT) - archive_format = V7_FORMAT; - else if (archive_format != V7_FORMAT) - USAGE_ERROR ((0, 0, _("Conflicting archive format options"))); + o_option = 1; break; case 'O': @@ -791,10 +776,6 @@ decode_options (int argc, char **argv) same_permissions_option = 1; break; - case OBSOLETE_ABSOLUTE_NAMES: - WARN ((0, 0, _("Obsolete option name replaced by --absolute-names"))); - /* Fall through. */ - case 'P': absolute_names_option = 1; break; @@ -803,10 +784,6 @@ decode_options (int argc, char **argv) set_subcommand_option (APPEND_SUBCOMMAND); break; - case OBSOLETE_BLOCK_NUMBER: - WARN ((0, 0, _("Obsolete option name replaced by --block-number"))); - /* Fall through. */ - case 'R': /* Print block numbers for debugging bad tar archives. */ @@ -889,14 +866,18 @@ decode_options (int argc, char **argv) set_use_compress_program_option ("compress"); break; - case OBSOLETE_VERSION_CONTROL: - WARN ((0, 0, _("Obsolete option name replaced by --backup"))); - /* Fall through. */ - case ANCHORED_OPTION: exclude_options |= EXCLUDE_ANCHORED; break; + case ATIME_PRESERVE_OPTION: + atime_preserve_option = 1; + break; + + case CHECKPOINT_OPTION: + checkpoint_option = 1; + break; + case BACKUP_OPTION: backup_option = 1; if (optarg) @@ -911,10 +892,22 @@ decode_options (int argc, char **argv) add_exclude (excluded, optarg, exclude_options | recursion_option); break; + case FORCE_LOCAL_OPTION: + force_local_option = 1; + break; + + case INDEX_FILE_OPTION: + index_file_name = optarg; + break; + case IGNORE_CASE_OPTION: exclude_options |= FNM_CASEFOLD; break; + case IGNORE_FAILED_READ_OPTION: + ignore_failed_read_option = 1; + break; + case GROUP_OPTION: if (! (strlen (optarg) < GNAME_FIELD_SIZE && gname_to_gid (optarg, &group_option))) @@ -947,6 +940,10 @@ decode_options (int argc, char **argv) exclude_options &= ~ FNM_CASEFOLD; break; + case NO_OVERWRITE_DIR_OPTION: + old_files_option = NO_OVERWRITE_DIR_OLD_FILES; + break; + case NO_WILDCARDS_OPTION: exclude_options &= ~ EXCLUDE_WILDCARDS; break; @@ -959,12 +956,12 @@ decode_options (int argc, char **argv) filename_terminator = '\0'; break; - case OVERWRITE_OPTION: - old_files_option = OVERWRITE_OLD_FILES; + case NUMERIC_OWNER_OPTION: + numeric_owner_option = 1; break; - case OVERWRITE_DIR_OPTION: - old_files_option = OVERWRITE_OLD_DIRS; + case OVERWRITE_OPTION: + old_files_option = OVERWRITE_OLD_FILES; break; case OWNER_OPTION: @@ -1015,6 +1012,14 @@ decode_options (int argc, char **argv) } break; + case RECURSIVE_UNLINK_OPTION: + recursive_unlink_option = 1; + break; + + case REMOVE_FILES_OPTION: + remove_files_option = 1; + break; + case RSH_COMMAND_OPTION: rsh_command_option = optarg; break; @@ -1119,6 +1124,32 @@ decode_options (int argc, char **argv) #endif /* not DEVICE_PREFIX */ } + /* Special handling for 'o' option: + + GNU tar used to say "output old format". + UNIX98 tar says don't chown files after extracting (we use + "--no-same-owner" for this). + + The old GNU tar semantics is retained when used with --create + option, otherwise UNIX98 semantics is assumed */ + + if (o_option) + { + if (subcommand_option == CREATE_SUBCOMMAND) + { + /* GNU Tar <= 1.13 compatibility */ + if (archive_format == DEFAULT_FORMAT) + archive_format = V7_FORMAT; + else if (archive_format != V7_FORMAT) + USAGE_ERROR ((0, 0, _("Conflicting archive format options"))); + } + else + { + /* UNIX98 compatibility */ + same_owner_option = 1; + } + } + /* Handle operands after any "--" argument. */ for (; optind < argc; optind++) { @@ -1130,8 +1161,8 @@ decode_options (int argc, char **argv) if (show_version) { - printf ("tar (GNU %s) %s\n", PACKAGE, VERSION); - print_copyright ("2001 Free Software Foundation, Inc."); + printf ("tar (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + printf (_("Copyright (C) %d Free Software Foundation, Inc.\n"), 2003); puts (_("\ 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\ @@ -1253,6 +1284,14 @@ see the file named COPYING for details.")); if (backup_option) backup_type = xget_version ("--backup", version_control_string); + + if (verbose_option && textual_date_option) + { + char const *treated_as = tartime (newer_mtime_option); + if (strcmp (textual_date_option, treated_as) != 0) + WARN ((0, 0, _("Treating date `%s' as %s"), + textual_date_option, treated_as)); + } } /* Tar proper. */ @@ -1325,7 +1364,11 @@ main (int argc, char **argv) case EXTRACT_SUBCOMMAND: extr_init (); read_and (extract_archive); + + /* FIXME: should extract_finish () even if an ordinary signal is + received. */ extract_finish (); + break; case LIST_SUBCOMMAND: @@ -1338,6 +1381,9 @@ main (int argc, char **argv) break; } + if (check_links_option) + check_links (); + if (volno_file_option) closeout_volume_number (); @@ -1346,9 +1392,22 @@ main (int argc, char **argv) free (archive_name_array); name_term (); - if (stdlis == stdout && (ferror (stdout) || fclose (stdout) != 0)) + if (stdlis != stderr && (ferror (stdlis) || fclose (stdlis) != 0)) FATAL_ERROR ((0, 0, _("Error in writing to standard output"))); if (exit_status == TAREXIT_FAILURE) error (0, 0, _("Error exit delayed from previous errors")); + if (ferror (stderr) || fclose (stderr) != 0) + exit_status = TAREXIT_FAILURE; exit (exit_status); } + +void +destroy_stat (struct tar_stat_info *st) +{ + free (st->orig_file_name); + free (st->file_name); + free (st->link_name); + free (st->uname); + free (st->gname); + memset (st, 0, sizeof (*st)); +}