]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Fix testsuite and bootstrap. Implement -I.
[chaz/tar] / src / tar.c
index ff3c5c957cf4270426b940335c4181d50aeb37a9..8396ad5e4e4e753f2c6284643b1939b7a52e3887 100644 (file)
--- a/src/tar.c
+++ b/src/tar.c
@@ -1,13 +1,13 @@
 /* A tar (tape archiver) program.
 
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
-   2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   2001, 2003, 2004, 2005, 2006, 2007 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
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -22,7 +22,6 @@
 #include <system.h>
 
 #include <fnmatch.h>
-#include <getline.h>
 #include <argp.h>
 #include <argp-namefrob.h>
 #include <argp-fmtstream.h>
 
 #include <argmatch.h>
 #include <closeout.h>
+#include <configmake.h>
 #include <exitfail.h>
 #include <getdate.h>
-#include <localedir.h>
 #include <rmt.h>
+#include <rmt-command.h>
 #include <prepargs.h>
 #include <quotearg.h>
 #include <version-etc.h>
@@ -249,11 +249,20 @@ enum
   ANCHORED_OPTION = CHAR_MAX + 1,
   ATIME_PRESERVE_OPTION,
   BACKUP_OPTION,
+  CHECK_DEVICE_OPTION,
   CHECKPOINT_OPTION,
+  CHECKPOINT_ACTION_OPTION,
   DELAY_DIRECTORY_RESTORE_OPTION,
+  HARD_DEREFERENCE_OPTION,
   DELETE_OPTION,
   EXCLUDE_CACHES_OPTION,
+  EXCLUDE_CACHES_UNDER_OPTION,
+  EXCLUDE_CACHES_ALL_OPTION,
   EXCLUDE_OPTION,
+  EXCLUDE_TAG_OPTION,
+  EXCLUDE_TAG_UNDER_OPTION,
+  EXCLUDE_TAG_ALL_OPTION,
+  EXCLUDE_VCS_OPTION,
   FORCE_LOCAL_OPTION,
   GROUP_OPTION,
   HANG_OPTION,
@@ -262,13 +271,17 @@ enum
   IGNORE_FAILED_READ_OPTION,
   INDEX_FILE_OPTION,
   KEEP_NEWER_FILES_OPTION,
+  LZOP_OPTION,
   MODE_OPTION,
   MTIME_OPTION,
   NEWER_MTIME_OPTION,
   NO_ANCHORED_OPTION,
+  NO_AUTO_COMPRESS_OPTION,
+  NO_CHECK_DEVICE_OPTION,
   NO_DELAY_DIRECTORY_RESTORE_OPTION,
   NO_IGNORE_CASE_OPTION,
   NO_IGNORE_COMMAND_ERROR_OPTION,
+  NO_NULL_OPTION,
   NO_OVERWRITE_DIR_OPTION,
   NO_QUOTE_CHARS_OPTION,
   NO_RECURSION_OPTION,
@@ -310,7 +323,6 @@ enum
   TRANSFORM_OPTION,
   UNQUOTE_OPTION,
   USAGE_OPTION,
-  USE_COMPRESS_PROGRAM_OPTION,
   UTC_OPTION,
   VERSION_OPTION,
   VOLNO_FILE_OPTION,
@@ -320,13 +332,16 @@ enum
 
 const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
-static char doc[] = N_("GNU `tar' saves many files together into a single tape or disk archive, and can restore individual files from the archive.\n\
+static char const doc[] = N_("\
+GNU `tar' saves many files together into a single tape or disk archive, \
+and can restore individual files from the archive.\n\
 \n\
 Examples:\n\
   tar -cf archive.tar foo bar  # Create archive.tar from files foo and bar.\n\
   tar -tvf archive.tar         # List all files in archive.tar verbosely.\n\
-  tar -xf archive.tar          # Extract all files from archive.tar.\n\
-\vThe backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
+  tar -xf archive.tar          # Extract all files from archive.tar.\n")
+"\v"
+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\
   none, off       never make backups\n\
   t, numbered     make numbered backups\n\
@@ -336,7 +351,7 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
 
 /* NOTE:
 
-   Available option letters are DEIJQY and aeqy. Consider the following
+   Available option letters are DEQY and eqy. Consider the following
    assignments:
 
    [For Solaris tar compatibility =/= Is it important at all?]
@@ -344,7 +359,6 @@ The version control may be set with --backup or VERSION_CONTROL, values are:\n\n
    E  use extended headers (--format=posix)
 
    [q  alias for --occurrence=1 =/= this would better be used for quiet?]
-   [I  same as T =/= will harm star compatibility]
 
    y  per-file gzip compression
    Y  per-block gzip compression */
