diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index a2a4ec0e..f62735ad 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -30,6 +30,8 @@ extern syscall_mkdirat extern syscall_clockget extern syscall_linkat extern syscall_readlinkat +extern syscall_fchmod +extern syscall_fchmodat syscalltab: dq syscall_print dq syscall_mmap @@ -62,7 +64,9 @@ dq syscall_mkdirat dq syscall_clockget dq syscall_linkat dq syscall_readlinkat -syscallcount equ 31 +dq syscall_fchmod +dq syscall_fchmodat +syscallcount equ 33 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index 8a768886..c5095163 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -4,7 +4,7 @@ #ifdef SYSCALL_LOGGING -#define SYSCALL_COUNT 30 +#define SYSCALL_COUNT 33 #define LOGSTR(x) arch_e9_puts(x) static char *name[] = { @@ -38,7 +38,9 @@ static char *name[] = { "mkdirat", "clockget", "linkat", - "readlinkat" + "readlinkat", + "fchmod", + "fchmodat" }; static char *args[] = { @@ -72,7 +74,9 @@ static char *args[] = { "dirfd %d path %s mode %o", // mkdirat "clockid %d timespec %p", // clockget "olddirfd %d oldpath %s newdirfd %d oldpath %s flags %d type %d", // linkat - "dirfd %d path %s buffer %p buffer length %lu" // readlinkat + "dirfd %d path %s buffer %p buffer length %lu", // readlinkat + "fd %d mode %o", // fchmod + "dirfd %d path %s mode %o flags %d" // fchmodat }; #endif diff --git a/kernel-src/sys/syscalls/chmod.c b/kernel-src/sys/syscalls/chmod.c new file mode 100644 index 00000000..446e92dc --- /dev/null +++ b/kernel-src/sys/syscalls/chmod.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include + +static int dochmod(vnode_t *node, mode_t mode) { + vattr_t attr; + cred_t *cred = &_cpu()->thread->proc->cred; + int e = VOP_GETATTR(node, &attr, cred); + if (e) + return e; + + attr.mode = mode; + + return VOP_SETATTR(node, &attr, cred); +} + +syscallret_t syscall_fchmodat(context_t *, int dirfd, const char *upath, mode_t mode, int flags) { + syscallret_t ret = { + .ret = -1 + }; + + char *path = alloc(strlen(upath) + 1); + if (path == NULL) { + ret.errno = ENOMEM; + return ret; + } + + strcpy(path, upath); + + file_t *file = NULL; + vnode_t *dirnode = NULL; + vnode_t *node = NULL; + ret.errno = dirfd_enter(path, dirfd, &file, &dirnode); + if (ret.errno) + goto cleanup; + + ret.errno = vfs_lookup(&node, dirnode, path, NULL, (flags & AT_SYMLINK_NOFOLLOW) ? VFS_LOOKUP_NOLINK : 0); + if (ret.errno) + goto cleanup; + + ret.errno = dochmod(node, mode); + ret.ret = ret.errno ? -1 : 0; + + cleanup: + + if (node) + VOP_RELEASE(node); + + if (dirnode) + dirfd_leave(dirnode, file); + + free(path); + + return ret; +} + +syscallret_t syscall_fchmod(context_t *, int fd, mode_t mode) { + syscallret_t ret = { + .ret = -1 + }; + + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + return ret; + } + + ret.errno = dochmod(file->vnode, mode); + ret.ret = ret.errno ? -1 : 0; + + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index aa212761..de4879e5 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -133,10 +133,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..90bfad3 +index 0000000..569f811 --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,329 @@ +@@ -0,0 +1,343 @@ +#include +#include +#include @@ -211,6 +211,20 @@ index 0000000..90bfad3 + return 0; + } + ++ int sys_fchmod(int fd, mode_t mode) { ++ long ret; ++ return syscall(SYSCALL_FCHMOD, &ret, fd, mode); ++ } ++ ++ int sys_fchmodat(int fd, const char *pathname, mode_t mode, int flags) { ++ long ret; ++ return syscall(SYSCALL_FCHMODAT, &ret, fd, (uint64_t)pathname, mode, flags); ++ } ++ ++ int sys_chmod(const char *pathname, mode_t mode) { ++ return sys_fchmodat(AT_FDCWD, pathname, mode, 0); ++ } ++ + int sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length) { + long ret; + long error = syscall(SYSCALL_READLINKAT, &ret, AT_FDCWD, (uint64_t)path, (uint64_t)buffer, max_size); @@ -485,10 +499,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..fa60d43 +index 0000000..d058baa --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,54 @@ +@@ -0,0 +1,56 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -523,6 +537,8 @@ index 0000000..fa60d43 +#define SYSCALL_CLOCKGET 28 +#define SYSCALL_LINKAT 29 +#define SYSCALL_READLINKAT 30 ++#define SYSCALL_FCHMOD 31 ++#define SYSCALL_FCHMODAT 32 + +#include +#include