[Rd] unlink() on "~" removes the home directory

Gábor Csárdi c@@rd|@g@bor @end|ng |rom gm@||@com
Wed Feb 26 23:47:49 CET 2020


!!! DON'T TRY THE CODE IN THIS EMAIL AT HOME !!!

Well, unlink() does what it is supposed to do, so you could argue that
there is nothing wrong with it. Also, nobody would call unlink() on
"~", right?

The situation is not so simple, however. E.g. if you happen to have a
directory called "~", and you iterate over all files and directories
to selectively remove some of them, then your code might end up
calling unlink on the local "~" directory, and then your home is gone.

But you would not create a directory named "~", that is just asking
for trouble. Well, surely, _intentionally_ you would not do that.
Unintentionally, you might. E.g. something like this is enough:

# Create a subpath within a base directory
badfun <- function(base = ".", path) {
  dir.create(file.path(base, path), recursive = TRUE, showWarnings = FALSE)
}
badfun(path = "~/foo")

(If you did run this, be very careful how you remove the directory called "~"!)

A real example is `R CMD build` which deletes the home directory of
the current user if the root of the package contains a non-empty "~"
directory. Luckily this is now fixed in R-devel, so R 4.0.0 will do
better. (R 3.6.3 will not.) See
https://github.com/wch/r-source/commit/1d4f7aa1dac427ea2213d1f7cd7b5c16e896af22

I have seen several bug reports about various packages (that call R
CMD build) removing the home directory, so this indeed happens in
practice to a number of people. The commit above will fix `R CMD
build`, but it would be great to "fix" this in general.

It seems pretty hard to prevent users from creating of a "~"
directory. But preventing unlink() from deleting "~" does not actually
seem too hard. If unlink() could just refuse removing "~" (when expand
= TRUE), that would be great. It seems to me that the current behavior
is very-very rarely intended, and its consequences are potentially
disastrous.

If unlink("~", recursive = TRUE) errors, you can still remove a local
"~" file/dir with unlink("./~", ...). And you can still remove your
home directory if you really want to do that, with
unlink(path.expand("~"), ...). So no functionality is lost.

Also, if anyone is aware of packages/functions that tend to create "~"
directories or files, please let me know.

I would be happy to submit a patch for the new unlink("~") behavior.

Thanks,
Gabor



More information about the R-devel mailing list