commit: b31d16cba79ce9892c36db520c2e8a43df6c8830
parent 31812994d3503b922c6ca74cc7a1fc749736a650
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Fri, 29 Mar 2024 04:50:18 +0100
cmd/rm: Avoid non-portable AT_SYMLINK_NOFOLLOW by skipping symlinks
Diffstat:
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/cmd/rm.c b/cmd/rm.c
@@ -196,12 +196,21 @@ do_unlinkat(int fd, char *name, char *acc_path)
if(!force)
{
- // FIXME: Terminal always considered to be present for tests reason
- if(faccessat(fd, name, W_OK, AT_SYMLINK_NOFOLLOW) != 0 || opt_i)
+ if(opt_i)
{
- errno = 0;
if(!consentf("rm: Remove '%s' ? [y/N] ", acc_path)) return 0;
}
+ else
+ {
+ // Don't check symbolic links, would need AT_SYMLINK_NOFOLLOW on faccessat which isn't portable
+ // Can assume symbolic links are 0777 anyway
+ if(!S_ISLNK(stats.st_mode) && faccessat(fd, name, W_OK, 0) != 0)
+ {
+ errno = 0;
+
+ if(!consentf("rm: Remove non-writable '%s' ? [y/N] ", acc_path)) return 0;
+ }
+ }
}
assert(errno == 0);
diff --git a/test-cmd/rm.t b/test-cmd/rm.t
@@ -82,14 +82,14 @@ Extra check from rm(1), unrelated to the EPERM that unlink gets on a non-writabl
$ touch no_write
$ chmod -- -w no_write
$ echo | rm no_write
- rm: Remove 'no_write' ? [y/N]
+ rm: Remove non-writable 'no_write' ? [y/N]
rm: Got empty response, considering it false
$ test -f no_write
$ echo n | rm no_write
- rm: Remove 'no_write' ? [y/N] n
+ rm: Remove non-writable 'no_write' ? [y/N] n
$ test -f no_write
$ echo y | rm no_write
- rm: Remove 'no_write' ? [y/N] y
+ rm: Remove non-writable 'no_write' ? [y/N] y
$ test ! -f no_write