summaryrefslogtreecommitdiff
path: root/src/unistd/access.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/unistd/access.c')
-rw-r--r--src/unistd/access.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/unistd/access.c b/src/unistd/access.c
new file mode 100644
index 00000000..25554edf
--- /dev/null
+++ b/src/unistd/access.c
@@ -0,0 +1,43 @@
+#include "stddef.h"
+#include "sys/types.h"
+#include <unistd.h>
+#include "errno.h"
+#include "sys/stat.h"
+
+int access(const char *path, int amode)
+{
+ struct stat st;
+ mode_t check = (amode & R_OK ? 4 : 0)
+ | (amode & W_OK ? 2 : 0)
+ | (amode & X_OK ? 1 : 0);
+
+ if (amode != F_OK && ((amode & ~(R_OK | W_OK | X_OK)) != 0)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (stat(path, &st) == -1) {
+ /* errno set by stat() */
+ return -1;
+ }
+
+ if (amode == F_OK) {
+ return 0;
+ }
+
+ if (st.st_uid == getuid()) {
+ check <<= 6;
+ } else if (st.st_gid == getgid()) {
+ check <<= 3;
+ }
+
+ if ((st.st_mode & check) == check) {
+ return 0;
+ }
+
+ errno = EACCES;
+ return -1;
+}
+/*
+POSIX(1)
+*/