Hi, the enclosed patch changes the following (remove.c against HEAD):
* write_protected_non_symlink() now returns -1 for error (errno will be set accordingly), 0 for everything fine, and 1 if it's a write protected file. * prompt() now deals with the changed semantics of the above function. It's needed because error codes are expressed with negative values on some platforms like Haiku, and BeOS; previously, the code incorrectly assumed error codes would always be positive. Kind Regards, Axel Dörfler.
diff --git a/src/remove.c b/src/remove.c index 9c6dc9e..61bc935 100644 --- a/src/remove.c +++ b/src/remove.c @@ -728,9 +728,9 @@ AD_is_removable (Dirstack_state const *ds, char const *file) return ! (top->unremovable && hash_lookup (top->unremovable, file)); } -/* Return -1 if FILE is an unwritable non-symlink, - 0 if it is writable or some other type of file, - a positive error number if there is some problem in determining the answer. +/* Return 1 if FILE is an unwritable non-symlink, 0 if it is writable or some + other type of file. + Returns -1 and sets errno if there is some problem in determining the answer. Set *BUF to the file status. This is to avoid calling euidaccess when FILE is a symlink. */ static int @@ -742,7 +742,7 @@ write_protected_non_symlink (int fd_cwd, if (can_write_any_file ()) return 0; if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0) - return errno; + return -1; if (S_ISLNK (buf->st_mode)) return 0; /* Here, we know FILE is not a symbolic link. */ @@ -799,15 +799,18 @@ write_protected_non_symlink (int fd_cwd, = obstack_object_size (&ds->dir_stack) + strlen (file); if (MIN (PATH_MAX, 8192) <= file_name_len) - return - euidaccess_stat (buf, W_OK); + return ! euidaccess_stat (buf, W_OK); if (euidaccess (xfull_filename (ds, file), W_OK) == 0) return 0; if (errno == EACCES) - return -1; + { + errno = 0; + return 1; + } /* Perhaps some other process has removed the file, or perhaps this is a buggy NFS client. */ - return errno; + return -1; } } @@ -839,15 +842,18 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, if (x->interactive == RMI_NEVER) return RM_OK; + errno = 0; + if (!x->ignore_missing_files && ((x->interactive == RMI_ALWAYS) || x->stdin_tty) && dirent_type != DT_LNK) write_protected = write_protected_non_symlink (fd_cwd, filename, ds, sbuf); - if (write_protected || x->interactive == RMI_ALWAYS) + if (write_protected || errno || x->interactive == RMI_ALWAYS) { - if (write_protected <= 0 && dirent_type == DT_UNKNOWN) + if (errno == 0 && dirent_type == DT_UNKNOWN) { + /* Might fail, e.g., for `rm '''. */ if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0) { if (S_ISLNK (sbuf->st_mode)) @@ -857,14 +863,9 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, /* Otherwise it doesn't matter, so leave it DT_UNKNOWN. */ *pdirent_type = dirent_type; } - else - { - /* This happens, e.g., with `rm '''. */ - write_protected = errno; - } } - if (write_protected <= 0) + if (errno == 0) switch (dirent_type) { case DT_LNK: @@ -875,15 +876,15 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, case DT_DIR: if (!x->recursive) - write_protected = EISDIR; + errno = EISDIR; break; } char const *quoted_name = quote (full_filename (filename)); - if (0 < write_protected) + if (errno != 0) { - error (0, write_protected, _("cannot remove %s"), quoted_name); + error (0, errno, _("cannot remove %s"), quoted_name); return RM_ERROR; }
_______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils