]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Update
[chaz/tar] / src / tar.c
index 84b89034640d2e4b4339f02ebe89c58c7d19121f..b460211d6338ef750268741bbf588ef5e641974a 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,
 /* 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
 
    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
    version.
 
    This program is distributed in the hope that it will be useful, but
 
 #include <argmatch.h>
 #include <closeout.h>
 
 #include <argmatch.h>
 #include <closeout.h>
+#include <configmake.h>
 #include <exitfail.h>
 #include <getdate.h>
 #include <exitfail.h>
 #include <getdate.h>
-#include <localedir.h>
 #include <rmt.h>
 #include <rmt.h>
+#include <rmt-command.h>
 #include <prepargs.h>
 #include <quotearg.h>
 #include <version-etc.h>
 #include <prepargs.h>
 #include <quotearg.h>
 #include <version-etc.h>
@@ -253,7 +254,12 @@ enum
   DELAY_DIRECTORY_RESTORE_OPTION,
   DELETE_OPTION,
   EXCLUDE_CACHES_OPTION,
   DELAY_DIRECTORY_RESTORE_OPTION,
   DELETE_OPTION,
   EXCLUDE_CACHES_OPTION,
+  EXCLUDE_CACHES_UNDER_OPTION,
+  EXCLUDE_CACHES_ALL_OPTION,
   EXCLUDE_OPTION,
   EXCLUDE_OPTION,
+  EXCLUDE_TAG_OPTION,
+  EXCLUDE_TAG_UNDER_OPTION,
+  EXCLUDE_TAG_ALL_OPTION,
   FORCE_LOCAL_OPTION,
   GROUP_OPTION,
   HANG_OPTION,
   FORCE_LOCAL_OPTION,
   GROUP_OPTION,
   HANG_OPTION,
@@ -320,17 +326,16 @@ enum
 
 const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
 
 const char *argp_program_version = "tar (" PACKAGE_NAME ") " VERSION;
 const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">";
-static char const doc0[] = 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\
 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\
-");
-static char const doc1[] = N_("\
-The 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\
 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\
@@ -407,7 +412,7 @@ static struct argp_option options[] = {
 
 #define GRID 30
   {NULL, 0, NULL, 0,
 
 #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 },
 
   {"verify", 'W', 0, 0,
    N_("attempt to verify the archive after writing it"), GRID+1 },
@@ -489,7 +494,7 @@ static struct argp_option options[] = {
 
 #define GRID 60
   {NULL, 0, NULL, 0,
 
 #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 },
 
   {"file", 'f', N_("ARCHIVE"), 0,
    N_("use archive file or device ARCHIVE"), GRID+1 },
@@ -528,7 +533,7 @@ static struct argp_option options[] = {
 
 #define GRID 70
   {NULL, 0, NULL, 0,
 
 #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 },
 
   {"blocking-factor", 'b', N_("BLOCKS"), 0,
    N_("BLOCKS x 512 bytes per record"), GRID+1 },
@@ -603,7 +608,20 @@ 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,
   {"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 },
   {"no-recursion", NO_RECURSION_OPTION, 0, 0,
    N_("avoid descending automatically in directories"), GRID+1 },
   {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
   {"no-recursion", NO_RECURSION_OPTION, 0, 0,
    N_("avoid descending automatically in directories"), GRID+1 },
   {"one-file-system", ONE_FILE_SYSTEM_OPTION, 0, 0,
@@ -954,7 +972,8 @@ 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_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 FILENAME_TERMINATOR and put them
@@ -972,13 +991,15 @@ read_name_from_file (FILE *fp, struct obstack *stk)
        {
          /* We have read a zero separator. The file possibly is
             zero-separated */
        {
          /* 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++;
     }
 
          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;
   obstack_1grow (stk, 0);
 
   return (counter == 0 && c == EOF) ? file_list_end : file_list_success;
@@ -1059,31 +1080,42 @@ update_argv (const char *filename, struct argp_state *state)
        open_fatal (filename);
     }
 
        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)) != 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 */
+           filename_terminator = 0;
+           break;
+         }
+
+       case file_list_skip:
+         break;
+       }
     }
 
   if (!is_stdin)
     }
 
   if (!is_stdin)
