- Copyright 1988, 92,93,94,95,96,97,99, 2000 Free Software Foundation, Inc.
+
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001
+ 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
Written by John Gilmore, starting 1985-08-25.
This program is free software; you can redistribute it and/or modify it
/* The following causes "common.h" to produce definitions of all the global
variables, rather than just "extern" declarations of them. GNU tar does
depend on the system loader to preset all GLOBAL variables to neutral (or
/* The following causes "common.h" to produce definitions of all the global
variables, rather than just "extern" declarations of them. GNU tar does
depend on the system loader to preset all GLOBAL variables to neutral (or
-/*--------------------------------------------------------.
-| Returns true if and only if the user typed 'y' or 'Y'. |
-`--------------------------------------------------------*/
-
+/* Returns true if and only if the user typed 'y' or 'Y'. */
/* 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
/* 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
{
{"absolute-names", no_argument, 0, 'P'},
{"absolute-paths", no_argument, 0, OBSOLETE_ABSOLUTE_NAMES},
{"after-date", required_argument, 0, 'N'},
{
{"absolute-names", no_argument, 0, 'P'},
{"absolute-paths", no_argument, 0, OBSOLETE_ABSOLUTE_NAMES},
{"after-date", required_argument, 0, 'N'},
{"append", no_argument, 0, 'r'},
{"atime-preserve", no_argument, &atime_preserve_option, 1},
{"backup", optional_argument, 0, BACKUP_OPTION},
{"append", no_argument, 0, 'r'},
{"atime-preserve", no_argument, &atime_preserve_option, 1},
{"backup", optional_argument, 0, BACKUP_OPTION},
{"block-number", no_argument, 0, 'R'},
{"block-size", required_argument, 0, OBSOLETE_BLOCKING_FACTOR},
{"blocking-factor", required_argument, 0, 'b'},
{"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'},
{"catenate", no_argument, 0, 'A'},
{"checkpoint", no_argument, &checkpoint_option, 1},
{"compare", no_argument, 0, 'd'},
{"gunzip", no_argument, 0, 'z'},
{"gzip", no_argument, 0, 'z'},
{"help", no_argument, &show_help, 1},
{"gunzip", no_argument, 0, 'z'},
{"gzip", no_argument, 0, 'z'},
{"help", no_argument, &show_help, 1},
{"ignore-failed-read", no_argument, &ignore_failed_read_option, 1},
{"ignore-zeros", no_argument, 0, 'i'},
/* FIXME: --ignore-end as a new name for --ignore-zeros? */
{"ignore-failed-read", no_argument, &ignore_failed_read_option, 1},
{"ignore-zeros", no_argument, 0, 'i'},
/* FIXME: --ignore-end as a new name for --ignore-zeros? */
{"newer", required_argument, 0, 'N'},
{"newer-mtime", required_argument, 0, NEWER_MTIME_OPTION},
{"null", no_argument, 0, NULL_OPTION},
{"newer", required_argument, 0, 'N'},
{"newer-mtime", required_argument, 0, NEWER_MTIME_OPTION},
{"null", no_argument, 0, NULL_OPTION},
- {"no-recursion", no_argument, 0, NO_RECURSE_OPTION},
+ {"no-anchored", no_argument, 0, NO_ANCHORED_OPTION},
+ {"no-ignore-case", no_argument, 0, NO_IGNORE_CASE_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},
{"old-archive", no_argument, 0, 'o'},
{"one-file-system", no_argument, 0, 'l'},
{"overwrite", no_argument, 0, OVERWRITE_OPTION},
{"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},
{"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},
{"preserve", no_argument, 0, PRESERVE_OPTION},
{"preserve-order", no_argument, 0, 's'},
{"preserve-permissions", no_argument, 0, 'p'},
{"owner", required_argument, 0, OWNER_OPTION},
{"portability", no_argument, 0, 'o'},
{"posix", no_argument, 0, POSIX_OPTION},
{"preserve", no_argument, 0, PRESERVE_OPTION},
{"preserve-order", no_argument, 0, 's'},
{"preserve-permissions", no_argument, 0, 'p'},
{"recursive-unlink", no_argument, &recursive_unlink_option, 1},
{"read-full-blocks", no_argument, 0, OBSOLETE_READ_FULL_RECORDS},
{"read-full-records", no_argument, 0, 'B'},
{"recursive-unlink", no_argument, &recursive_unlink_option, 1},
{"read-full-blocks", no_argument, 0, OBSOLETE_READ_FULL_RECORDS},
{"read-full-records", no_argument, 0, 'B'},
{"version", no_argument, &show_version, 1},
{"version-control", required_argument, 0, OBSOLETE_VERSION_CONTROL},
{"volno-file", required_argument, 0, VOLNO_FILE_OPTION},
{"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},
--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\
--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\
-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\
-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\
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\
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\
-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"),
-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"),
-C, --directory=DIR change to directory DIR\n\
-T, --files-from=NAME get names to extract or create from file NAME\n\
--null -T reads null-terminated names, disable -C\n\
-C, --directory=DIR change to directory DIR\n\
-T, --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\
+ --exclude=PATTERN exclude files, given as a PATTERN\n\
+ -X, --exclude-from=FILE exclude patterns listed in FILE\n\
+ --anchored exclude patterns match file name start (default)\n\
+ --no-anchored exclude patterns match after any /\n\
+ --ignore-case exclusion ignores case\n\
+ --no-ignore-case exclusion is case sensitive (default)\n\
+ --wildcards exclude patterns use wildcards (default)\n\
+ --no-wildcards exclude patterns are plain strings\n\
+ --wildcards-match-slash exclude pattern wildcards match '/' (default)\n\
+ --no-wildcards-match-slash exclude pattern wildcards do not match '/'\n\
-P, --absolute-names don't strip leading `/'s from file names\n\
-h, --dereference dump instead the files symlinks point to\n\
--no-recursion avoid descending automatically in directories\n\
-P, --absolute-names don't strip leading `/'s from file names\n\
-h, --dereference dump instead the files symlinks point to\n\
--no-recursion avoid descending automatically in directories\n\
GNU tar cannot read nor produce `--posix' archives. If POSIXLY_CORRECT\n\
is set in the environment, GNU extensions are disallowed with `--posix'.\n\
Support for POSIX is only partially implemented, don't count on it yet.\n\
GNU tar cannot read nor produce `--posix' archives. If POSIXLY_CORRECT\n\
is set in the environment, GNU extensions are disallowed with `--posix'.\n\
Support for POSIX is only partially implemented, don't count on it yet.\n\
-ARCHIVE may be FILE, HOST:FILE or USER@HOST:FILE; and FILE may be a file\n\
-or a device. *This* `tar' defaults to `-f%s -b%d'.\n"),
+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 <bug-tar@gnu.org>.\n"), stdout);
}
exit (status);
}
DEFAULT_ARCHIVE, DEFAULT_BLOCKING);
fputs (_("\nReport bugs to <bug-tar@gnu.org>.\n"), stdout);
}
exit (status);
}
+ e exit immediately with a nonzero exit status if unexpected errors occur
+ E use extended headers (draft POSIX headers, that is)
+ I same as T (for compatibility with Solaris tar)
+ n the archive is quickly seekable, so don't worry about random seeks
+ q stop after extracting the first occurrence of the named file
-add_filtered_exclude (struct exclude *dummy, char const *pattern)
-{
- add_exclude ((strchr (pattern, '/')
- ? excluded_with_slash
- : excluded_without_slash),
- 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 */
const char *backup_suffix_string;
const char *version_control_string = 0;
{
int optchar; /* option letter */
int input_files; /* number of input files */
const char *backup_suffix_string;
const char *version_control_string = 0;
archive_format = DEFAULT_FORMAT;
blocking_factor = DEFAULT_BLOCKING;
record_size = DEFAULT_BLOCKING * BLOCKSIZE;
archive_format = DEFAULT_FORMAT;
blocking_factor = DEFAULT_BLOCKING;
record_size = DEFAULT_BLOCKING * BLOCKSIZE;
while (optchar = getopt_long (argc, argv, OPTION_STRING, long_options, 0),
optchar != -1)
switch (optchar)
while (optchar = getopt_long (argc, argv, OPTION_STRING, long_options, 0),
optchar != -1)
switch (optchar)
- USAGE_ERROR ((0, 0, _("Invalid blocking factor")));
+ USAGE_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
+ _("Invalid blocking factor")));
{
uintmax_t u;
if (xstrtoumax (optarg, 0, 10, &u, "") != LONGINT_OK)
{
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")));
- 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), quote (optarg)));
+ if (FILESYSTEM_PREFIX_LEN (optarg) != 0
+ || ISSLASH (*optarg)
+ || *optarg == '.')
+ {
+ struct stat st;
+ if (deref_stat (dereference_option, optarg, &st) != 0)
+ {
+ stat_error (optarg);
+ USAGE_ERROR ((0, 0, _("Date file not found")));
+ }
+ newer_mtime_option = st.st_mtime;
+ }
+ else
+ {
+ 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), quote (optarg)));
+ }
- if (add_exclude_file (add_filtered_exclude, 0, optarg, '\n') != 0)
+ if (add_exclude_file (add_exclude, excluded, optarg,
+ exclude_options | recursion_option, '\n')
+ != 0)
{
int e = errno;
FATAL_ERROR ((0, e, "%s", quotearg_colon (optarg)));
}
break;
{
int e = errno;
FATAL_ERROR ((0, e, "%s", quotearg_colon (optarg)));
}
break;
- add_filtered_exclude (0, optarg);
+ add_exclude (excluded, optarg, exclude_options | recursion_option);
+ break;
+
+ case IGNORE_CASE_OPTION:
+ exclude_options |= FNM_CASEFOLD;
- FATAL_ERROR ((0, 0, _("Invalid group given on option")));
+ FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
+ _("%s: Invalid group")));
- case NO_RECURSE_OPTION:
- no_recurse_option = 1;
+ case NO_ANCHORED_OPTION:
+ exclude_options &= ~ EXCLUDE_ANCHORED;
+ break;
+
+ case NO_IGNORE_CASE_OPTION:
+ exclude_options &= ~ FNM_CASEFOLD;
+ break;
+
+ case NO_WILDCARDS_OPTION:
+ exclude_options &= ~ EXCLUDE_WILDCARDS;
+ break;
+
+ case NO_WILDCARDS_MATCH_SLASH_OPTION:
+ exclude_options |= FNM_FILE_NAME;
case OWNER_OPTION:
if (! (strlen (optarg) < UNAME_FIELD_SIZE
&& uname_to_uid (optarg, &owner_option)))
case OWNER_OPTION:
if (! (strlen (optarg) < UNAME_FIELD_SIZE
&& uname_to_uid (optarg, &owner_option)))
- FATAL_ERROR ((0, 0, _("Invalid owner given on option")));
+ FATAL_ERROR ((0, 0, "%s: %s", quotearg_colon (optarg),
+ _("Invalid owner")));
uintmax_t u;
if (! (xstrtoumax (optarg, 0, 10, &u, "") == LONGINT_OK
&& u == (size_t) u))
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."),
record_size = u;
if (record_size % BLOCKSIZE != 0)
USAGE_ERROR ((0, 0, _("Record size must be a multiple of %d."),
- case USE_COMPRESS_PROGRAM_OPTION:
- set_use_compress_program_option (optarg);
+ case WILDCARDS_OPTION:
+ exclude_options |= EXCLUDE_WILDCARDS;
+ break;
+
+ case WILDCARDS_MATCH_SLASH_OPTION:
+ exclude_options &= ~ FNM_FILE_NAME;
- printf ("tar (GNU %s) %s\n%s\n%s\n%s\n", PACKAGE, VERSION,
- "Copyright 2000 Free Software Foundation, Inc.",
- _("\
+ printf ("tar (GNU %s) %s\n", PACKAGE, VERSION);
+ print_copyright ("2001 Free Software Foundation, Inc.");
+ 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\
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\
-see the file named COPYING for details."),
- _("Written by John Gilmore and Jay Fenlason."));
+see the file named COPYING for details."));
+
+ puts (_("Written by John Gilmore and Jay Fenlason."));
+
+ if (volume_label_option)
+ {
+ size_t volume_label_max_len =
+ (sizeof current_header->header.name
+ - 1 /* for trailing '\0' */
+ - (multi_volume_option
+ ? (sizeof " Volume "
+ - 1 /* for null at end of " Volume " */
+ + INT_STRLEN_BOUND (int) /* for volume number */
+ - 1 /* for sign, as 0 <= volno */)
+ : 0));
+ if (volume_label_max_len < strlen (volume_label_option))
+ USAGE_ERROR ((0, 0,
+ _("%s: Volume label is too long (limit is %lu bytes)"),
+ quotearg_colon (volume_label_option),
+ (unsigned long) volume_label_max_len));
+ }
+
/* If ready to unlink hierarchies, so we are for simpler files. */
if (recursive_unlink_option)
old_files_option = UNLINK_FIRST_OLD_FILES;
/* If ready to unlink hierarchies, so we are for simpler files. */
if (recursive_unlink_option)
old_files_option = UNLINK_FIRST_OLD_FILES;
for (archive_name_cursor = archive_name_array;
archive_name_cursor < archive_name_array + archive_names;
archive_name_cursor++)
if (!strcmp (*archive_name_cursor, "-"))
USAGE_ERROR ((0, 0,
for (archive_name_cursor = archive_name_array;
archive_name_cursor < archive_name_array + archive_names;
archive_name_cursor++)
if (!strcmp (*archive_name_cursor, "-"))
USAGE_ERROR ((0, 0,