@@ -399,11 +413,17 @@ static struct argp_option options[] = {
       " NUMBER defaults to 1"), GRID+1 },
   {"seek", 'n', NULL, 0,
    N_("archive is seekable"), GRID+1 },
+  {"no-check-device", NO_CHECK_DEVICE_OPTION, NULL, 0,
+   N_("do not check device numbers when creating incremental archives"),
+   GRID+1 },
+  {"check-device", CHECK_DEVICE_OPTION, NULL, 0,
+   N_("check device numbers when creating incremental archives (default)"),
+   GRID+1 },
 #undef GRID
 
 #define GRID 30
   {NULL, 0, NULL, 0,
-   N_("Overwrite control:"), GRID+1 },
+   N_("Overwrite control:"), GRID },
 
   {"verify", 'W', 0, 0,
    N_("attempt to verify the archive after writing it"), GRID+1 },
@@ -485,7 +505,7 @@ static struct argp_option options[] = {
 
 #define GRID 60
   {NULL, 0, NULL, 0,
-   N_("Device selection and switching:\n"), GRID+1 },
+   N_("Device selection and switching:"), GRID },
 
   {"file", 'f', N_("ARCHIVE"), 0,
    N_("use archive file or device ARCHIVE"), GRID+1 },
@@ -524,7 +544,7 @@ static struct argp_option options[] = {
 
 #define GRID 70
   {NULL, 0, NULL, 0,
-   N_("Device blocking:"), GRID+1 },
+   N_("Device blocking:"), GRID },
 
   {"blocking-factor", 'b', N_("BLOCKS"), 0,
    N_("BLOCKS x 512 bytes per record"), GRID+1 },
@@ -565,20 +585,34 @@ static struct argp_option options[] = {
    N_("control pax keywords"), GRID+8 },
   {"label", 'V', N_("TEXT"), 0,
    N_("create archive with volume name TEXT; at list/extract time, use TEXT as a globbing pattern for volume name"), GRID+8 },
