diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-03-10 11:29:04 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-03-12 23:08:53 +0200 |
commit | a40e565719314287a3c4abcf5909d77bfb19797d (patch) | |
tree | e24da3c55a2ac47786a915e624ec935e23d1e337 /src/incremen.c | |
parent | 17f99bc6f1405effe6cc31a60bb7353a033c13d6 (diff) | |
download | tar-a40e565719314287a3c4abcf5909d77bfb19797d.tar.gz |
Fix interaction of various --exclude-tag options with --listed-incremental.
* src/incremen.c (procdir): Set directory->tagfile in
the exclusion_tag_contents case.
(makedumpdir): Mark all entries as ignored if directory->tagfile
is set.
Free new_dump before returning.
(maketagdumpdir): New function.
(scan_directory): If directory->children is set to
NO_CHILDREN and directory->tagfile is set, create a
dumpdir consisting of the tagfile only.
* tests/exclude08.at: New testcase.
* tests/exclude09.at: New testcase.
* tests/exclude10.at: New testcase.
* tests/exclude11.at: New testcase.
* tests/exclude12.at: New testcase.
* tests/exclude13.at: New testcase.
* tests/exclude14.at: New testcase.
* tests/exclude15.at: New testcase.
* tests/exclude16.at: New testcase.
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Include new tests.
* tests/atlocal.in (mkexcltest): New function.
* tests/chtype.at: Update keywords.
* tests/filerem01.at: Likewise.
* tests/filerem02.at: Likewise.
* tests/incremental.at: Likewise.
* tests/multiv04.at: Likewise.
Diffstat (limited to 'src/incremen.c')
-rw-r--r-- | src/incremen.c | 170 |
1 files changed, 97 insertions, 73 deletions
diff --git a/src/incremen.c b/src/incremen.c index 1d20c446..557df309 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -609,6 +609,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, exclusion_tag_warning (name_buffer, tag_file_name, _("contents not dumped")); directory->children = NO_CHILDREN; + directory->tagfile = tag_file_name; break; case exclusion_tag_under: @@ -680,15 +681,13 @@ makedumpdir (struct directory *directory, const char *dir) if (loc) { if (directory->tagfile) - *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ? - ' ' : 'I'; + *new_dump_ptr = 'I'; else *new_dump_ptr = ' '; new_dump_ptr++; } else if (directory->tagfile) - *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ? - ' ' : 'I'; + *new_dump_ptr++ = 'I'; else *new_dump_ptr++ = 'Y'; /* New entry */ @@ -699,9 +698,26 @@ makedumpdir (struct directory *directory, const char *dir) *new_dump_ptr = 0; directory->idump = directory->dump; directory->dump = dumpdir_create0 (new_dump, NULL); + free (new_dump); free (array); } +/* Create a dumpdir containing only one entry: that for the + tagfile. */ +static void +maketagdumpdir (struct directory *directory) +{ + size_t len = strlen (directory->tagfile) + 1; + char *new_dump = xmalloc (len + 2); + new_dump[0] = 'Y'; + memcpy (new_dump + 1, directory->tagfile, len); + new_dump[len + 1] = 0; + + directory->idump = directory->dump; + directory->dump = dumpdir_create0 (new_dump, NULL); + free (new_dump); +} + /* Recursively scan the directory identified by ST. */ struct directory * scan_directory (struct tar_stat_info *st) @@ -729,86 +745,94 @@ scan_directory (struct tar_stat_info *st) nbuf = namebuf_create (dir); - if (dirp && directory->children != NO_CHILDREN) + if (dirp) { - char *entry; /* directory entry being scanned */ - struct dumpdir_iter *itr; - - makedumpdir (directory, dirp); - - for (entry = dumpdir_first (directory->dump, 1, &itr); - entry; - entry = dumpdir_next (itr)) + if (directory->children != NO_CHILDREN) { - char *full_name = namebuf_name (nbuf, entry + 1); - - if (*entry == 'I') /* Ignored entry */ - *entry = 'N'; - else if (excluded_name (full_name)) - *entry = 'N'; - else - { - int fd = st->fd; - void (*diag) (char const *) = 0; - struct tar_stat_info stsub; - tar_stat_init (&stsub); + char *entry; /* directory entry being scanned */ + struct dumpdir_iter *itr; - if (fd < 0) - { - errno = - fd; - diag = open_diag; - } - else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0) - diag = stat_diag; - else if (S_ISDIR (stsub.stat.st_mode)) - { - int subfd = subfile_open (st, entry + 1, open_read_flags); - if (subfd < 0) - diag = open_diag; - else - { - stsub.fd = subfd; - if (fstat (subfd, &stsub.stat) != 0) - diag = stat_diag; - } - } + makedumpdir (directory, dirp); - if (diag) - { - file_removed_diag (full_name, false, diag); - *entry = 'N'; - } - else if (S_ISDIR (stsub.stat.st_mode)) - { - int pd_flag = 0; - if (!recursion_option) - pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN; - else if (directory->children == ALL_CHILDREN) - pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; - *entry = 'D'; - - stsub.parent = st; - procdir (full_name, &stsub, pd_flag, entry); - restore_parent_fd (&stsub); - } - else if (one_file_system_option && device != stsub.stat.st_dev) + for (entry = dumpdir_first (directory->dump, 1, &itr); + entry; + entry = dumpdir_next (itr)) + { + char *full_name = namebuf_name (nbuf, entry + 1); + + if (*entry == 'I') /* Ignored entry */ *entry = 'N'; - else if (*entry == 'Y') - /* New entry, skip further checks */; - /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ - else if (OLDER_STAT_TIME (stsub.stat, m) - && (!after_date_option - || OLDER_STAT_TIME (stsub.stat, c))) + else if (excluded_name (full_name)) *entry = 'N'; else - *entry = 'Y'; + { + int fd = st->fd; + void (*diag) (char const *) = 0; + struct tar_stat_info stsub; + tar_stat_init (&stsub); - tar_stat_destroy (&stsub); + if (fd < 0) + { + errno = - fd; + diag = open_diag; + } + else if (fstatat (fd, entry + 1, &stsub.stat, + fstatat_flags) != 0) + diag = stat_diag; + else if (S_ISDIR (stsub.stat.st_mode)) + { + int subfd = subfile_open (st, entry + 1, + open_read_flags); + if (subfd < 0) + diag = open_diag; + else + { + stsub.fd = subfd; + if (fstat (subfd, &stsub.stat) != 0) + diag = stat_diag; + } + } + + if (diag) + { + file_removed_diag (full_name, false, diag); + *entry = 'N'; + } + else if (S_ISDIR (stsub.stat.st_mode)) + { + int pd_flag = 0; + if (!recursion_option) + pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN; + else if (directory->children == ALL_CHILDREN) + pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; + *entry = 'D'; + + stsub.parent = st; + procdir (full_name, &stsub, pd_flag, entry); + restore_parent_fd (&stsub); + } + else if (one_file_system_option && + device != stsub.stat.st_dev) + *entry = 'N'; + else if (*entry == 'Y') + /* New entry, skip further checks */; + /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ + else if (OLDER_STAT_TIME (stsub.stat, m) + && (!after_date_option + || OLDER_STAT_TIME (stsub.stat, c))) + *entry = 'N'; + else + *entry = 'Y'; + + tar_stat_destroy (&stsub); + } } + free (itr); } - free (itr); + else if (directory->tagfile) + maketagdumpdir (directory); } - + namebuf_free (nbuf); free (dirp); |