@@ -1146,11 +1178,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
 
   switch (key)
     {
 
   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);
 
     case 'A':
       set_subcommand_option (CAT_SUBCOMMAND);
@@ -1490,7 +1522,30 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case EXCLUDE_CACHES_OPTION:
       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 FORCE_LOCAL_OPTION:
       break;
 
     case FORCE_LOCAL_OPTION:
@@ -1862,27 +1917,12 @@ static struct argp argp = {
   options,
   parse_opt,
   N_("[FILE]..."),
   options,
   parse_opt,
   N_("[FILE]..."),
-  NULL,
+  doc,
   NULL,
   NULL,
   NULL
 };
 
   NULL,
   NULL,
   NULL
 };
 
-/* Initialize the argp documentation.  gettext 0.15 dislikes doc
-   strings containing '\v', so insert '\v' after translation.  */
-
-static void
-initialize_argp_doc (void)
-{
-  char const *xdoc0 = _(doc0); size_t xlen0 = strlen (xdoc0);
-  char const *xdoc1 = _(doc1); size_t xlen1 = strlen (xdoc1);
-  char *doc = xmalloc (xlen0 + 1 + xlen1 + 1);
-  memcpy (doc, xdoc0, xlen0);
-  doc[xlen0] = '\v';
-  memcpy (doc + xlen0 + 1, doc1, xlen1 + 1);;
-  argp.doc = doc;
-}
-
 void
 usage (int status)
 {
 void
 usage (int status)
 {
@@ -1939,8 +1979,6 @@ decode_options (int argc, char **argv)
   owner_option = -1;
   group_option = -1;
 
   owner_option = -1;
   group_option = -1;
 
-  initialize_argp_doc ();
-
   /* Convert old-style tar call by exploding option element and rearranging
      options accordingly.  */
 
   /* Convert old-style tar call by exploding option element and rearranging
      options accordingly.  */
 
@@ -2264,9 +2302,6 @@ main (int argc, char **argv)
   /* Make sure we have first three descriptors available */
   stdopen ();
 
   /* 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;
   /* Pre-allocate a few structures.  */
 
   allocated_archive_names = 10;
@@ -2284,6 +2319,7 @@ main (int argc, char **argv)
   /* Decode options.  */
 
   decode_options (argc, argv);
   /* Decode options.  */
 
   decode_options (argc, argv);
+
   name_init ();
 
   /* Main command execution.  */
   name_init ();
 
   /* Main command execution.  */
@@ -2345,13 +2381,14 @@ main (int argc, char **argv)
   free (archive_name_array);
   name_term ();
 
   free (archive_name_array);
   name_term ();
 
-  if (stdlis == stdout)
-    close_stdout ();
-
   if (exit_status == TAREXIT_FAILURE)
     error (0, 0, _("Error exit delayed from previous errors"));
   if (exit_status == TAREXIT_FAILURE)
     error (0, 0, _("Error exit delayed from previous errors"));
-  if (ferror (stderr) || fclose (stderr) != 0)
+
+  if (stdlis == stdout)
+    close_stdout ();
+  else if (ferror (stderr) || fclose (stderr) != 0)
     exit_status = TAREXIT_FAILURE;
     exit_status = TAREXIT_FAILURE;
+
   return exit_status;
 }
 
   return exit_status;
 }
 
@@ -2371,6 +2408,7 @@ tar_stat_destroy (struct tar_stat_info *st)
   free (st->gname);
   free (st->sparse_map);
   free (st->dumpdir);
   free (st->gname);
   free (st->sparse_map);
   free (st->dumpdir);
+  xheader_destroy (&st->xhdr);
   memset (st, 0, sizeof (*st));
 }
 
   memset (st, 0, sizeof (*st));
 }
 
This page took 0.027594 seconds and 4 git commands to generate.