On 14/11/14 13:15, Eric Blake wrote: > On 11/14/2014 04:41 AM, Pádraig Brady wrote: >> tag 19051 notabug >> close 19501 >> stop >> >> On 14/11/14 06:53, aaron brick wrote: >>> hi folks, >>> >>> $ ln -s / sl >>> $ rm sl/ >>> rm: cannot remove `sl/': Is a directory >>> $ rm sl >>> $ >>> > >> >> Confused me too when I encountered it first, but tt's required by POSIX: >> http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11 > > No, actually, POSIX requires that it (attempt to) remove the DIRECTORY, > not the symlink. Linux is intentionally in violation of POSIX on this > front.
Right, that's what I meant. In the original `rm` context above the directory is (implicitly) referenced. On all platforms `rm sl/` it will fail. Following on to the rmdir() issue.. I changed your example below to rmdir which I presume you meant? Yes solaris leaves the dangling symlink in this case. > Try this on Solaris: > > $ mkdir a > $ ln -s a b > $ rmdir b/ > $ ls -d ? > b >> But now I see that coreutils rmdir is inconsistent and doesn't >> treat sl/ as the directory. We should probably fix that up >> to be consistent with other tools, POSIX and other systems. > > We've had this conversation in the past. The fact that Linux > intentionally violates POSIX is actually useful; the POSIX behavior > leaves behind dangling symlinks, whereas the Linux behavior makes some > sort of sense (even if not the best quality errno values). Our decision > has been that we choose NOT to override kernel semantics on this front; > waiting for either the kernel folks to obey POSIX (unlikely) or for > POSIX to relax and concede that the Linux behavior is a useful > alternative and allow it in addition to Solaris behavior (possible, but > I haven't tried pushing hard for it lately). Thanks for the insight. So usually a trailing / is treated as the directory itself: $ mkdir a $ ln -s a b $ ls -Fd b/ b// $ ls -Fd b b@ $ stat b -c %F symbolic link $ stat b/ -c %F directory Also in this case coreutils generates that good error internally without attempting to unlink anything. $ rm b/ rm: cannot remove ‘b/’: Is a directory Then we get to the inconsistent Linux behaviour: $ strace -e unlinkat rm -R b/ unlinkat(AT_FDCWD, "b/", AT_REMOVEDIR) = -1 ENOTDIR (Not a directory) rm: cannot remove ‘b/’: Not a directory $ strace -e rmdir rmdir b/ rmdir("b/") = -1 ENOTDIR (Not a directory) rmdir: failed to remove ‘b/’: Not a directory I disagree with the inconsistent kernel behavior here, though agree we shouldn't try to work around it. thanks, Pádraig.