From b9588c472262be876400e0804c529c57102d6f0d Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Tue, 23 Jan 2007 10:25:06 +0000 Subject: [PATCH] (struct exclude_tag): rename to exclusion_tag (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 | 215 +++++++++++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 94 deletions(-) diff --git a/src/create.c b/src/create.c index 23e9efd..4ff3054 100644 --- a/src/create.c +++ b/src/create.c @@ -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; } @@ -1043,53 +1087,13 @@ dump_regular_file (int fd, struct tar_stat_info *st) } -/* 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. */ -- 2.44.0