diff --git a/qa/lib/c/access.c b/qa/lib/c/access.c new file mode 100644 index 0000000..bec8557 --- /dev/null +++ b/qa/lib/c/access.c @@ -0,0 +1,40 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2017 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +#include +#include + +void +main(void) +{ + char *err = nil; + if(access("/tmp", AEXIST) != 0) + err = "/tmp does not exists"; + else if(access("/tmp", AREAD) != 0) + err = "/tmp is not readable"; + else if(access("/tmp", AWRITE) != 0) + err = "/tmp is not writeable"; + else if(access("/tmp", AEXEC) != 0) + err = "/tmp is not traversable"; + if(err == nil){ + print("PASS\n"); + exits("PASS"); + } else { + print("FAIL: %s\n", err); + exits("FAIL"); + } +} diff --git a/qa/lib/c/build.json b/qa/lib/c/build.json index 1271f7d..9aef650 100644 --- a/qa/lib/c/build.json +++ b/qa/lib/c/build.json @@ -12,6 +12,7 @@ "cp *.rc $JEHANNE/arch/$ARCH/qa/lib/c/" ], "SourceFilesCmd": [ + "access.c", "asmscall.c", "cleanname.c", "conswrite.c", diff --git a/qa/lib/newlib/103-files.c b/qa/lib/newlib/103-files.c index 360803a..e64e6be 100644 --- a/qa/lib/newlib/103-files.c +++ b/qa/lib/newlib/103-files.c @@ -39,6 +39,21 @@ main(int argc, char **argv) printf("FAIL: mkdir(qa-files) in /tmp returns %d\n", ret); exit(5); } + ret = access("/tmp/qa-files", F_OK); + if(ret != 0){ + printf("FAIL: access(\"/tmp/qa-files\", F_OK) returned %d; errno %d\n", ret, errno); + exit(6); + } + ret = access("/tmp/qa-files", R_OK); + if(ret != 0){ + printf("FAIL: access(\"/tmp/qa-files\", R_OK) returned %d; errno %d\n", ret, errno); + exit(7); + } + ret = access("/tmp/qa-files", X_OK); + if(ret != 0){ + printf("FAIL: access(\"/tmp/qa-files\", X_OK) returned %d; errno %d\n", ret, errno); + exit(8); + } return 0; } diff --git a/sys/include/posix.h b/sys/include/posix.h index 5c0817a..67ab5bb 100644 --- a/sys/include/posix.h +++ b/sys/include/posix.h @@ -86,6 +86,7 @@ typedef unsigned long clock_t; #define __POSIX_EXIT_SIGNAL_PREFIX "terminated by posix signal " #define __POSIX_SIGNAL_PREFIX "posix: " +extern int POSIX_access(int *errnop, const char *path, int amode); extern void POSIX_exit(int code) __attribute__((noreturn)); extern int POSIX_chmod(int *errnop, const char *path, int mode); extern int POSIX_fchmodat(int *errnop, int fd, const char *path, long mode, int flag); @@ -282,6 +283,8 @@ extern int libposix_translate_open(PosixOpenTranslator translation); extern int libposix_translate_seek_whence(int seek_set, int seek_cur, int seek_end); +extern int libposix_translate_access_mode(int f_ok, int r_ok, int w_ok, int x_ok); + /* Map the main exit status received by POSIX_exit to the exit status * string for Jehanne. * diff --git a/sys/src/lib/c/9sys/access.c b/sys/src/lib/c/9sys/access.c index 7ade817..6b51d82 100644 --- a/sys/src/lib/c/9sys/access.c +++ b/sys/src/lib/c/9sys/access.c @@ -1,7 +1,7 @@ /* * This file is part of Jehanne. * - * Copyright (C) 2016 Giacomo Tesio + * Copyright (C) 2016-2017 Giacomo Tesio * * Jehanne is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ int jehanne_access(const char *name, int mode) { int fd; + Dir *db; static char omode[] = { OSTAT, @@ -40,5 +41,12 @@ jehanne_access(const char *name, int mode) close(fd); return 0; } + db = jehanne_dirstat(name); + if(db != nil){ + fd = db->mode & omode[mode&AMASK]; + jehanne_free(db); + if(fd) + return 0; + } return -1; } diff --git a/sys/src/lib/posix/files.c b/sys/src/lib/posix/files.c index 7aecb1d..9afab27 100644 --- a/sys/src/lib/posix/files.c +++ b/sys/src/lib/posix/files.c @@ -24,6 +24,10 @@ static PosixStatReader __libposix_stat_reader; static PosixOpenTranslator __libposix_open_translation; static int __libposix_AT_FDCWD; +static int __libposix_F_OK; +static int __libposix_R_OK; +static int __libposix_W_OK; +static int __libposix_X_OK; typedef enum SeekTypes { @@ -87,6 +91,19 @@ libposix_translate_seek_whence(int seek_set, int seek_cur, int seek_end) return 1; } +int +libposix_translate_access_mode(int f_ok, int r_ok, int w_ok, int x_ok) +{ + if(__libposix_initialized()) + return 0; + + __libposix_F_OK = f_ok; + __libposix_R_OK = r_ok; + __libposix_W_OK = w_ok; + __libposix_X_OK = x_ok; + return 1; +} + static SeekTypes find_seek_type(int whence) { @@ -99,6 +116,32 @@ find_seek_type(int whence) return -1; } +int +POSIX_access(int *errnop, const char *path, int amode) +{ + PosixError e = 0; + + if(path == nil || path[0] == '\0'){ + e = PosixENOENT; + } else if(amode == __libposix_F_OK){ + if(access(path, AEXIST) == 0) + return 0; + e = PosixENOENT; + } else if(amode & ~(__libposix_R_OK|__libposix_W_OK|__libposix_X_OK)) + e = PosixEINVAL; + else if((amode & __libposix_R_OK) && access(path, AREAD) != 0) + e = PosixEACCES; + else if((amode & __libposix_W_OK) && access(path, AWRITE) != 0) + e = PosixEACCES; + else if((amode & __libposix_X_OK) && access(path, AEXEC) != 0) + e = PosixEACCES; + else + return 0; + + *errnop = __libposix_get_errno(e); + return -1; +} + int POSIX_pipe(int *errnop, int fildes[2]) {