+#undef GRID
+
+#define GRID 90
+  {NULL, 0, NULL, 0,
+   N_("Compression options:"), GRID },
+  {"auto-compress", 'a', 0, 0,
+   N_("use archive suffix to determine the compression program"), GRID+1 },
+  {"no-auto-compress", NO_AUTO_COMPRESS_OPTION, 0, 0,
+   N_("do not use use archive suffix to determine the compression program"),
+   GRID+1 },
   {"bzip2", 'j', 0, 0,
-   N_("filter the archive through bzip2"), GRID+8 },
+   N_("filter the archive through bzip2"), GRID+1 },
   {"gzip", 'z', 0, 0,
-   N_("filter the archive through gzip"), GRID+8 },
-  {"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
-  {"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
+   N_("filter the archive through gzip"), GRID+1 },
+  {"gunzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
+  {"ungzip", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
   {"compress", 'Z', 0, 0,
-   N_("filter the archive through compress"), GRID+8 },
-  {"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+8 },
-  {"use-compress-program", USE_COMPRESS_PROGRAM_OPTION, N_("PROG"), 0,
-   N_("filter through PROG (must accept -d)"), GRID+8 },
+   N_("filter the archive through compress"), GRID+1 },
+  {"uncompress", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
+  {"lzma", 'J', 0, 0,
+   N_("filter the archive through lzma"), GRID+1 },
+  {"lzop", LZOP_OPTION, 0, 0,
+   N_("filter the archive through lzop"), GRID+8 },
+  {"use-compress-program", 'I', N_("PROG"), 0,
+   N_("filter through PROG (must accept -d)"), GRID+1 },
 #undef GRID
-
-#define GRID 90
+  
+#define GRID 100
   {NULL, 0, NULL, 0,
    N_("Local file selection:"), GRID },
 
@@ -590,6 +624,8 @@ static struct argp_option options[] = {
    N_("get names to extract or create from FILE"), GRID+1 },
   {"null", NULL_OPTION, 0, 0,
    N_("-T reads null-terminated names, disable -C"), GRID+1 },
+  {"no-null", NO_NULL_OPTION, 0, 0,
+   N_("disable the effect of the previous --null option"), GRID+1 },
   {"unquote", UNQUOTE_OPTION, 0, 0,
    N_("unquote filenames read with -T (default)"), GRID+1 },
   {"no-unquote", NO_UNQUOTE_OPTION, 0, 0,
@@ -599,7 +635,22 @@ static struct argp_option options[] = {
   {"exclude-from", 'X', N_("FILE"), 0,
    N_("exclude patterns listed in FILE"), GRID+1 },
   {"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0,
-   N_("exclude directories containing a cache tag"), GRID+1 },
+   N_("exclude contents of directories containing CACHEDIR.TAG, "
+      "except for the tag file itself"), GRID+1 },
+  {"exclude-caches-under", EXCLUDE_CACHES_UNDER_OPTION, 0, 0,
+   N_("exclude everything under directories containing CACHEDIR.TAG"),
+   GRID+1 },
+  {"exclude-caches-all", EXCLUDE_CACHES_ALL_OPTION, 0, 0,
+   N_("exclude directories containing CACHEDIR.TAG"), GRID+1 },
+  {"exclude-tag", EXCLUDE_TAG_OPTION, N_("FILE"), 0,
+   N_("exclude contents of directories containing FILE, except"
+      " for FILE itself"), GRID+1 },
+  {"exclude-tag-under", EXCLUDE_TAG_UNDER_OPTION, N_("FILE"), 0,
+   N_("exclude everything under directories containing FILE"), GRID+1 },
+  {"exclude-tag-all", EXCLUDE_TAG_ALL_OPTION, N_("FILE"), 0,
+   N_("exclude directories containing FILE"), GRID+1 },
+  {"exclude-vcs", EXCLUDE_VCS_OPTION, NULL, 0,
+   N_("exclude version control system directories"), GRID+1 },
   {"no-recursion", NO_RECURSION_OPTION, 0, 0,
    N_("avoid descending automatically in directories"), GRID+1 },
   {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
@@ -610,6 +661,8 @@ static struct argp_option options[] = {
    N_("don't strip leading `/'s from file names"), GRID+1 },
   {"dereference", 'h', 0, 0,
    N_("follow symlinks; archive and dump the files they point to"), GRID+1 },
+  {"hard-dereference", HARD_DEREFERENCE_OPTION, 0, 0,
+   N_("follow hard links; archive and dump the files they refer to"), GRID+1 },
   {"starting-file", 'K', N_("MEMBER-NAME"), 0,
    N_("begin at member MEMBER-NAME in the archive"), GRID+1 },
   {"newer", 'N', N_("DATE-OR-FILE"), 0,
@@ -623,7 +676,7 @@ static struct argp_option options[] = {
    N_("backup before removal, override usual suffix ('~' unless overridden by environment variable SIMPLE_BACKUP_SUFFIX)"), GRID+1 },
 #undef GRID
 
-#define GRID 92
+#define GRID 110
   {NULL, 0, NULL, 0,
    N_("File name transformations:"), GRID },
   {"strip-components", STRIP_COMPONENTS_OPTION, N_("NUMBER"), 0,
@@ -631,9 +684,10 @@ static struct argp_option options[] = {
    GRID+1 },
   {"transform", TRANSFORM_OPTION, N_("EXPRESSION"), 0,
    N_("use sed replace EXPRESSION to transform file names"), GRID+1 },
+  {"xform", 0, 0, OPTION_ALIAS, NULL, GRID+1 },
 #undef GRID
 
-#define GRID 95  
+#define GRID 120
   {NULL, 0, NULL, 0,
    N_("File name matching options (affect both exclude and include patterns):"),
    GRID },
@@ -654,16 +708,19 @@ static struct argp_option options[] = {
   {"wildcards-match-slash", WILDCARDS_MATCH_SLASH_OPTION, 0, 0,
    N_("wildcards match `/' (default for exclusion)"), GRID+1 },
 #undef GRID
-  
-#define GRID 100
+
+#define GRID 130
   {NULL, 0, NULL, 0,
    N_("Informative output:"), GRID },
 
   {"verbose", 'v', 0, 0,
    N_("verbosely list files processed"), GRID+1 },
-  {"checkpoint", CHECKPOINT_OPTION, N_("[.]NUMBER"), OPTION_ARG_OPTIONAL,
+  {"checkpoint", CHECKPOINT_OPTION, N_("NUMBER"), OPTION_ARG_OPTIONAL,
    N_("display progress messages every NUMBERth record (default 10)"),
    GRID+1 },
+  {"checkpoint-action", CHECKPOINT_ACTION_OPTION, N_("ACTION"), 0,
+   N_("execute ACTION on each checkpoint"),
+   GRID+1 },
   {"check-links", 'l', 0, 0,
    N_("print a message if not all links are dumped"), GRID+1 },
   {"totals", TOTALS_OPTION, N_("SIGNAL"), OPTION_ARG_OPTIONAL,
@@ -696,7 +753,7 @@ static struct argp_option options[] = {
    N_("disable quoting for characters from STRING"), GRID+1 },
 #undef GRID
 
-#define GRID 110
+#define GRID 140
   {NULL, 0, NULL, 0,
    N_("Compatibility options:"), GRID },
 
@@ -704,7 +761,7 @@ static struct argp_option options[] = {
    N_("when creating, same as --old-archive; when extracting, same as --no-same-owner"), GRID+1 },
 #undef GRID
 
-#define GRID 120
+#define GRID 150
   {NULL, 0, NULL, 0,
    N_("Other options:"), GRID },
 
@@ -761,8 +818,11 @@ struct tar_args        /* Variables used during option parsing */
   char const *backup_suffix_string;   /* --suffix option argument */
   char const *version_control_string; /* --backup option argument */
   bool input_files;                /* True if some input files where given */
+  int compress_autodetect;         /* True if compression autodetection should
+                                     be attempted when creating archives */
 };
 
+\f
 #define MAKE_EXCL_OPTIONS(args) \
  ((((args)->wildcards != disable_wildcards) ? EXCLUDE_WILDCARDS : 0) \
   | (args)->matching_flags \
@@ -774,7 +834,48 @@ struct tar_args        /* Variables used during option parsing */
   | (args)->matching_flags \
   | recursion_option)
 
-#ifdef REMOTE_SHELL                                                       
+void
+exclude_vcs_files ()
+{
+  int i;
+  static char *vcs_file[] = {
+    /* CVS: */
+    "CVS",
+    ".cvsignore",
+    /* RCS: */
+    "RCS",
+    /* SCCS: */
+    "SCCS",
+    /* SVN: */
+    ".svn",
+    /* git: */
+    ".git",
+    ".gitignore",
+    /* Arch: */
+    ".arch-ids",
+    "{arch}",
+    "=RELEASE-ID",
+    "=meta-update",
+    "=update",
+    /* Bazaar */
+    ".bzr",
+    ".bzrignore",
+    ".bzrtags",
+    /* Mercurial */
+    ".hg",
+    ".hgignore",
+    ".hgtags",
+    /* darcs */
+    "_darcs",
+    NULL
+  };
+
+  for (i = 0; vcs_file[i]; i++)
+    add_exclude (excluded, vcs_file[i], 0);
+}
+
+\f
+#ifdef REMOTE_SHELL
 # define DECL_SHOW_DEFAULT_SETTINGS(stream, printer)                      \
 {                                                                         \
   printer (stream,                                                        \
@@ -802,7 +903,7 @@ struct tar_args        /* Variables used during option parsing */
 static void
 show_default_settings (FILE *fp)
      DECL_SHOW_DEFAULT_SETTINGS(fp, fprintf)
-     
+
 static void
 show_default_settings_fs (argp_fmtstream_t fs)
      DECL_SHOW_DEFAULT_SETTINGS(fs, argp_fmtstream_printf)
@@ -872,7 +973,7 @@ set_stat_signal (const char *name)
     { "QUIT", SIGQUIT }
   };
   struct sigtab *p;
-  
+
   for (p = sigtab; p < sigtab + sizeof (sigtab) / sizeof (sigtab[0]); p++)
     if (strcmp (p->name, name) == 0)
       {
@@ -946,35 +1047,41 @@ report_textual_dates (struct tar_args *args)
 \f
 static volatile int _argp_hang;
 
+/* Either NL or NUL, as decided by the --null option.  */
+static char filename_terminator;
+
 enum read_file_list_state  /* Result of reading file name from the list file */
   {
     file_list_success,     /* OK, name read successfully */
     file_list_end,         /* End of list file */
-    file_list_zero         /* Zero separator encountered where it should not */
+    file_list_zero,        /* Zero separator encountered where it should not */
+    file_list_skip         /* Empty (zero-length) entry encountered, skip it */
   };
 
-/* Read from FP a sequence of characters up to FILENAME_TERMINATOR and put them
+/* Read from FP a sequence of characters up to TERM and put them
    into STK.
  */
 static enum read_file_list_state
-read_name_from_file (FILE *fp, struct obstack *stk)
+read_name_from_file (FILE *fp, struct obstack *stk, int term)
 {
   int c;
   size_t counter = 0;
 
-  for (c = getc (fp); c != EOF && c != filename_terminator; c = getc (fp))
+  for (c = getc (fp); c != EOF && c != term; c = getc (fp))
     {
       if (c == 0)
        {
          /* We have read a zero separator. The file possibly is
             zero-separated */
-         /* FATAL_ERROR((0, 0, N_("file name contains null character"))); */
          return file_list_zero;
        }
       obstack_1grow (stk, c);
       counter++;
     }
 
+  if (counter == 0 && c != EOF)
+    return file_list_skip;
+
   obstack_1grow (stk, 0);
 
   return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
@@ -1041,7 +1148,8 @@ update_argv (const char *filename, struct argp_state *state)
   size_t new_argc;
   bool is_stdin = false;
   enum read_file_list_state read_state;
-
+  int term = filename_terminator;
+  
   if (!strcmp (filename, "-"))
     {
       is_stdin = true;
@@ -1055,31 +1163,43 @@ update_argv (const char *filename, struct argp_state *state)
        open_fatal (filename);
     }
 
-  while ((read_state = read_name_from_file (fp, &argv_stk)) == file_list_success)
-    count++;
-
-  if (read_state == file_list_zero)
+  while ((read_state = read_name_from_file (fp, &argv_stk, term))
+        != file_list_end)
     {
-      size_t size;
+      switch (read_state)
+       {
+       case file_list_success:
+         count++;
+         break;
 
-      WARN ((0, 0, N_("%s: file name read contains nul character"),
-            quotearg_colon (filename)));
+       case file_list_end: /* won't happen, just to pacify gcc */
+         break;
 
-      /* Prepare new stack contents */
-      size = obstack_object_size (&argv_stk);
-      p = obstack_finish (&argv_stk);
-      for (; size > 0; size--, p++)
-       if (*p)
-         obstack_1grow (&argv_stk, *p);
-        else
-         obstack_1grow (&argv_stk, '\n');
-      obstack_1grow (&argv_stk, 0);
-      count = 1;
-
-      /* Read rest of files using new filename terminator */
-      filename_terminator = 0;
-      while (read_name_from_file (fp, &argv_stk) == file_list_success)
-       count++;
+       case file_list_zero:
+         {
+           size_t size;
+
+           WARN ((0, 0, N_("%s: file name read contains nul character"),
+                  quotearg_colon (filename)));
+
+           /* Prepare new stack contents */
+           size = obstack_object_size (&argv_stk);
+           p = obstack_finish (&argv_stk);
+           for (; size > 0; size--, p++)
+             if (*p)
+               obstack_1grow (&argv_stk, *p);
+             else
+               obstack_1grow (&argv_stk, '\n');
+           obstack_1grow (&argv_stk, 0);
+           count = 1;
+           /* Read rest of files using new filename terminator */
+           term = 0;
+           break;
+         }
+
+       case file_list_skip:
+         break;
+       }
     }
 
   if (!is_stdin)
@@ -1090,7 +1210,7 @@ update_argv (const char *filename, struct argp_state *state)
 
   start = obstack_finish (&argv_stk);
 
-  if (filename_terminator == 0)
+  if (term == 0)
     for (p = start; *p; p += strlen (p) + 1)
       if (p[0] == '-')
        count++;
@@ -1106,7 +1226,7 @@ update_argv (const char *filename, struct argp_state *state)
 
   for (i = state->next, p = start; *p; p += strlen (p) + 1, i++)
     {
-      if (filename_terminator == 0 && p[0] == '-')
+      if (term == 0 && p[0] == '-')
        state->argv[i++] = "--add-file";
       state->argv[i] = p;
     }
@@ -1122,11 +1242,11 @@ tar_help (struct argp_state *state)
                   ARGP_HELP_STD_HELP & ~ARGP_HELP_BUG_ADDR);
   /* FIXME: use struct uparams.rmargin (from argp-help.c) instead of 79 */
   fs = argp_make_fmtstream (state->out_stream, 0, 79, 0);
-  
+
   argp_fmtstream_printf (fs, "\n%s\n\n",
                       _("Valid arguments for --quoting-style options are:"));
   tar_list_quoting_styles (fs, "  ");
-       
+
   argp_fmtstream_puts (fs, _("\n*This* tar defaults to:\n"));
   show_default_settings_fs (fs);
   argp_fmtstream_putc (fs, '\n');
@@ -1142,16 +1262,24 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
   switch (key)
     {
-      case ARGP_KEY_ARG:
-       /* File name or non-parsed option, because of ARGP_IN_ORDER */
-       name_add_name (arg, MAKE_INCL_OPTIONS (args));
-       args->input_files = true;
-       break;
+    case ARGP_KEY_ARG:
+      /* File name or non-parsed option, because of ARGP_IN_ORDER */
+      name_add_name (arg, MAKE_INCL_OPTIONS (args));
+      args->input_files = true;
+      break;
 
     case 'A':
       set_subcommand_option (CAT_SUBCOMMAND);
       break;
 
+    case 'a':
+      args->compress_autodetect = true;
+      break;
+
+    case NO_AUTO_COMPRESS_OPTION:
+      args->compress_autodetect = false;
+      break;
+      
     case 'b':
       {
        uintmax_t u;
@@ -1222,6 +1350,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       dereference_option = true;
       break;
 
+    case HARD_DEREFERENCE_OPTION:
+      hard_dereference_option = true;
+      break;
+      
     case 'i':
       /* Ignore zero blocks (eofs).  This can't be the default,
         because Unix tar writes two blocks of zeros, then pads out
@@ -1230,16 +1362,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
       ignore_zeros_option = true;
       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;
 
+    case 'J':
+      set_use_compress_program_option ("lzma");
+      break;
+      
     case 'k':
       /* Don't replace existing files.  */
       old_files_option = KEEP_OLD_FILES;
@@ -1271,6 +1401,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       }
       break;
 
+    case LZOP_OPTION:
+      set_use_compress_program_option ("lzop");
+      break;
+      
     case 'm':
       touch_option = true;
       break;
@@ -1286,7 +1420,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       get_date_or_file (args, "--mtime", arg, &mtime_option);
       set_mtime_option = true;
       break;
-      
+
     case 'n':
       seekable_archive = true;
       break;
@@ -1359,7 +1493,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
          }
       }
       break;
-           
+
     case 't':
       set_subcommand_option (LIST_SUBCOMMAND);
       verbose_option++;
@@ -1444,6 +1578,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
                        " on this platform")));
       break;
 
+    case CHECK_DEVICE_OPTION:
+      check_device_option = true;
+      break;
+      
+    case NO_CHECK_DEVICE_OPTION:
+      check_device_option = false;
+      break;
+      
     case CHECKPOINT_OPTION:
       if (arg)
        {
@@ -1451,7 +1593,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
          if (*arg == '.')
            {
-             checkpoint_style = checkpoint_dot;
+             checkpoint_compile_action (".");
              arg++;
            }
          checkpoint_option = strtoul (arg, &p, 0);
@@ -1460,9 +1602,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
                          _("--checkpoint value is not an integer")));
        }
       else
-       checkpoint_option = 10;
+       checkpoint_option = DEFAULT_CHECKPOINT;
       break;
 
+    case CHECKPOINT_ACTION_OPTION:
+      checkpoint_compile_action (arg);
+      break;
+      
     case BACKUP_OPTION:
       backup_option = true;
       if (arg)
@@ -1486,9 +1632,36 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case EXCLUDE_CACHES_OPTION:
-      exclude_caches_option = true;
+      add_exclusion_tag ("CACHEDIR.TAG", exclusion_tag_contents,
+                        cachedir_file_p);
+      break;
+
+    case EXCLUDE_CACHES_UNDER_OPTION:
+      add_exclusion_tag ("CACHEDIR.TAG", exclusion_tag_under,
+                        cachedir_file_p);
+      break;
+
+    case EXCLUDE_CACHES_ALL_OPTION:
+      add_exclusion_tag ("CACHEDIR.TAG", exclusion_tag_all,
+                        cachedir_file_p);
+      break;
+
+    case EXCLUDE_TAG_OPTION:
+      add_exclusion_tag (arg, exclusion_tag_contents, NULL);
+      break;
+
+    case EXCLUDE_TAG_UNDER_OPTION:
+      add_exclusion_tag (arg, exclusion_tag_under, NULL);
+      break;
+
+    case EXCLUDE_TAG_ALL_OPTION:
+      add_exclusion_tag (arg, exclusion_tag_all, NULL);
       break;
 
+    case EXCLUDE_VCS_OPTION:
+      exclude_vcs_files ();
+      break;
+      
     case FORCE_LOCAL_OPTION:
       force_local_option = true;
       break;
@@ -1573,6 +1746,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       filename_terminator = '\0';
       break;
 
+    case NO_NULL_OPTION:
+      filename_terminator = '\n';
+      break;
+
     case NUMERIC_OWNER_OPTION:
       numeric_owner_option = true;
       break;
@@ -1635,6 +1812,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
       /* FIXME: What it is good for? */
       same_permissions_option = true;
       same_order_option = true;
+      WARN ((0, 0, _("The --preserve option is deprecated, "
+                    "use --preserve-permissions --preserve-order instead")));
       break;
 
     case RECORD_SIZE_OPTION:
@@ -1717,8 +1896,8 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case TRANSFORM_OPTION:
       set_transform_expr (arg);
       break;
-      
-    case USE_COMPRESS_PROGRAM_OPTION:
+
+    case 'I':
       set_use_compress_program_option (arg);
       break;
 
@@ -1875,23 +2054,23 @@ usage (int status)
 /* Parse the options for tar.  */
 
 static struct argp_option *
-find_argp_option (struct argp_option *options, int letter)
+find_argp_option (struct argp_option *o, int letter)
 {
   for (;
-       !(options->name == NULL
-        && options->key == 0
-        && options->arg == 0
-        && options->flags == 0
-        && options->doc == NULL); options++)
-    if (options->key == letter)
-      return options;
+       !(o->name == NULL
+        && o->key == 0
+        && o->arg == 0
+        && o->flags == 0
+        && o->doc == NULL); o++)
+    if (o->key == letter)
+      return o;
   return NULL;
 }
 
 static void
 decode_options (int argc, char **argv)
 {
-  int index;
+  int idx;
   struct tar_args args;
 
   /* Set some default option values.  */
@@ -1904,6 +2083,7 @@ decode_options (int argc, char **argv)
   args.backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
   args.version_control_string = 0;
   args.input_files = false;
+  args.compress_autodetect = false;
   
   subcommand_option = UNKNOWN_SUBCOMMAND;
   archive_format = DEFAULT_FORMAT;
@@ -1916,10 +2096,12 @@ decode_options (int argc, char **argv)
   unquote_option = true;
   tar_sparse_major = 1;
   tar_sparse_minor = 0;
-  
+
   owner_option = -1;
   group_option = -1;
 
+  check_device_option = true;
+  
   /* Convert old-style tar call by exploding option element and rearranging
      options accordingly.  */
 
@@ -1982,7 +2164,7 @@ decode_options (int argc, char **argv)
   prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
 
   if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_HELP,
-                 &index, &args))
+                 &idx, &args))
     exit (TAREXIT_FAILURE);
 
 
@@ -2010,16 +2192,16 @@ decode_options (int argc, char **argv)
     }
 
   /* Handle operands after any "--" argument.  */
-  for (; index < argc; index++)
+  for (; idx < argc; idx++)
     {
-      name_add_name (argv[index], MAKE_INCL_OPTIONS (&args));
+      name_add_name (argv[idx], MAKE_INCL_OPTIONS (&args));
       args.input_files = true;
     }
 
   /* Warn about implicit use of the wildcards in command line arguments.
      See TODO */
   warn_regex_usage = args.wildcards == default_wildcards;
-  
+
   /* Derive option values and check option consistency.  */
 
   if (archive_format == DEFAULT_FORMAT)
@@ -2038,13 +2220,6 @@ decode_options (int argc, char **argv)
                   | FORMAT_MASK (GNU_FORMAT)
                   | FORMAT_MASK (POSIX_FORMAT));
 
