[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] --one-file-system and "file changed" warning for mountpoin
From: |
Sergey Poznyakoff |
Subject: |
Re: [Bug-tar] --one-file-system and "file changed" warning for mountpoint |
Date: |
Sun, 17 Dec 2017 12:14:28 +0200 |
Hi Nathan,
> Does anyone know of a reason that tar needs to perform the file-changed
> check on directories that it has skipped due to --one-file-system...?
There's no compelling reason, it's just an oversight. Please try
the attached patch.
Regards,
Sergey
PS: I'm going to release v.1.30 today. It looks a bit risky to apply
a patch of this size to about-to-be-released code, so I'm going to
postpone it until it is well tested.
>From e08d7825df0967edf5ea31fdb2a0269a3368f594 Mon Sep 17 00:00:00 2001
From: Sergey Poznyakoff <address@hidden>
Date: Sun, 17 Dec 2017 12:04:13 +0200
Subject: [PATCH] Don't do post-dumping checks on files that have been skipped.
* src/common.h (dump_status_skip): New status code.
* src/create.c (dump_dir0): Return enum dump_status.
(dump_dir): Likewise.
(dump_file0): Don't do additional checks (timestamp, etc)
if the file has been skipped.
---
src/common.h | 3 ++-
src/create.c | 63 ++++++++++++++++++++++++++++++++++--------------------------
2 files changed, 38 insertions(+), 28 deletions(-)
diff --git a/src/common.h b/src/common.h
index bbe167e..275252d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -492,7 +492,8 @@ enum dump_status
dump_status_ok,
dump_status_short,
dump_status_fail,
- dump_status_not_implemented
+ dump_status_not_implemented,
+ dump_status_skip
};
void add_exclusion_tag (const char *name, enum exclusion_tag_type type,
diff --git a/src/create.c b/src/create.c
index 35bcf5b..1537fb4 100644
--- a/src/create.c
+++ b/src/create.c
@@ -1119,9 +1119,11 @@ dump_regular_file (int fd, struct tar_stat_info *st)
/* Copy info from the directory identified by ST into the archive.
- DIRECTORY contains the directory's entries. */
+ DIRECTORY contains the directory's entries. Return dump_status_ok
+ on success, dump_status_skip if the directory was not dumped, and
+ dump_status_fail on error. */
-static void
+static enum dump_status
dump_dir0 (struct tar_stat_info *st, char const *directory)
{
bool top_level = ! st->parent;
@@ -1133,7 +1135,7 @@ dump_dir0 (struct tar_stat_info *st, char const
*directory)
blk = start_header (st);
if (!blk)
- return;
+ return dump_status_fail;
info_attach_exclist (st);
@@ -1188,11 +1190,11 @@ dump_dir0 (struct tar_stat_info *st, char const
*directory)
set_next_block_after (blk + (bufsize - 1) / BLOCKSIZE);
}
}
- return;
+ return dump_status_ok;
}
if (!recursion_option)
- return;
+ return dump_status_skip;
if (one_file_system_option
&& !top_level
@@ -1203,6 +1205,7 @@ dump_dir0 (struct tar_stat_info *st, char const
*directory)
(0, 0,
_("%s: file is on a different filesystem; not dumped"),
quotearg_colon (st->orig_file_name)));
+ return dump_status_skip;
}
else
{
@@ -1259,6 +1262,7 @@ dump_dir0 (struct tar_stat_info *st, char const
*directory)
break;
}
}
+ return dump_status_ok;
}
/* Ensure exactly one trailing slash. */
@@ -1315,24 +1319,28 @@ get_directory_entries (struct tar_stat_info *st)
return streamsavedir (st->dirstream, savedir_sort_order);
}
-/* Dump the directory ST. Return true if successful, false (emitting
- diagnostics) otherwise. Get ST's entries, recurse through its
- subdirectories, and clean up file descriptors afterwards. */
-static bool
+/* Dump the directory ST. Return dump_status_ok if successful,
+ dump_status_skip if the directory was not eligible for dumping (e.g.
+ located on another file system while --one-file-system is in effect), and
+ dump_status_fail (emitting diagnostics) on error. Get ST's entries,
+ recurse through its subdirectories, and clean up file descriptors
+ afterwards. */
+static enum dump_status
dump_dir (struct tar_stat_info *st)
{
+ enum dump_status status;
char *directory = get_directory_entries (st);
if (! directory)
{
savedir_diag (st->orig_file_name);
- return false;
+ return dump_status_fail;
}
- dump_dir0 (st, directory);
+ status = dump_dir0 (st, directory);
restore_parent_fd (st);
free (directory);
- return true;
+ return status;
}
@@ -1755,7 +1763,7 @@ dump_file0 (struct tar_stat_info *st, char const *name,
char const *p)
if (is_dir || S_ISREG (st->stat.st_mode) || S_ISCTG (st->stat.st_mode))
{
- bool ok;
+ enum dump_status status;
struct stat final_stat;
xattrs_acls_get (parentfd, name, st, 0, !is_dir);
@@ -1775,15 +1783,13 @@ dump_file0 (struct tar_stat_info *st, char const *name,
char const *p)
return;
}
- ok = dump_dir (st);
+ status = dump_dir (st);
fd = st->fd;
parentfd = top_level ? chdir_fd : parent->fd;
}
else
{
- enum dump_status status;
-
if (fd && sparse_option && ST_IS_SPARSE (st->stat))
{
status = sparse_dump_file (fd, st);
@@ -1801,40 +1807,42 @@ dump_file0 (struct tar_stat_info *st, char const *name,
char const *p)
break;
case dump_status_fail:
+ case dump_status_skip:
break;
case dump_status_not_implemented:
abort ();
}
-
- ok = status == dump_status_ok;
}
- if (ok)
+ if (status == dump_status_ok)
{
if (fd < 0)
{
errno = - fd;
- ok = false;
+ status = dump_status_fail;
}
else if (fd == 0)
{
if (parentfd < 0 && ! top_level)
{
errno = - parentfd;
- ok = false;
+ status = dump_status_fail;
}
else
- ok = fstatat (parentfd, name, &final_stat, fstatat_flags) == 0;
+ status =
+ fstatat (parentfd, name, &final_stat, fstatat_flags) == 0
+ ? dump_status_ok : dump_status_fail;
}
else
- ok = fstat (fd, &final_stat) == 0;
+ status = fstat (fd, &final_stat) == 0
+ ? dump_status_ok : dump_status_fail;
- if (! ok)
+ if (status == dump_status_fail)
file_removed_diag (p, top_level, stat_diag);
}
- if (ok)
+ if (status == dump_status_ok)
{
if ((timespec_cmp (get_stat_ctime (&final_stat), original_ctime) != 0
/* Original ctime will change if the file is a directory and
@@ -1853,8 +1861,9 @@ dump_file0 (struct tar_stat_info *st, char const *name,
char const *p)
utime_error (p);
}
- ok &= tar_stat_close (st);
- if (ok && remove_files_option)
+ if (! tar_stat_close (st))
+ status = dump_status_fail;
+ if (status == dump_status_ok && remove_files_option)
queue_deferred_unlink (p, is_dir);
return;
--
1.8.4