From 712aa9fbc0619a8bed62271705c4930f69c3d85a Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 7 Sep 2023 15:47:11 -0300 Subject: [PATCH] kernel: utime syscall --- kernel-src/sys/syscalls/utime.c | 76 +++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 kernel-src/sys/syscalls/utime.c diff --git a/kernel-src/sys/syscalls/utime.c b/kernel-src/sys/syscalls/utime.c new file mode 100644 index 00000000..5d03346d --- /dev/null +++ b/kernel-src/sys/syscalls/utime.c @@ -0,0 +1,76 @@ +#include +#include +#include + +syscallret_t syscall_utimensat(context_t *, int fd, char *upath, timespec_t uts[2], int flags) { + // TODO + // uts -> NULL -> current time + // upath -> NULL -> dirfd points to vnode + syscallret_t ret = { + .ret = -1 + }; + + timespec_t ts[2]; + if (uts == NULL) + memcpy(ts, uts, sizeof(timespec_t) * 2); + else + ts[0] = ts[1] = timekeeper_time(); + + vnode_t *node = NULL; + vnode_t *dirnode = NULL; + file_t *file = NULL; + char *path = NULL; + + if (upath == NULL) { + // operation is done on the file pointed to by fd + file_t *file = fd_get(fd); + if (file == NULL) { + ret.errno = EBADF; + goto cleanup; + } + + node = file->vnode; + VOP_HOLD(node); + fd_release(file); + } else { + // operation is done on the file pointed to by the path relative to fd + path = alloc(strlen(upath) + 1); + if (path == NULL) { + ret.errno = ENOMEM; + goto cleanup; + } + + strcpy(path, upath); + ret.errno = dirfd_enter(path, fd, &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; + } + + // XXX race condition with other system calls + vattr_t attr; + ret.errno = VOP_GETATTR(node, &attr, &_cpu()->thread->proc->cred); + if (ret.errno) + goto cleanup; + + attr.atime = ts[0]; + attr.mtime = ts[1]; + + ret.errno = VOP_SETATTR(node, &attr, &_cpu()->thread->proc->cred); + ret.ret = ret.errno ? -1 : 0; + + cleanup: + if (node) + VOP_RELEASE(node); + + if (dirnode) + dirfd_leave(dirnode, file); + + if (path) + free(path); + + return ret; +}