On Tue, Mar 26, 2013 at 14:19:22 -0400, Nathan Stratton Treadway wrote: > I get the same behavior as you report (also using Ubuntu's GNU tar 1.26). > > However, the "aaa" file is deleted correctly if I don't use the -C > option: > > $ mkdir ext > $ cd ext > $ tar -G -vxf ../test.0.tar > aaa/ > aaa/aaa > aaa/bbb > $ tar -G -vxf ../test.1.tar > aaa/ > aaa/ccc > $ tar -G -vxf ../test.2.tar > aaa/ > tar: Deleting `aaa/aaa' > > > Interestingly, even using -C, "ccc" is deleted if I then extract > test.0.tar a second time: > > $ cd .. > $ tar -G -vxf test.0.tar -C ext/ > aaa/ > tar: Deleting `aaa/ccc' > aaa/aaa > aaa/bbb > > But I'm not sure off hand what that tells us...
Well, this turned out to be a hint that the _check_ for files which need to be deleted ignores the -C option (though the actual deletion process does not); in this case, the "ccc" file gets deleted because it still exists in the original "aaa" directory, while in the earlier test.2.tar case "aaa/aaa" did not exist. In other words, with the "-C ext" option, tar 1.26 will delete the file "aaa" only if it exists in both the "aaa/" and "ext/aaa/" directories: $ ls aaa/aaa ext/aaa/aaa ls: cannot access aaa/aaa: No such file or directory ext/aaa/aaa $ tar -G -vxf test.2.tar -C ext/ aaa/ $ touch aaa/aaa $ ls aaa/aaa ext/aaa/aaa aaa/aaa ext/aaa/aaa $ tar -G -vxf test.2.tar -C ext/ aaa/ tar: Deleting `aaa/aaa' $ ls aaa/aaa ext/aaa/aaa ls: cannot access ext/aaa/aaa: No such file or directory aaa/aaa After some debugging, I tracked the problem down to the current_dir = savedir (directory_name); line near the top of incremen.c:try_purge_directory(), since savedir() processes the passed directory by name ("aaa" in this case) without any reference to chdir_fd anywhere. Looking back over the changes committed since GNU tar 1.23, it seems pretty likely that this problem originated with commit 4bde4f39d08f000 "tar: prefer openat-style functions"; if that's true, then the problem is present in versions 1.24 and later. In any case, I see in that commit the following change was made to update.c:update_archive() - dirp = savedir (name->name); - if (!dirp) + DIR *stream; + int fd = openat (chdir_fd, name->name, + open_read_flags | O_DIRECTORY); + if (fd < 0) + open_error (name->name); + else if (! ((stream = fdopendir (fd)) + && (dirp = streamsavedir (stream)))) Perhaps a similar change would work in try_purge_directory() ? Nathan ---------------------------------------------------------------------------- Nathan Stratton Treadway - natha...@ontko.com - Mid-Atlantic region Ray Ontko & Co. - Software consulting services - http://www.ontko.com/ GPG Key: http://www.ontko.com/~nathanst/gpg_key.txt ID: 1023D/ECFB6239 Key fingerprint = 6AD8 485E 20B9 5C71 231C 0C32 15F3 ADCD ECFB 6239