diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2005-12-17 06:55:32 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2005-12-17 06:55:32 +0000 |
commit | 3f86aaadcfc70682baab8b676de5cfd7e2340e2c (patch) | |
tree | 1c54cacbf21c8ff492c897db34509d43a6bcf775 /lib | |
parent | 1c5cebe7033a90f4350ddb794f905dce68f2d6b8 (diff) | |
download | coreutils-3f86aaadcfc70682baab8b676de5cfd7e2340e2c.tar.xz |
Don't include <stdlib.h>, <unistd.h>, <fcntl.h>,
"gettext.h"; either no longer needed or are guaranteed by openat.h.
(_): Remove; no longer needed.
(openat): Renamed from rpl_openat; no need for rpl_openat
since openat.h renames openat for us.
Replace most of the body with a call to openat_permissive,
to avoid duplicate code.
Port to (probably hypothetical) environments were mode_t is
wider than int.
(openat_permissive): Require mode arg, so that we can check
types better. Put it just after flags. Change cwd failure
indicator from pointer-to-bool to pointer-to-errno-value.
All callers changed.
Invoke openat_save_fail and/or openat_restore_fail if
cwd_errno is null, so that openat can call us.
(openat_permissive, fdopendir, fstatat, unlinkat):
Simplify errno handling to avoid some duplicate code,
as it's OK to set errno on success.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/openat.c | 229 |
1 files changed, 82 insertions, 147 deletions
diff --git a/lib/openat.c b/lib/openat.c index 1c6d6d728..20c217d97 100644 --- a/lib/openat.c +++ b/lib/openat.c @@ -23,19 +23,13 @@ #include "openat.h" -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <errno.h> -#include <fcntl.h> - #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ +#include "openat-priv.h" #include "save-cwd.h" -#include "gettext.h" -#define _(msgid) gettext (msgid) - -#include "openat-priv.h" +#include <stdarg.h> +#include <stddef.h> +#include <errno.h> /* Replacement for Solaris' openat function. <http://www.google.com/search?q=openat+site:docs.sun.com> @@ -46,61 +40,31 @@ Otherwise, upon failure, set errno and return -1, as openat does. Upon successful completion, return a file descriptor. */ int -rpl_openat (int fd, char const *file, int flags, ...) +openat (int fd, char const *file, int flags, ...) { - struct saved_cwd saved_cwd; - int saved_errno; - int err; mode_t mode = 0; if (flags & O_CREAT) { va_list arg; va_start (arg, flags); - /* Use the promoted type (int), not mode_t, as second argument. */ - mode = (mode_t) va_arg (arg, int); - va_end (arg); - } - - if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) - return open (file, flags, mode); - - { - char *proc_file; - BUILD_PROC_NAME (proc_file, fd, file); - err = open (proc_file, flags, mode); - /* If the syscall succeeds, or if it fails with an unexpected - errno value, then return right away. Otherwise, fall through - and resort to using save_cwd/restore_cwd. */ - if (0 <= err || ! EXPECTED_ERRNO (errno)) - return err; - } - if (save_cwd (&saved_cwd) != 0) - openat_save_fail (errno); + /* If mode_t is narrower than int, use the promoted type (int), + not mode_t. Use sizeof to guess whether mode_t is nerrower; + we don't know of any practical counterexamples. */ + if (sizeof (mode_t) < sizeof (int)) + mode = va_arg (arg, int); + else + mode = va_arg (arg, mode_t); - if (fchdir (fd) != 0) - { - saved_errno = errno; - free_cwd (&saved_cwd); - errno = saved_errno; - return -1; + va_end (arg); } - err = open (file, flags, mode); - saved_errno = (err < 0 ? errno : 0); - - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); - - free_cwd (&saved_cwd); - - if (saved_errno) - errno = saved_errno; - return err; + return openat_permissive (fd, file, flags, mode, NULL); } -/* Like openat above, but set *RESTORE_FAILED if unable to save +/* Like openat (FD, FILE, FLAGS, MODE), but if CWD_ERRNO is + nonnull, set *CWD_ERRNO to an errno value if unable to save or restore the initial working directory. This is needed only the first time remove.c's remove_dir opens a command-line directory argument. @@ -111,23 +75,13 @@ rpl_openat (int fd, char const *file, int flags, ...) in that case. */ int -openat_permissive (int fd, char const *file, int flags, - bool *cwd_restore_failed, ...) +openat_permissive (int fd, char const *file, int flags, mode_t mode, + int *cwd_errno) { struct saved_cwd saved_cwd; int saved_errno; - int save_restore_errno = 0; int err; - mode_t mode = 0; - - if (flags & O_CREAT) - { - va_list arg; - va_start (arg, cwd_restore_failed); - /* Use the promoted type (int), not mode_t, as second argument. */ - mode = (mode_t) va_arg (arg, int); - va_end (arg); - } + bool save_ok; if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) return open (file, flags, mode); @@ -143,37 +97,31 @@ openat_permissive (int fd, char const *file, int flags, return err; } - if (save_cwd (&saved_cwd) != 0) + save_ok = (save_cwd (&saved_cwd) == 0); + if (! save_ok) { - *cwd_restore_failed = true; - save_restore_errno = errno; + if (! cwd_errno) + openat_save_fail (errno); + *cwd_errno = errno; } - if (fchdir (fd) != 0) - { - saved_errno = errno; - free_cwd (&saved_cwd); - errno = saved_errno; - return -1; - } - - err = open (file, flags, mode); - saved_errno = (err < 0 ? errno : 0); + err = fchdir (fd); + saved_errno = errno; - if ( ! *cwd_restore_failed && restore_cwd (&saved_cwd) != 0) + if (! err) { - *cwd_restore_failed = true; - save_restore_errno = errno; + err = open (file, flags, mode); + saved_errno = errno; + if (save_ok && restore_cwd (&saved_cwd) != 0) + { + if (! cwd_errno) + openat_restore_fail (errno); + *cwd_errno = errno; + } } - if ( ! *cwd_restore_failed) - free_cwd (&saved_cwd); - - if (saved_errno) - errno = saved_errno; - else if (save_restore_errno) - errno = save_restore_errno; - + free_cwd (&saved_cwd); + errno = saved_errno; return err; } @@ -198,43 +146,38 @@ fdopendir (int fd) int saved_errno; DIR *dir; - { - char *proc_file; - BUILD_PROC_NAME (proc_file, fd, "."); - dir = opendir (proc_file); - saved_errno = (dir == NULL ? errno : 0); - /* If the syscall succeeds, or if it fails with an unexpected - errno value, then return right away. Otherwise, fall through - and resort to using save_cwd/restore_cwd. */ - if (dir != NULL || ! EXPECTED_ERRNO (errno)) - goto close_and_return; - } + char *proc_file; + BUILD_PROC_NAME (proc_file, fd, "."); + dir = opendir (proc_file); + saved_errno = errno; - if (save_cwd (&saved_cwd) != 0) - openat_save_fail (errno); - - if (fchdir (fd) != 0) + /* If the syscall fails with an expected errno value, resort to + save_cwd/restore_cwd. */ + if (! dir && EXPECTED_ERRNO (saved_errno)) { - saved_errno = errno; + if (save_cwd (&saved_cwd) != 0) + openat_save_fail (errno); + + if (fchdir (fd) != 0) + { + dir = NULL; + saved_errno = errno; + } + else + { + dir = opendir ("."); + saved_errno = errno; + + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + } + free_cwd (&saved_cwd); - errno = saved_errno; - return NULL; } - dir = opendir ("."); - saved_errno = (dir == NULL ? errno : 0); - - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); - - free_cwd (&saved_cwd); - - close_and_return:; if (dir) close (fd); - - if (saved_errno) - errno = saved_errno; + errno = saved_errno; return dir; } @@ -275,26 +218,22 @@ fstatat (int fd, char const *file, struct stat *st, int flag) if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); - if (fchdir (fd) != 0) + err = fchdir (fd); + saved_errno = errno; + + if (! err) { + err = (flag == AT_SYMLINK_NOFOLLOW + ? lstat (file, st) + : stat (file, st)); saved_errno = errno; - free_cwd (&saved_cwd); - errno = saved_errno; - return -1; - } - - err = (flag == AT_SYMLINK_NOFOLLOW - ? lstat (file, st) - : stat (file, st)); - saved_errno = (err < 0 ? errno : 0); - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + } free_cwd (&saved_cwd); - - if (saved_errno) - errno = saved_errno; + errno = saved_errno; return err; } @@ -329,23 +268,19 @@ unlinkat (int fd, char const *file, int flag) if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); - if (fchdir (fd) != 0) + err = fchdir (fd); + saved_errno = errno; + + if (! err) { + err = (flag == AT_REMOVEDIR ? rmdir (file) : unlink (file)); saved_errno = errno; - free_cwd (&saved_cwd); - errno = saved_errno; - return -1; - } - - err = (flag == AT_REMOVEDIR ? rmdir (file) : unlink (file)); - saved_errno = (err < 0 ? errno : 0); - if (restore_cwd (&saved_cwd) != 0) - openat_restore_fail (errno); + if (restore_cwd (&saved_cwd) != 0) + openat_restore_fail (errno); + } free_cwd (&saved_cwd); - - if (saved_errno) - errno = saved_errno; + errno = saved_errno; return err; } |