summaryrefslogtreecommitdiff
path: root/src/incremen.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-03-10 11:29:04 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2013-03-12 23:08:53 +0200
commita40e565719314287a3c4abcf5909d77bfb19797d (patch)
treee24da3c55a2ac47786a915e624ec935e23d1e337 /src/incremen.c
parent17f99bc6f1405effe6cc31a60bb7353a033c13d6 (diff)
downloadtar-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.c170
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);