diff options
author | Jim Meyering <jim@meyering.net> | 2008-03-24 17:38:27 +0100 |
---|---|---|
committer | Jim Meyering <meyering@redhat.com> | 2008-04-06 09:26:32 +0200 |
commit | 9982e26c12ffae9bbe96eb3ea260d680ab2584a2 (patch) | |
tree | c36c6a86672c01cd670b49b10e87340bcd77af63 /src | |
parent | 2741677b281d66eb33784c7e80c7dec6223b543d (diff) | |
download | coreutils-9982e26c12ffae9bbe96eb3ea260d680ab2584a2.tar.xz |
remove.c: accommodate systems with negative errno values
This is required at least on Haiku and BeOS.
* src/remove.c (write_protected_non_symlink): Return 1 for a write-
protected non-symlink, 0 if we determine it's not, and -1 upon
error (setting errno accordingly only in this final case).
(prompt): Deal with the changed semantics of the above function.
Based on this patch from Axel Dörfler:
http://thread.gmane.org/gmane.comp.gnu.coreutils.bugs/13071
Diffstat (limited to 'src')
-rw-r--r-- | src/remove.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/src/remove.c b/src/remove.c index 7ba1e38ef..07c2f71ba 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, +/* 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. + -1 and set 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) ? 0 : -1; + 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,14 +842,19 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, if (x->interactive == RMI_NEVER) return RM_OK; + int wp_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); + { + write_protected = write_protected_non_symlink (fd_cwd, filename, ds, sbuf); + wp_errno = errno; + } if (write_protected || x->interactive == RMI_ALWAYS) { - if (write_protected <= 0 && dirent_type == DT_UNKNOWN) + if (0 <= write_protected && dirent_type == DT_UNKNOWN) { if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0) { @@ -860,11 +868,12 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, else { /* This happens, e.g., with `rm '''. */ - write_protected = errno; + write_protected = -1; + wp_errno = errno; } } - if (write_protected <= 0) + if (0 <= write_protected) switch (dirent_type) { case DT_LNK: @@ -875,15 +884,18 @@ prompt (int fd_cwd, Dirstack_state const *ds, char const *filename, case DT_DIR: if (!x->recursive) - write_protected = EISDIR; + { + write_protected = -1; + wp_errno = EISDIR; + } break; } char const *quoted_name = quote (full_filename (filename)); - if (0 < write_protected) + if (write_protected < 0) { - error (0, write_protected, _("cannot remove %s"), quoted_name); + error (0, wp_errno, _("cannot remove %s"), quoted_name); return RM_ERROR; } |