]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
1.13.25
[chaz/tar] / src / tar.c
index fcd23a8fc5f4b045bb1399a0f669d86f5d9c38f2..7d87f80159909f0a34b7c3ff493a0496dee6d5cb 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,5 +1,8 @@
 /* A tar (tape archiver) program.
-   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
@@ -18,6 +21,7 @@
 
 #include "system.h"
 
+#include <fnmatch.h>
 #include <getopt.h>
 
 #include <signal.h>
 # define SIGCHLD SIGCLD
 #endif
 
-#include <time.h>
-#ifndef time
-time_t time ();
-#endif
-
 /* 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
@@ -37,6 +36,7 @@ time_t time ();
 #define GLOBAL
 #include "common.h"
 
+#include <print-copyr.h>
 #include <localedir.h>
 #include <prepargs.h>
 #include <quotearg.h>
@@ -126,15 +126,21 @@ confirm (const char *message_action, const char *message_name)
 
 enum
 {
-  BACKUP_OPTION = CHAR_MAX + 1,
+  ANCHORED_OPTION = CHAR_MAX + 1,
+  BACKUP_OPTION,
   DELETE_OPTION,
   EXCLUDE_OPTION,
   GROUP_OPTION,
+  IGNORE_CASE_OPTION,
   MODE_OPTION,
   NEWER_MTIME_OPTION,
-  NO_RECURSE_OPTION,
+  NO_ANCHORED_OPTION,
+  NO_IGNORE_CASE_OPTION,
+  NO_WILDCARDS_OPTION,
+  NO_WILDCARDS_MATCH_SLASH_OPTION,
   NULL_OPTION,
   OVERWRITE_OPTION,
+  OVERWRITE_DIR_OPTION,
   OWNER_OPTION,
   POSIX_OPTION,
   PRESERVE_OPTION,
@@ -143,6 +149,8 @@ enum
   SUFFIX_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
@@ -168,6 +176,7 @@ 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},
   {"backup", optional_argument, 0, BACKUP_OPTION},
@@ -199,6 +208,7 @@ static struct option long_options[] =
   {"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-zeros", no_argument, 0, 'i'},
   /* FIXME: --ignore-end as a new name for --ignore-zeros?  */
@@ -216,19 +226,25 @@ static struct option long_options[] =
   {"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},
+  {"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},
   {"preserve", no_argument, 0, PRESERVE_OPTION},
   {"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},
   {"read-full-records", no_argument, 0, 'B'},
@@ -258,6 +274,8 @@ static struct option long_options[] =
   {"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}
 };
@@ -307,6 +325,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\
   -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\
@@ -371,10 +390,18 @@ Archive format selection:\n\
 \n\
 Local file selection:\n\
   -C, --directory=DIR          change to directory DIR\n\
-  -T, -I, --files-from=NAME    get names to extract or create from file NAME\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\
@@ -384,7 +411,7 @@ Local file selection:\n\
 #if !MSDOS
       fputs (_("\
   -N, --newer=DATE             only store files newer than DATE\n\
-      --newer-mtime            compare date and time when data changed only\n\
+      --newer-mtime=DATE       compare date and time when data changed only\n\
       --after-date=DATE        same as -N\n"),
             stdout);
 #endif
@@ -418,8 +445,9 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\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);
     }
@@ -428,17 +456,18 @@ or a device.  *This* `tar' defaults to `-f%s -b%d'.\n"),
 
 /* Parse the options for tar.  */
 
-/* Available option letters are DEHJQY and aenqy.  Some are reserved:
+/* Available option letters are DEHIJQY 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)
+   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
    y  per-file gzip compression
    Y  per-block gzip compression */
 
 #define OPTION_STRING \
-  "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hijklmoprstuvwxz"
+  "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hijklmoprstuvwxyz"
 
 static void
 set_subcommand_option (enum subcommand subcommand)
@@ -460,18 +489,6 @@ set_use_compress_program_option (const char *string)
   use_compress_program_option = string;
 }
 
