]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Update
[chaz/tar] / src / tar.c
index 5b68548fde14a72cfffd0bf35115a823c775553b..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,
@@ -406,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 },
@@ -488,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 },
@@ -527,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 },
@@ -602,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,
@@ -953,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
@@ -971,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;
@@ -1058,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)
@@ -1145,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);
@@ -1489,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:
@@ -2246,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;
@@ -2266,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.  */
@@ -2327,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;
 }
 
@@ -2353,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.03059 seconds and 4 git commands to generate.