-  if (multi_volume_option
-      && archive_format == POSIX_FORMAT
-      && subcommand_option == CREATE_SUBCOMMAND
-      && !tape_length_option)
-    USAGE_ERROR ((0, 0,
-                 _("creating multi-volume archives in posix format requires using --tape-length (-L) option")));
-
   if (occurrence_option)
     {
       if (!args.input_files)
@@ -2163,6 +2338,13 @@ decode_options (int argc, char **argv)
   else if (utc_option)
     verbose_option = 2;
 
+  if (tape_length_option && tape_length_option < record_size)
+    USAGE_ERROR ((0, 0, _("Volume length cannot be less than record size")));
+
+  if (same_order_option && listed_incremental_option)
+    USAGE_ERROR ((0, 0, _("--preserve-order is not compatible with "
+                         "--listed-incremental")));
+  
   /* Forbid using -c with no input files whatsoever.  Check that `-f -',
      explicit or implied, is used correctly.  */
 
@@ -2172,6 +2354,10 @@ decode_options (int argc, char **argv)
       if (!args.input_files && !files_from_option)
        USAGE_ERROR ((0, 0,
                      _("Cowardly refusing to create an empty archive")));
+      if (args.compress_autodetect && archive_names
+         && strcmp (archive_name_array[0], "-"))
+       set_comression_program_by_suffix (archive_name_array[0],
+                                         use_compress_program_option);
       break;
 
     case EXTRACT_SUBCOMMAND:
@@ -2198,6 +2384,16 @@ decode_options (int argc, char **argv)
       break;
     }
 
