]> Dogcows Code - chaz/tar/blobdiff - src/tar.c
Relicense under GPLv3
[chaz/tar] / src / tar.c
index e0b8ad02bddcd221d080fe71db4707e810b74e6f..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,
-   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
 
 #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>
@@ -253,7 +254,12 @@ enum
   DELAY_DIRECTORY_RESTORE_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,
   FORCE_LOCAL_OPTION,
   GROUP_OPTION,
   HANG_OPTION,
@@ -406,7 +412,7 @@ static struct argp_option options[] = {
 
 #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 },
@@ -488,7 +494,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 },
@@ -527,7 +533,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 },
@@ -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,
-   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,
@@ -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_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
@@ -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 */
-         /* 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;
@@ -1058,31 +1080,42 @@ 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)) != 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)
@@ -1145,11 +1178,11 @@ 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);
@@ -1489,7 +1522,30 @@ 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 FORCE_LOCAL_OPTION:
@@ -2246,9 +2302,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;
@@ -2266,6 +2319,7 @@ main (int argc, char **argv)
   /* Decode options.  */
 
   decode_options (argc, argv);
+
   name_init ();
 
   /* Main command execution.  */
@@ -2332,7 +2386,7 @@ main (int argc, char **argv)
 
   if (stdlis == stdout)
     close_stdout ();
-  else if (ferror (stderr) || fclose (stderr) != 0) 
+  else if (ferror (stderr) || fclose (stderr) != 0)
     exit_status = TAREXIT_FAILURE;
 
   return exit_status;
@@ -2354,6 +2408,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.029269 seconds and 4 git commands to generate.