Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Sep 2007 22:00:15 GMT
From:      Bruce Evans <brde@optusnet.com.au>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/116477: rm behaves unexpectedly when using -r and relative paths
Message-ID:  <200709202200.l8KM0Fc2055932@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/116477; it has been noted by GNATS.

From: Bruce Evans <brde@optusnet.com.au>
To: Justin Mitchell <freebsd.20.skel@spamgourmet.org>
Cc: freebsd-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org
Subject: Re: bin/116477: rm behaves unexpectedly when using -r and relative
 paths
Date: Thu, 20 Sep 2007 21:45:20 +1000 (EST)

 On Wed, 19 Sep 2007, Justin Mitchell wrote:
 
 >> Description:
 > This is a bug with the 'rm' commandline utility that can cause data
 > loss.
 
 This is rm doing what you asked it to.
 
 > When using 'rm -r' with relative paths and a trailing slash rm can
 > delete the wrong item, or no item at all. Here is an example of rm
 > deleting the wrong file.
 >
 > mac:~ $ mkdir tmp
 > mac:~ $ cd tmp
 > mac:~/tmp $ mkdir test
 > mac:~/tmp $ ln -s test test2
 > mac:~/tmp $ ls -l
 > total 8
 > drwxr-xr-x   2 justin  justin  68 Aug 10 01:41 test
 > lrwxr-xr-x   1 justin  justin   4 Aug 10 01:42 test2 -> test
 > mac:~/tmp $ cd ..
 > mac:~ $ rm -r tmp/test2/
 > mac:~ $ ls -l tmp
 > total 8
 > lrwxr-xr-x   1 justin  justin  4 Aug 10 01:42 test2 -> test
 >
 > Note that if you do you not use the trailing slash in 'rm -f tmp/
 > test2/' that it will behave normally. It will also behave normally if
 > you do not 'cd' to another directory.
 >
 > I confirmed this with another individual running OS X, but I do
 > not know the version. For comparison, I tested this with an older
 > version of Redhat, and it worked fine.
 
 gnu/Linux rm or Linux could easily have a bug like that, but at least
 the version in an old FreeBSD package (linux_base-8-8.0_4 with bin/rm
 dated Sep 2 2002) works correctly under FreeBSD -- it removes the
 directory.
 
 > I submitted this bug report to Apple, but they said "This is how FreeBSD operates and rm is based on their sources."
 
 This is how symbolic links work.  The trailing slash causes the symlink
 to be followed.  POSIX spec: trailing slashes shall be resolved as if
 a single dot character were appended to a pathname.  Hmm, this seems
 to require a small part behaviour that you want -- the pathname ends
 up with a trailing dot no matter where in the process of pathname
 resolution that the dot is added.  Then rm(1)'s and/or rmdir(2)'s
 (bogus) restriction on removing "." and ".." comes into play and
 according to POSIX should prevent the removal of the directory pointed
 to by the symlink (but not the contents of the directory -- see below).
 
 What FreeBSD does is follow "test2/" to resolve to "test".  It doesn't
 add the dot as required by POSIX.  POSIX doesn't seem to say clearly
 when the dot should be added, but it would have to be added at the
 beginning of pathname resolution to be useful, since then it would
 cause "test2/" to be resolved to "test/.", while adding it after
 resolving to "test" would give the name "test." where the dot doesn't
 have anything to do with the directory entry "." and just messes up
 the name "test".
 
 After resolving to "test/.", rmdir() on the directory must fail due
 to rmdir()'s bogus restriction on removing ".".  This restriction is
 bogus because it is only by name -- you can easily rmdir() your current
 directory (if it is empty) by spelling its name differently, e.g., as
 the absolute path to th current directory, but you can't dubdirectories
 if you spell their name with a ".".  Before I started writing this mail,
 I thought that you could use the spelling of "<symlink>/" to remove
 current and other directories, but the POSIX spec prevents that.
 
 However, the POSIX spec doesn't affect removing the directories entire
 contents using "rm -r <symlink>/".  rm has its own bogus restriction
 on removing "." (and "..") by name.  This restriction doesn't apply
 here since there is no dot in "<symlink>/".  The pathname resolution
 that POSIX requires to add the dot occurs entirely in the kernel.
 
 Thus the expected behaviour for a POSIX "rm -r test2/" is:
 
      follow the symlink to get "test/."
      remove the contents of "test/."
         rm will probably just apply rm -r to each file in "test/.".
         I verified that the Linux rm from 2002 when run under FreeBSD
         just chdir()'s into any subdirs to remove them recursively.
      fail with errno EINVAL trying to rmdir() "test/."
         (the Linux rm from 2002 just tries to remove "test/", and this
         succeeds under FreeBSD)
      don't remove the symlink
 
      This is not what you want -- it removes everything except the one
      thing that is easy to recover.
 
 and the expected behaviour for a FreeBSD "rm -r test2/" is:
 
      same as above, except it won't fail on the top-level rmdir().
 
 I know too much about this because I broke following of symlinks for
 "<symlink>/" when fixing the handling of trailing slashes in general.
 
 Some other cases of interest:
 
 (1) when test2 is symlink to "test" and "test" doesn't exist at the start
      of each of the following operations:
 
      FreeBSD mkdir test2/    succeeds
      FreeBSD mkdir test2/.   fails with errno ENOENT (reasonable, since test2
  			    exists, but test2/ and test2/, don't)
      POSIX   mkdir test2/    must fail after adding dot
 
 (2) when "test" doesn't exist at the start:
 
      FreeBSD mkdir test      succeeds, nothing special
      FreeBSD mkdir test/     succeeds (tricky to make this work)
      FreeBSD mkdir test/.    fails with ENOENT
      POSIX   mkdir test/     ?  POSIX says that trailing slashes shall be
  			    ignored in directory contexts.  FreeBSD
  			    considers this to be a directory context
 
 (3) cases involving rename(2) are more complicated, and cases involving
      mv(1) are even more complicated, since mv to a directory has to manage
      pathnames before calling rename(2).
 
 Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200709202200.l8KM0Fc2055932>