]> Dogcows Code - chaz/tar/commitdiff
(struct exclude_tag): rename to exclusion_tag
authorSergey Poznyakoff <gray@gnu.org.ua>
Tue, 23 Jan 2007 10:25:06 +0000 (10:25 +0000)
committerSergey Poznyakoff <gray@gnu.org.ua>
Tue, 23 Jan 2007 10:25:06 +0000 (10:25 +0000)
(check_exclusion_tags): New function
(cachedir_file_p): New function (from check_cache_directory)
(dump_dir0,dump_file0): Use check_exclusion_tags

src/create.c

index 23e9efdbd302f8537c872d4561b69280ae04fa54..4ff30542ba8fb27e0d7c268ce09c0f8163165f40 100644 (file)
@@ -1,7 +1,7 @@
 /* Create a tar archive.
 
    Copyright (C) 1985, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
-   2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    Written by John Gilmore, on 1985-08-25.
 
@@ -34,36 +34,53 @@ struct link
     char name[1];
   };
 
-struct exclude_tag
+struct exclusion_tag
 {
   const char *name;
   size_t length;
-  struct exclude_tag *next;
+  enum exclusion_tag_type type;
+  bool (*predicate) (const char *name);
+  struct exclusion_tag *next;
 };
 
-static struct exclude_tag *exclude_tags;
+static struct exclusion_tag *exclusion_tags;
 
 void
-add_exclude_tag (const char *name)
+add_exclusion_tag (const char *name, enum exclusion_tag_type type,
+                  bool (*predicate) (const char *name))
 {
-  struct exclude_tag *tag = xmalloc (sizeof tag[0]);
-  tag->next = exclude_tags;
+  struct exclusion_tag *tag = xmalloc (sizeof tag[0]);
+  tag->next = exclusion_tags;
   tag->name = name;
+  tag->type = type;
+  tag->predicate = predicate;
   tag->length = strlen (name);
-  exclude_tags = tag;
+  exclusion_tags = tag;
 }
 
-static bool
-check_exclude_tags (char *dirname)
+static void
+exclusion_tag_warning (const char *dirname, const char *tagname,
+                      const char *message)
+{
+  if (verbose_option)
+    WARN ((0, 0,
+          _("%s: contains a cache directory tag %s; %s"),
+          quotearg_colon (dirname),
+          quotearg_n (1, tagname),
+          message));
+}
+
+static enum exclusion_tag_type 
+check_exclusion_tags (char *dirname, const char **tag_file_name)
 {
   static char *tagname;
   static size_t tagsize;
-  struct exclude_tag *tag;
+  struct exclusion_tag *tag;
   size_t dlen = strlen (dirname);
   char *nptr = NULL;
   char *ret = NULL;
   
-  for (tag = exclude_tags; tag; tag = tag->next)
+  for (tag = exclusion_tags; tag; tag = tag->next)
     {
       size_t size = dlen + tag->length + 1;
       if (size > tagsize)
@@ -78,18 +95,45 @@ check_exclude_tags (char *dirname)
          nptr = tagname + dlen;
        }
       strcpy (nptr, tag->name);
-      if (access (tagname, F_OK) == 0)
+      if (access (tagname, F_OK) == 0
+         && (!tag->predicate || tag->predicate (tagname)))
        {
-         if (verbose_option)
-           WARN ((0, 0,
-                  _("%s: contains a cache directory tag %s; not dumped"),
-                  quotearg_colon (dirname),
-                  quotearg_n (1, tag->name)));
-         return true;
+         if (tag_file_name)
+           *tag_file_name = tag->name;
+         return tag->type;
        }
     }
 
-  return false;
+  return exclusion_tag_none;
+}
+
+/* Exclusion predicate to test if the named file (usually "CACHEDIR.TAG")
+   contains a valid header, as described at:
+       http://www.brynosaurus.com/cachedir
+   Applications can write this file into directories they create
+   for use as caches containing purely regenerable, non-precious data,
+   allowing us to avoid archiving them if --exclude-caches is specified. */
+
+#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
+#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
+
+bool
+cachedir_file_p (const char *name)
+{
+  bool tag_present = false;
+  int fd = open (name, O_RDONLY);
+  if (fd >= 0)
+    {
+      static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
+
+      if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
+         == CACHEDIR_SIGNATURE_SIZE
+         && memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
+       tag_present = true;
+
+      close (fd);
+    }
+  return tag_present;
 }
 
 \f
@@ -1043,53 +1087,13 @@ dump_regular_file (int fd, struct tar_stat_info *st)
 }
 
 \f
