1296 prevented incremental backups on individual files
from working, as reported by Andreas Schuldei
<andreas@schuldei.org>.
This is due to the condition
(0 < top_level || !incremental_option)
Removing it makes incremental backups work for individual
files as well as for directories. On the other hand, it does
not affect other functionality, as shown by the reasoning below:
To begin with, the two parts of this condition are mutually
superfluous, because
1) when top_level < 0, incremental_option == 1
so the condition yields false
2) when top_level >= 0, incremental_option == 0
so the condition yields true.
In other words, it is completely equivalent to
(!incremental_option)
Now, let's consider the effect of its removal. There are two cases:
1) when incremental_option==1
This means incremental backup in progress. In this case dump_file
is invoked only for directories or for files marked with 'Y' by
get_directory_contents. The latter are those that did not meet the
condition in incremen.c:242, which is exactly the same condition
as this at create.c:1296. So, for these files the check
(!incremental_option) is useless, since the rest of the
conditional will yield false anyway. On the other hand, if
dump_file is invoked on a directory, the conditional will yield
false due to !S_ISDIR assertion, so these will be processed as usual.
Thus, for this case the extra condition (!incremental_option) is
irrelevant, and its removal won't alter the behavior of tar,
*except* that it will enable incremental backups on individual
files, which is the wanted effect.
2) when incremental_option==0
In this case the condition yields true and its removal does not
affect the functionality.
(write_extended): Removed superfluous last argument. Use
xheader_write()
(simple_finish_header): New function.
(finish_header): Use simple_finish_header() to break recursive
dependency between this function and write_extended().
All callers changed.
(start_header): Clear devmajor and devminor fields, too.
(finish_header): New arg block_ordinal.
(init_sparsearray): Now extern. Set sp_array_size to
SPARSES_IN_OLDGNU_HEADER if it is zero.
(dump_file): Keep link table as a hash.
Do not count "file changed as we read it" as a failure.
This fixes a bug reported by Jose Pedro Oliveira.
(dump_file): Use offsetof when computing sizes for
struct hack; this avoids wasted space in some cases.
> (relativize): New function, with much of old start_header's guts.
Handle filesystem prefixes.
(start_header): Use this new function.
(init_sparsearray): Don't bother to zero out the new array; it's not needed.
(deal_with_sparse): Fix array allocation bug.
(create_archive): Don't assume '/' is the only separator.
(dump_file): Likewise.
Don't worry about leading / in symlink targets.
(gnu_list_name): Remove decl.
(struct link): Remove "next" member.
(linklist): Remove.
(start_header): Say "leading `FOO'" rather than "`FOO' prefix" for consistency
with other diagnostics.
(deal_with_sparse): Check for I/O error when closing the file.
(create_archive):
Do not allocate an array of size PATH_MAX, as PATH_MAX might be (size_t) -1.
Instead, allocate an array with the size that's needed.
(hash_link, compare_links): New functions.
(dump_file): Do not exhaust open file descriptors when descending deeply
into a directory, by using savedir rather than opendir/readdir.
Do not zero-fill the name buffer unnecessarily.
Hash the set of links already created, instead of using a linked list.
Fix some bugs in outputting sparse files which caused the sparse tables
to be incorrect.
When a file unexpectedly shrinks, output zeros rather than garbage.
Do not allocate an array of size PATH_MAX, as PATH_MAX might be (size_t) -1.
Instead, allocate an array with the size that's needed.
All callers changed.
(deal_with_sparse): Don't keep reading after read errors.
(finish_sparse_file): Just abort if there is an internal error.
Use error message functions to report errors consistently.
(dump_file): Fix typo: stat_warn and stat_error were interchanged.
Quote file names with colons if possible.
Don't restore access times on directories during incremental dumps
until after dealing with the directory.
If ignoring failed reads, count closedir errors as warnings, not errors.
Fix buffer overrun problem when dumping sparse files.
If ignoring failed reads, count read errors as warnings, not errors.
Use error message functions to report errors consistently.
If ignoring failed reads, count unknown files as warnings, not errors.
(start_header): Use `member names' to refer to archive member names, not
`archive names'. Warn about `..' in member names.
(finish_sparse_file, dump_file):
Quote arbitrary strings in diagnostics.
(finish_sparse_file, dump_file):
Don't assume that gettext preserves errno.
(dump_file): Don't use `access' to determine whether a directory is readable;
this isn't reliable if tar is setuid. Use `opendir' instead.
Check for readdir and closedir failures.
Don't dump sockets as if they were fifos; just warn and skip.
files. Instead, diagnose them a bit better.
Report that a file changed if its ctime changes; this is more
sensitive than mtime+size, and more accurate.
said should be there, but is absent. It was
probably removed between then and now.
Do not pass meaningless errno to ERROR when reporting that the
file changed as we read it.
(base_64_digits): Move to list.c.
(base_8_digits): Remove.
(to_octal): New function, with some of old contents of to_base.
(to_base): Remove.
(to_base256): New function.
(to_chars): Use base 256, not base 64, for huge values.
(mode_to_chars): Don't use two's complement in GNU format or POSIX format.
(dump_file): Interchange last two arguments. If TOP_LEVEL is negative,
it means we have an incremental dump where we don't know whether this
is a top-level call.
Use deref_stat instead of statx / stat / lstat.
Cast result of alloca.
Check for dates if 0 < top_level, not if listed_incremental_option.
Move multiple-link check after directory check.
Do not dump avoided names.
Dump hard links to symbolic names as links, not as separate symbolic links.
start_header cannot return a null pointer, so don't test for it.
Likewise for find_next_block.
(create_archive): Check for excluded names when doing incremental
pass through directory.
(dump_file): Do not dump old files explicitly given on command line
when using --listed-incremental. Do not strip ./ from front of file names.
(base_8_digits): New macro.
(MAX_VAL_WITH_DIGITS): New macro.
(to_base): Renamed from to_oct. Support base 64 too.
New parameters specifying bits per digit and digits.
Remove `type' parameter. The result is now undefined if it doesn't fit;
it's the caller's responsibility to check this.
(to_chars): Other half of old to_oct, for 64-bit support.
Mostly a new function.
(GID_NOBODY, UID_NOBODY): Don't define if the headers don't.
(gid_substitute, uid_substitute): Look up names dynamically if
GID_NOBODY and UID_NOBODY aren't defined; use -2 if all else fails.
(mode_to_chars): Renamed from mode_to_oct.
Support negative values in all the _to_chars functions.
(start_header): Use FILESYSTEM_PREFIX_LEN instead of MSDOS ifdef.
Abort if archive format is DEFAULT_FORMAT when it shouldn't be.
(dump_file): Inspect entire pathname, not just new file name
component, when deciding whether to exclude it.