From: Sergey Poznyakoff Date: Thu, 30 Nov 2006 09:40:47 +0000 (+0000) Subject: (dump_dir0): Implement --exclude-tag option X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=137ebf41fd97baa7e4f2a66e0da0bdb182ca6f7b;p=chaz%2Ftar (dump_dir0): Implement --exclude-tag option --- diff --git a/src/create.c b/src/create.c index 6eb6ad2..641603a 100644 --- a/src/create.c +++ b/src/create.c @@ -33,6 +33,65 @@ struct link size_t nlink; char name[1]; }; + +struct exclude_tag +{ + const char *name; + size_t length; + struct exclude_tag *next; +}; + +static struct exclude_tag *exclude_tags; + +void +add_exclude_tag (const char *name) +{ + struct exclude_tag *tag = xmalloc (sizeof tag[0]); + tag->next = exclude_tags; + tag->name = name; + tag->length = strlen (name); + exclude_tags = tag; +} + +static bool +check_exclude_tags (char *dirname) +{ + static char *tagname; + static size_t tagsize; + struct exclude_tag *tag; + size_t dlen = strlen (dirname); + char *nptr = NULL; + char *ret = NULL; + + for (tag = exclude_tags; tag; tag = tag->next) + { + size_t size = dlen + tag->length + 1; + if (size > tagsize) + { + tagsize = size; + tagname = xrealloc (tagname, tagsize); + } + + if (!nptr) + { + strcpy (tagname, dirname); + nptr = tagname + dlen; + } + strcpy (nptr, tag->name); + if (access (tagname, F_OK) == 0) + { + 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; + } + } + + return false; +} + /* The maximum uintmax_t value that can be represented with DIGITS digits, assuming that each digit is BITS_PER_DIGIT wide. */ @@ -983,6 +1042,7 @@ dump_regular_file (int fd, struct tar_stat_info *st) return dump_status_ok; } + /* Look in directory DIRNAME for a cache directory tag file with the magic name "CACHEDIR.TAG" and a standard header, as described at: @@ -1000,7 +1060,7 @@ check_cache_directory (char *dirname) static char tagname[] = "CACHEDIR.TAG"; char *tagpath; int fd; - int tag_present = false; + bool tag_present = false; tagpath = xmalloc (strlen (dirname) + strlen (tagname) + 1); strcpy (tagpath, dirname); @@ -1124,6 +1184,9 @@ dump_dir0 (char *directory, return; } + if (check_exclude_tags (st->orig_file_name)) + return; + { char const *entry; size_t entry_len; diff --git a/src/tar.c b/src/tar.c index 68c8801..35121ff 100644 --- a/src/tar.c +++ b/src/tar.c @@ -255,6 +255,7 @@ enum DELETE_OPTION, EXCLUDE_CACHES_OPTION, EXCLUDE_OPTION, + EXCLUDE_TAG_OPTION, FORCE_LOCAL_OPTION, GROUP_OPTION, HANG_OPTION, @@ -604,6 +605,8 @@ static struct argp_option options[] = { N_("exclude patterns listed in FILE"), GRID+1 }, {"exclude-caches", EXCLUDE_CACHES_OPTION, 0, 0, N_("exclude directories containing a cache tag"), GRID+1 }, + {"exclude-tag", EXCLUDE_TAG_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, @@ -1507,6 +1510,10 @@ parse_opt (int key, char *arg, struct argp_state *state) exclude_caches_option = true; break; + case EXCLUDE_TAG_OPTION: + add_exclude_tag (arg); + break; + case FORCE_LOCAL_OPTION: force_local_option = true; break;