-/* Look in directory DIRNAME for a cache directory tag file
-   with the magic name "CACHEDIR.TAG" and a standard header,
-   as described at:
-       http://www.brynosaurus.com/cachedir
-   Applications can write this file into directories they create
-   for use as caches containing purely regenerable, non-precious data,
-   allowing us to avoid archiving them if --exclude-caches is specified. */
-
-#define CACHEDIR_SIGNATURE "Signature: 8a477f597d28d172789f06886806bc55"
-#define CACHEDIR_SIGNATURE_SIZE (sizeof CACHEDIR_SIGNATURE - 1)
-
-static bool
-check_cache_directory (char *dirname)
-{
-  static char tagname[] = "CACHEDIR.TAG";
-  char *tagpath;
-  int fd;
-  bool tag_present = false;
-
-  tagpath = xmalloc (strlen (dirname) + strlen (tagname) + 1);
-  strcpy (tagpath, dirname);
-  strcat (tagpath, tagname);
-
-  fd = open (tagpath, O_RDONLY);
-  if (fd >= 0)
-    {
-      static char tagbuf[CACHEDIR_SIGNATURE_SIZE];
-
-      if (read (fd, tagbuf, CACHEDIR_SIGNATURE_SIZE)
-         == CACHEDIR_SIGNATURE_SIZE
-         && memcmp (tagbuf, CACHEDIR_SIGNATURE, CACHEDIR_SIGNATURE_SIZE) == 0)
-       tag_present = true;
-
-      close (fd);
-    }
-
-  free (tagpath);
-
-  return tag_present;
-}
-
 static void
 dump_dir0 (char *directory,
           struct tar_stat_info *st, int top_level, dev_t parent_device)
 {
   dev_t our_device = st->stat.st_dev;
-
+  const char *tag_file_name;
+  
   if (!is_avoided_name (st->orig_file_name))
     {
       union block *blk = NULL;
@@ -1171,34 +1175,61 @@ dump_dir0 (char *directory,
        WARN ((0, 0,
               _("%s: file is on a different filesystem; not dumped"),
               quotearg_colon (st->orig_file_name)));
-      return;
     }
-  
-  {
-    char const *entry;
-    size_t entry_len;
-    char *name_buf = xstrdup (st->orig_file_name);
-    size_t name_size = strlen (name_buf);
-    size_t name_len = name_size;
+  else
+    {
+      char *name_buf;
+      size_t name_size;
+      
+      switch (check_exclusion_tags (st->orig_file_name, &tag_file_name))
+       {
+       case exclusion_tag_none:
+       case exclusion_tag_all:
+         {
+           char const *entry;
+           size_t entry_len;
+           size_t name_len;
 
-    /* Now output all the files in the directory.  */
-    /* FIXME: Should speed this up by cd-ing into the dir.  */
+           name_buf = xstrdup (st->orig_file_name);
+           name_size = name_len = strlen (name_buf);
 
-    for (entry = directory; (entry_len = strlen (entry)) != 0;
-        entry += entry_len + 1)
-      {
-       if (name_size < name_len + entry_len)
-         {
-           name_size = name_len + entry_len;
-           name_buf = xrealloc (name_buf, name_size + 1);
+           /* Now output all the files in the directory.  */
+           /* FIXME: Should speed this up by cd-ing into the dir.  */
+
+           for (entry = directory; (entry_len = strlen (entry)) != 0;
+                entry += entry_len + 1)
+             {
+               if (name_size < name_len + entry_len)
+                 {
+                   name_size = name_len + entry_len;
+                   name_buf = xrealloc (name_buf, name_size + 1);
+                 }
+               strcpy (name_buf + name_len, entry);
+               if (!excluded_name (name_buf))
+                 dump_file (name_buf, 0, our_device);
+             }
+           
+           free (name_buf);
          }
-       strcpy (name_buf + name_len, entry);
-       if (!excluded_name (name_buf))
+         break;
+
+       case exclusion_tag_contents:
+         exclusion_tag_warning (st->orig_file_name, tag_file_name,
+                                _("contents not dumped"));
+         name_size = strlen (st->orig_file_name) + strlen (tag_file_name) + 1;
+         name_buf = xmalloc (name_size);
+         strcpy (name_buf, st->orig_file_name);
+         strcat (name_buf, tag_file_name);
          dump_file (name_buf, 0, our_device);
-      }
-
-    free (name_buf);
-  }
+         free (name_buf);
+         break;
+      
+       case exclusion_tag_under:
+         exclusion_tag_warning (st->orig_file_name, tag_file_name,
+                                _("contents not dumped"));
+         break;
+       }
+    }
 }
 
 /* Ensure exactly one trailing slash.  */
@@ -1544,22 +1575,18 @@ dump_file0 (struct tar_stat_info *st, const char *p,
 
       if (is_dir)
        {
+         const char *tag_file_name;
          ensure_slash (&st->orig_file_name);
          ensure_slash (&st->file_name);
 
-         if (exclude_caches_option
-             && check_cache_directory (st->orig_file_name))
+         if (check_exclusion_tags (st->orig_file_name, &tag_file_name)
+             == exclusion_tag_all)
            {
-             if (verbose_option)
-               WARN ((0, 0,
-                      _("%s: contains a cache directory tag; not dumped"),
-                      quotearg_colon (st->orig_file_name)));
+             exclusion_tag_warning (st->orig_file_name, tag_file_name,
+                                    _("directory not dumped"));
              return;
            }
          
-         if (check_exclude_tags (st->orig_file_name))
-           return;
-
          ok = dump_dir (fd, st, top_level, parent_device);
 
          /* dump_dir consumes FD if successful.  */
This page took 0.031058 seconds and 4 git commands to generate.