POSIX is clear that attempts to rmdir() a directory that still has open
descriptors may fail. Of course, on Linux, this (rather limiting)
restriction is not present, so we don't notice it; but on Cygwin, there
are certain file systems where this is a real problem, such as in this
thread:
http://cygwin.com/ml/cygwin/2011-10/msg00365.html
Looking at an strace on Linux reveals the problem (abbreviated to show
highlights here):
$ mkdir -p a/b
$ strace rm -f a
...
openat(AT_FDCWD, "a",
O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
...
fcntl(3, F_DUPFD, 3) = 4
...
close(3) = 0
...
openat(4, "b", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
...
fcntl(3, F_DUPFD, 3) = 5
...
close(3) = 0
close(5) = 0
unlinkat(4, "b", AT_REMOVEDIR) = 0
unlinkat(AT_FDCWD, "a", AT_REMOVEDIR) = 0
close(4) = 0
Notice that for subdirectories, we opened the directory, then used dup
to have a handle for use in further *at calls, then do
fdopendir/readdir/closedir on the DIR*, then close the duplicate fd, all
before calling unlinkat (aka rmdir) on that subdirectory. But for the
top-level directory, the dup'd fd (4) is still open when we attempt the
unlinkat.
I'm still trying to investigate whether the fix needs to be in gnulib or
just coreutils, but something needs to be done to swap the order so that
the last handle to the directory is closed prior to the rmdir attempt.
--
Eric Blake ebl...@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org