From 43b89665dc3ec83ccfc292d6bc65dce75fdad9b3 Mon Sep 17 00:00:00 2001 From: Lubos Dolezel Date: Wed, 1 Feb 2017 23:39:55 +0100 Subject: [PATCH] Implement sys_openat() --- src/kernel/emulation/linux/CMakeLists.txt | 1 + src/kernel/emulation/linux/fcntl/open.h | 2 + src/kernel/emulation/linux/fcntl/openat.c | 46 +++++++++++++++++++++++ src/kernel/emulation/linux/fcntl/openat.h | 8 ++++ src/kernel/emulation/linux/syscalls.c | 3 ++ 5 files changed, 60 insertions(+) create mode 100644 src/kernel/emulation/linux/fcntl/openat.c create mode 100644 src/kernel/emulation/linux/fcntl/openat.h diff --git a/src/kernel/emulation/linux/CMakeLists.txt b/src/kernel/emulation/linux/CMakeLists.txt index 8cbfbffb3..32a23cc67 100644 --- a/src/kernel/emulation/linux/CMakeLists.txt +++ b/src/kernel/emulation/linux/CMakeLists.txt @@ -114,6 +114,7 @@ set(emulation_sources misc/getrusage.c misc/getlogin.c fcntl/open.c + fcntl/openat.c fcntl/fcntl.c network/socket.c network/socketpair.c diff --git a/src/kernel/emulation/linux/fcntl/open.h b/src/kernel/emulation/linux/fcntl/open.h index 0e6ab1cf2..b5164cdd7 100644 --- a/src/kernel/emulation/linux/fcntl/open.h +++ b/src/kernel/emulation/linux/fcntl/open.h @@ -37,5 +37,7 @@ long sys_open_nocancel(const char* filename, int flags, unsigned int mode); #define BSD_O_SYMLINK 0x200000 #define BSD_O_CLOEXEC 0x1000000 +int oflags_bsd_to_linux(int flags); + #endif diff --git a/src/kernel/emulation/linux/fcntl/openat.c b/src/kernel/emulation/linux/fcntl/openat.c new file mode 100644 index 000000000..a55b300bb --- /dev/null +++ b/src/kernel/emulation/linux/fcntl/openat.c @@ -0,0 +1,46 @@ +#include "openat.h" +#include "open.h" +#include "../base.h" +#include "../errno.h" +#include +#include "../../../../libc/include/fcntl.h" +#include "../common_at.h" + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0x0100 +#endif +#ifndef O_CLOEXEC +# define O_CLOEXEC 0x1000000 +#endif +#ifndef O_DIRECTORY +# define O_DIRECTORY 0x100000 +#endif + +extern int strcmp(const char *s1, const char *s2); + +long sys_openat(int fd, const char* filename, int flags, unsigned int mode) +{ + return sys_openat_nocancel(fd, filename, flags, mode); +} + +long sys_openat_nocancel(int fd, const char* filename, int flags, unsigned int mode) +{ + int ret, linux_flags; + + linux_flags = oflags_bsd_to_linux(flags); + + if (sizeof(void*) == 4) + { + linux_flags |= LINUX_O_LARGEFILE; + } + + // XNU /dev/random behaves like Linux /dev/urandom + if (strcmp(filename, "/dev/random") == 0) + filename = "/dev/urandom"; + + ret = LINUX_SYSCALL(__NR_openat, atfd(fd), filename, linux_flags, mode); + if (ret < 0) + ret = errno_linux_to_bsd(ret); + + return ret; +} diff --git a/src/kernel/emulation/linux/fcntl/openat.h b/src/kernel/emulation/linux/fcntl/openat.h new file mode 100644 index 000000000..b323a235d --- /dev/null +++ b/src/kernel/emulation/linux/fcntl/openat.h @@ -0,0 +1,8 @@ +#ifndef LINUX_OPENAT_H +#define LINUX_OPENAT_H + +long sys_openat(int fd, const char* filename, int flags, unsigned int mode); +long sys_openat_nocancel(int fd, const char* filename, int flags, unsigned int mode); + +#endif + diff --git a/src/kernel/emulation/linux/syscalls.c b/src/kernel/emulation/linux/syscalls.c index 707e9611e..d396a3021 100644 --- a/src/kernel/emulation/linux/syscalls.c +++ b/src/kernel/emulation/linux/syscalls.c @@ -82,6 +82,7 @@ #include "misc/syscall.h" #include "synch/semwait_signal.h" #include "fcntl/open.h" +#include "fcntl/openat.h" #include "fcntl/fcntl.h" #include "network/socket.h" #include "network/connect.h" @@ -335,6 +336,8 @@ void* __bsd_syscall_table[600] = { [417] = sys_poll_nocancel, [423] = sys_semwait_signal_nocancel, [461] = sys_getattrlistbulk, + [463] = sys_openat, + [464] = sys_openat_nocancel, [469] = sys_fstatat, [470] = sys_fstatat64, [500] = sys_getentropy, -- 2.51.2