aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2010-04-02 22:02:22 +0800
committermaximilian attems <max@stro.at>2010-04-21 03:28:30 +0200
commit4fb18548dd55d68432105fd3c79a284242a3e73b (patch)
tree5824792c4faed098df9fb531f1970e7c67d7d281
parentd2324fee68bcfbe50fe73e835d2a2a1e0995e44f (diff)
downloadklibc-4fb18548dd55d68432105fd3c79a284242a3e73b.tar.gz
[klibc] [BUILTIN] Use faccessat if available
Eric Blake suggested that we should use faccessat so that ACLs and other corner cases are handled correctly. This patch does exactly that. Note that faccessat doesn't handle ACLs when euid != uid, as this case is currently implemented by glibc instead of the kernel, using code similar to the existing dash test. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> [ config.h undef HAVE_FACCESSAT ] Signed-off-by: maximilian attems <max@stro.at>
-rw-r--r--usr/dash/bltin/test.c22
-rw-r--r--usr/dash/config.h3
2 files changed, 25 insertions, 0 deletions
diff --git a/usr/dash/bltin/test.c b/usr/dash/bltin/test.c
index 8e7077a198805..7888f38eeb969 100644
--- a/usr/dash/bltin/test.c
+++ b/usr/dash/bltin/test.c
@@ -11,6 +11,7 @@
#include <sys/stat.h>
#include <sys/types.h>
+#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -147,8 +148,12 @@ static int isoperand(char **);
static int newerf(const char *, const char *);
static int olderf(const char *, const char *);
static int equalf(const char *, const char *);
+#ifdef HAVE_FACCESSAT
+static int test_file_access(const char *, int);
+#else
static int test_st_mode(const struct stat64 *, int);
static int bash_group_member(gid_t);
+#endif
static inline intmax_t getn(const char *s)
{
@@ -295,6 +300,14 @@ primary(enum token n)
return strlen(*t_wp) != 0;
case FILTT:
return isatty(getn(*t_wp));
+#ifdef HAVE_FACCESSAT
+ case FILRD:
+ return test_file_access(*t_wp, R_OK);
+ case FILWR:
+ return test_file_access(*t_wp, W_OK);
+ case FILEX:
+ return test_file_access(*t_wp, X_OK);
+#endif
default:
return filstat(*t_wp, n);
}
@@ -364,12 +377,14 @@ filstat(char *nm, enum token mode)
return 0;
switch (mode) {
+#ifndef HAVE_FACCESSAT
case FILRD:
return test_st_mode(&s, R_OK);
case FILWR:
return test_st_mode(&s, W_OK);
case FILEX:
return test_st_mode(&s, X_OK);
+#endif
case FILEXIST:
return 1;
case FILREG:
@@ -469,6 +484,12 @@ equalf (const char *f1, const char *f2)
b1.st_ino == b2.st_ino);
}
+#ifdef HAVE_FACCESSAT
+static int test_file_access(const char *path, int mode)
+{
+ return !faccessat(AT_FDCWD, path, mode, AT_EACCESS);
+}
+#else /* HAVE_FACCESSAT */
/*
* Similar to what access(2) does, but uses the effective uid and gid.
* Doesn't make the mistake of telling root that any file is executable.
@@ -519,3 +540,4 @@ bash_group_member(gid_t gid)
return (0);
}
+#endif /* HAVE_FACCESSAT */
diff --git a/usr/dash/config.h b/usr/dash/config.h
index 4b76f8a9481a1..ea090484acaa8 100644
--- a/usr/dash/config.h
+++ b/usr/dash/config.h
@@ -10,6 +10,9 @@
/* Define to 1 if you have the `bsearch' function. */
#define HAVE_BSEARCH 1
+/* Define to 1 if you have the `faccessat' function. */
+/* #undef HAVE_FACCESSAT */
+
/* Define to 1 if you have the `fnmatch' function. */
/* #undef HAVE_FNMATCH */