summaryrefslogtreecommitdiff
path: root/lib/openat.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2005-12-17 06:55:32 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2005-12-17 06:55:32 +0000
commit3f86aaadcfc70682baab8b676de5cfd7e2340e2c (patch)
tree1c54cacbf21c8ff492c897db34509d43a6bcf775 /lib/openat.c
parent1c5cebe7033a90f4350ddb794f905dce68f2d6b8 (diff)
downloadcoreutils-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/openat.c')
-rw-r--r--lib/openat.c229
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;
}