-/* Ignore DUMMY (which will always be null in practice), and add
-   PATTERN to the proper set of patterns to be excluded -- either
-   patterns with slashes, or patterns without.  */
-static void
-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 **argv)
 {
@@ -479,6 +496,7 @@ decode_options (int argc, char **argv)
   int input_files;             /* number of input files */
   const char *backup_suffix_string;
   const char *version_control_string = 0;
+  int exclude_options = EXCLUDE_WILDCARDS;
 
   /* Set some default option values.  */
 
@@ -486,9 +504,9 @@ decode_options (int argc, char **argv)
   archive_format = DEFAULT_FORMAT;
   blocking_factor = DEFAULT_BLOCKING;
   record_size = DEFAULT_BLOCKING * BLOCKSIZE;
-  excluded_with_slash = new_exclude ();
-  excluded_without_slash = new_exclude ();
+  excluded = new_exclude ();
   newer_mtime_option = TYPE_MINIMUM (time_t);
+  recursion_option = FNM_LEADING_DIR;
 
   owner_option = -1;
   group_option = -1;
@@ -673,6 +691,12 @@ decode_options (int argc, char **argv)
        ignore_zeros_option = 1;
        break;
 
+      case 'I':
+       USAGE_ERROR ((0, 0,
+                     _("Warning: the -I option is not supported;"
+                       " perhaps you meant -j or -T?")));
+       break;
+
       case 'j':
        set_use_compress_program_option ("bzip2");
        break;
@@ -726,13 +750,28 @@ decode_options (int argc, char **argv)
        /* Fall through.  */
 
       case NEWER_MTIME_OPTION:
-       if (newer_mtime_option != TYPE_MINIMUM (time_t))
+       if (newer_mtime_option != TYPE_MINIMUM (time_t))
          USAGE_ERROR ((0, 0, _("More than one threshold date")));
 
-       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)));
+         }
 
        break;
 #endif /* not MSDOS */
@@ -795,7 +834,6 @@ decode_options (int argc, char **argv)
        break;
 
       case 'T':
-      case 'I': /* for compatibility with Solaris tar */
        files_from_option = optarg;
        break;
 
@@ -828,13 +866,21 @@ decode_options (int argc, char **argv)
        break;
 
       case 'X':
-       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;
 
+      case 'y':
+       USAGE_ERROR ((0, 0,
+                     _("Warning: the -y option is not supported;"
+                       " perhaps you meant -j?")));
+       break;
+
       case 'z':
        set_use_compress_program_option ("gzip");
        break;
@@ -847,6 +893,10 @@ decode_options (int argc, char **argv)
        WARN ((0, 0, _("Obsolete option name replaced by --backup")));
        /* Fall through.  */
 
+      case ANCHORED_OPTION:
+       exclude_options |= EXCLUDE_ANCHORED;
+       break;
+
       case BACKUP_OPTION:
        backup_option = 1;
        if (optarg)
@@ -858,7 +908,11 @@ decode_options (int argc, char **argv)
        break;
 
       case EXCLUDE_OPTION:
-       add_filtered_exclude (0, optarg);
+       add_exclude (excluded, optarg, exclude_options | recursion_option);
+       break;
+
+      case IGNORE_CASE_OPTION:
+       exclude_options |= FNM_CASEFOLD;
        break;
 
       case GROUP_OPTION:
@@ -885,8 +939,20 @@ decode_options (int argc, char **argv)
          xalloc_die ();
        break;
 
-      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;
        break;
 
       case NULL_OPTION:
@@ -897,6 +963,10 @@ decode_options (int argc, char **argv)
        old_files_option = OVERWRITE_OLD_FILES;
        break;
 
+      case OVERWRITE_DIR_OPTION:
+       old_files_option = OVERWRITE_OLD_DIRS;
+       break;
+
       case OWNER_OPTION:
        if (! (strlen (optarg) < UNAME_FIELD_SIZE
               && uname_to_uid (optarg, &owner_option)))
@@ -954,12 +1024,20 @@ decode_options (int argc, char **argv)
        backup_suffix_string = optarg;
        break;
 
+      case USE_COMPRESS_PROGRAM_OPTION:
+       set_use_compress_program_option (optarg);
+       break;
+
       case VOLNO_FILE_OPTION:
        volno_file_option = optarg;
        break;
 
-      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;
        break;
 
       case '0':
@@ -1052,13 +1130,15 @@ decode_options (int argc, char **argv)
 
   if (show_version)
     {
-      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\
-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."));
+
       exit (TAREXIT_SUCCESS);
     }
 
@@ -1107,6 +1187,24 @@ see the file named COPYING for details."),
     USAGE_ERROR ((0, 0,
                  _("Cannot combine --listed-incremental with --newer")));
 
+  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;
This page took 0.035446 seconds and 4 git commands to generate.