--- Begin Message ---
Subject: |
Bug#424692: --remove-files complains that directories "changed as we read it" |
Date: |
Wed, 16 May 2007 19:35:31 +0000 |
Package: tar
Version: 1.16-2
Severity: normal
When creating an archive when --remove-files is specified, tar iterates over
the files in each directory, adding them to the archive and unlinking them.
Once the directory is empty, the directory itself is removed.
However, since tar(1) itself modified the directory, the directory has
changed since tar started operating on it, and tar complains. This also
causes tar's exit status to become non-zero (i.e., failure).
Here is a simple example:
address@hidden:pts/6 ~> mkdir foo
address@hidden:pts/6 ~> echo hi >foo/bar
address@hidden:pts/6 ~> tar cf tarball.tar --remove-files foo
tar: foo: file changed as we read it
address@hidden:pts/6 ~/a> echo $?
1
Here is strace(1) output (not for the example mentioned above, but a similar
case where I first noticed this behavior):
[pid 13977] lstat64("./DEBIAN/.svn/text-base", {st_mode=S_IFDIR|0755,
st_size=1024, ...}) = 0
[pid 13977] open("./DEBIAN/.svn/text-base",
O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 4
[pid 13977] open("/proc/self/fd/4/.",
O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 5
[pid 13977] fstat64(5, {st_mode=S_IFDIR|0755, st_size=1024, ...}) = 0
[pid 13977] fcntl64(5, F_SETFD, FD_CLOEXEC) = 0
[pid 13977] close(4) = 0
[pid 13977] getdents64(5, /* 8 entries */, 32768) = 288
[pid 13977] getdents64(5, /* 0 entries */, 32768) = 0
[pid 13977] close(5) = 0
[...]
[pid 13977] lstat64("./DEBIAN/.svn/text-base/conffiles.svn-base",
{st_mode=S_IFREG|0444, st_size=261, ...}) = 0
[pid 13977] open("./DEBIAN/.svn/text-base/conffiles.svn-base",
O_RDONLY|O_LARGEFILE) = 4
[pid 13977] read(4, "/etc/iptables.d/10isis-www-serve"..., 261) = 261
[pid 13977] fstat64(4, {st_mode=S_IFREG|0444, st_size=261, ...}) = 0
[pid 13977] close(4) = 0
[pid 13977] unlink("./DEBIAN/.svn/text-base/conffiles.svn-base") = 0
[pid 13977] lstat64("./DEBIAN/.svn/text-base", {st_mode=S_IFDIR|0755,
st_size=1024, ...}) = 0
[pid 13977] write(2, "tar: ", 5tar: ) = 5
[pid 13977] write(2, "./DEBIAN/.svn/text-base: file ch"...,
51./DEBIAN/.svn/text-base: file changed as we read it) = 51
[pid 13977] write(2, "\n", 1) = 1
[pid 13977] rmdir("./DEBIAN/.svn/text-base") = 0
It's noteworthy that the tar(1) from sarge (1.14-2.3) does not exhibit this
behavior. I suspect this is because that version does not unlink empty
directories when --remove-files is specified. Rather, it leaves them for the
user to clean up. strace(1) output from the older tar is the same, except
for the write() for the error message and rmdir().
-- System Information:
Debian Release: 4.0
APT prefers stable
APT policy: (500, 'stable')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-4-686
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)
Versions of packages tar depends on:
ii libc6 2.3.6.ds1-13 GNU C Library: Shared libraries
tar recommends no packages.
-- no debconf information
--- End Message ---