diff --git a/kernel/include/kernel/OpenFileDescriptorSet.h b/kernel/include/kernel/OpenFileDescriptorSet.h index ec5a5bcb..c4551be4 100644 --- a/kernel/include/kernel/OpenFileDescriptorSet.h +++ b/kernel/include/kernel/OpenFileDescriptorSet.h @@ -28,6 +28,8 @@ namespace Kernel BAN::ErrorOr dup(int); BAN::ErrorOr dup2(int, int); + BAN::ErrorOr fcntl(int fd, int cmd, int extra); + BAN::ErrorOr seek(int fd, off_t offset, int whence); BAN::ErrorOr tell(int) const; diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 152d8875..2a808fa4 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -99,6 +99,8 @@ namespace Kernel BAN::ErrorOr sys_dup(int fildes); BAN::ErrorOr sys_dup2(int fildes, int fildes2); + BAN::ErrorOr sys_fcntl(int fildes, int cmd, int extra); + BAN::ErrorOr sys_seek(int fd, off_t offset, int whence); BAN::ErrorOr sys_tell(int fd); diff --git a/kernel/kernel/OpenFileDescriptorSet.cpp b/kernel/kernel/OpenFileDescriptorSet.cpp index 607c6a52..46e6f794 100644 --- a/kernel/kernel/OpenFileDescriptorSet.cpp +++ b/kernel/kernel/OpenFileDescriptorSet.cpp @@ -118,6 +118,32 @@ namespace Kernel return fildes; } + BAN::ErrorOr OpenFileDescriptorSet::fcntl(int fd, int cmd, int extra) + { + TRY(validate_fd(fd)); + + constexpr int creation_flags = O_CLOEXEC | O_CREAT | O_DIRECTORY | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_TRUNC | O_TTY_INIT; + + switch (cmd) + { + case F_GETFD: + return m_open_files[fd]->flags; + case F_SETFD: + // FIXME: validate permissions to set access flags + m_open_files[fd]->flags = extra; + return 0; + case F_GETFL: + return m_open_files[fd]->flags & ~creation_flags; + case F_SETFL: + m_open_files[fd]->flags |= extra & ~(O_ACCMODE | creation_flags); + return 0; + default: + break; + } + + return BAN::Error::from_errno(ENOTSUP); + } + BAN::ErrorOr OpenFileDescriptorSet::seek(int fd, off_t offset, int whence) { TRY(validate_fd(fd)); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 753ab5d5..9bafe0cf 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -669,6 +669,12 @@ namespace Kernel return TRY(m_open_file_descriptors.dup2(fildes, fildes2)); } + BAN::ErrorOr Process::sys_fcntl(int fildes, int cmd, int extra) + { + LockGuard _(m_lock); + return TRY(m_open_file_descriptors.fcntl(fildes, cmd, extra)); + } + BAN::ErrorOr Process::sys_seek(int fd, off_t offset, int whence) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index fd9df89a..c919c39d 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -179,6 +179,9 @@ namespace Kernel case SYS_SET_PGID: ret = Process::current().sys_setpgid((pid_t)arg1, (pid_t)arg2); break; + case SYS_FCNTL: + ret = Process::current().sys_fcntl((int)arg1, (int)arg2, (int)arg3); + break; default: dwarnln("Unknown syscall {}", syscall); break; diff --git a/libc/fcntl.cpp b/libc/fcntl.cpp index 429f6480..4a796461 100644 --- a/libc/fcntl.cpp +++ b/libc/fcntl.cpp @@ -23,3 +23,13 @@ int openat(int fd, const char* path, int oflag, ...) return syscall(SYS_OPENAT, fd, path, oflag, mode); } + +int fcntl(int fildes, int cmd, ...) +{ + va_list args; + va_start(args, cmd); + int extra = va_arg(args, int); + va_end(args); + + return syscall(SYS_FCNTL, fildes, cmd, extra); +} \ No newline at end of file diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 25ba52dc..ae177acd 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -50,6 +50,7 @@ __BEGIN_DECLS #define SYS_GET_PID 43 #define SYS_GET_PGID 44 #define SYS_SET_PGID 45 +#define SYS_FCNTL 46 __END_DECLS