summaryrefslogtreecommitdiff
path: root/src/unistd/access.c
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-02-09 13:14:01 -0500
committerJakob Kaivo <jkk@ung.org>2019-02-09 13:14:01 -0500
commit253a32e2f9ff1cbb8edbe7c79834a678daebeb93 (patch)
tree599cf5baf01c6dae33a2f89989b08b7d553f7fd0 /src/unistd/access.c
parent88d0b5e7ffbf0554b236dc46225846061b5f4817 (diff)
merge POSIX.1-1988/1990
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)
+*/