+  /* Initialize stdlis */
+  if (index_file_name)
+    {
+      stdlis = fopen (index_file_name, "w");
+      if (! stdlis)
+       open_error (index_file_name);
+    }
+  else
+    stdlis = to_stdout_option ? stderr : stdout;
+
   archive_name_cursor = archive_name_array;
 
   /* Prepare for generating backup names.  */
@@ -2214,6 +2410,8 @@ decode_options (int argc, char **argv)
        backup_option = false;
     }
 
+  checkpoint_finish_compile ();
+  
   if (verbose_option)
     report_textual_dates (&args);
 }
@@ -2240,9 +2438,6 @@ main (int argc, char **argv)
   /* Make sure we have first three descriptors available */
   stdopen ();
 
-  /* Close all inherited open descriptors, except for the first three */
-  closeopen ();
-  
   /* Pre-allocate a few structures.  */
 
   allocated_archive_names = 10;
@@ -2260,6 +2455,7 @@ main (int argc, char **argv)
   /* Decode options.  */
 
   decode_options (argc, argv);
+
   name_init ();
 
   /* Main command execution.  */
@@ -2321,13 +2517,14 @@ main (int argc, char **argv)
   free (archive_name_array);
   name_term ();
 
+  if (exit_status == TAREXIT_FAILURE)
+    error (0, 0, _("Exiting with failure status due to previous errors"));
+
   if (stdlis == stdout)
     close_stdout ();
-
-  if (exit_status == TAREXIT_FAILURE)
-    error (0, 0, _("Error exit delayed from previous errors"));
-  if (ferror (stderr) || fclose (stderr) != 0)
+  else if (ferror (stderr) || fclose (stderr) != 0)
     exit_status = TAREXIT_FAILURE;
+
   return exit_status;
 }
 
@@ -2347,6 +2544,7 @@ tar_stat_destroy (struct tar_stat_info *st)
   free (st->gname);
   free (st->sparse_map);
   free (st->dumpdir);
+  xheader_destroy (&st->xhdr);
   memset (st, 0, sizeof (*st));
 }
 
This page took 0.043246 seconds and 4 git commands to generate.