[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug-tar] GNU tar 1.28: tests 161 163 fail on !Linux
From: |
Christian Weisgerber |
Subject: |
[Bug-tar] GNU tar 1.28: tests 161 163 fail on !Linux |
Date: |
Tue, 5 Aug 2014 22:07:20 +0200 |
User-agent: |
Mutt/1.5.23 (2014-03-12) |
On both FreeBSD and OpenBSD, these tests in GNU tar 1.28 fail:
161: remfiles08a.at:28 remove-files deleting two subdirs in -c/non-incr. mode
create remove-files remfiles08 remfiles08a
163: remfiles08c.at:28 remove-files deleting two subdirs in -r mode
create append remove-files remfiles08 remfiles08c
According to an earlier message to bug-tar, they also fail on Solaris.
I've looked at test #161 and it does this:
mkdir foo
mkdir bar
echo foo/foo_file > foo/foo_file
echo bar/bar_file > bar/bar_file
decho A
tar -cvf foo.tar --remove-files -C foo . -C ../bar .
decho B
find .
The failing result is that ./bar still exists.
A system call trace reveals this:
...
9370 gtar CALL unlinkat(0x4,0x801453100,0)
9370 gtar NAMI "foo_file"
9370 gtar RET unlinkat 0
9370 gtar CALL unlinkat(AT_FDCWD,0x801451060,0x800)
9370 gtar NAMI "foo"
9370 gtar RET unlinkat 0
9370 gtar CALL unlinkat(0x5,0x801453110,0)
9370 gtar NAMI "bar_file"
9370 gtar RET unlinkat 0
9370 gtar CALL unlinkat(0x4,0x801451068,0x800)
9370 gtar NAMI "../bar"
9370 gtar RET unlinkat -1 errno 2 No such file or directory
...
The problem is that "foo" is deleted and then the attempt fails to
delete a path relative to a filedescriptor referring to "foo".
The test program below reproduces this: The final unlinkat() fails
on FreeBSD/OpenBSD but succeeds on Linux.
(err.h may not be available everywhere.)
-----------------------------
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
int fd;
if (mkdir("foo", 0777) == -1)
err(1, "can't create foo");
if (mkdir("bar", 0777) == -1)
err(1, "can't create bar");
if ((fd = open("foo", O_RDONLY)) == -1)
err(1, "can't open foo");
if (unlinkat(AT_FDCWD, "foo", AT_REMOVEDIR) == -1)
err(1, "can't remove foo");
if (unlinkat(fd, "../bar", AT_REMOVEDIR) == -1)
err(1, "can't remove ../bar");
return 0;
}
-----------------------------
The BSD behavior appears to be in line with POSIX. unlinkat() with
AT_REMOVEDIR is equivalent to rmdir(), whose specification says:
If one or more processes have the directory open when the last
link is removed, the dot and dot-dot entries, if present, shall
be removed before rmdir() returns and no new entries may be created
in the directory, but the directory shall not be removed until
all references to the directory are closed.
Without "..", the path resolution of the subsequent unlinkat() call
should--or at least can--fail.
--
Christian "naddy" Weisgerber address@hidden
- [Bug-tar] GNU tar 1.28: tests 161 163 fail on !Linux,
Christian Weisgerber <=