diff --git a/Kernel/API/POSIX/fcntl.h b/Kernel/API/POSIX/fcntl.h index b28cefb678d..2a8bdfca5c6 100644 --- a/Kernel/API/POSIX/fcntl.h +++ b/Kernel/API/POSIX/fcntl.h @@ -46,6 +46,7 @@ extern "C" { #define AT_FDCWD -100 #define AT_SYMLINK_NOFOLLOW 0x100 +#define AT_REMOVEDIR 0x200 struct flock { short l_type; diff --git a/Kernel/Process.h b/Kernel/Process.h index 0f83fee862a..195ef0b3d91 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -354,7 +354,7 @@ public: ErrorOr sys$times(Userspace); ErrorOr sys$utime(Userspace pathname, size_t path_length, Userspace); ErrorOr sys$link(Userspace); - ErrorOr sys$unlink(Userspace pathname, size_t path_length); + ErrorOr sys$unlink(int dirfd, Userspace pathname, size_t path_length, int flags); ErrorOr sys$symlink(Userspace); ErrorOr sys$rmdir(Userspace pathname, size_t path_length); ErrorOr sys$mount(Userspace); diff --git a/Kernel/Syscalls/unlink.cpp b/Kernel/Syscalls/unlink.cpp index 80c89518dbe..582b1bea58b 100644 --- a/Kernel/Syscalls/unlink.cpp +++ b/Kernel/Syscalls/unlink.cpp @@ -10,12 +10,29 @@ namespace Kernel { -ErrorOr Process::sys$unlink(Userspace user_path, size_t path_length) +ErrorOr Process::sys$unlink(int dirfd, Userspace user_path, size_t path_length, int flags) { VERIFY_NO_PROCESS_BIG_LOCK(this) TRY(require_promise(Pledge::cpath)); auto path = TRY(get_syscall_path_argument(user_path, path_length)); - TRY(VirtualFileSystem::the().unlink(path->view(), current_directory())); + + if (flags & ~AT_REMOVEDIR) + return Error::from_errno(EINVAL); + + RefPtr base; + if (dirfd == AT_FDCWD) { + base = current_directory(); + } else { + auto base_description = TRY(open_file_description(dirfd)); + if (!base_description->custody()) + return Error::from_errno(EINVAL); + base = base_description->custody(); + } + + if (flags & AT_REMOVEDIR) + TRY(VirtualFileSystem::the().rmdir(path->view(), *base)); + else + TRY(VirtualFileSystem::the().unlink(path->view(), *base)); return 0; } diff --git a/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp b/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp index 7f10a25c6b0..fe90eff6575 100644 --- a/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp +++ b/Userland/DevTools/UserspaceEmulator/Emulator_syscalls.cpp @@ -362,7 +362,7 @@ int Emulator::virt$rmdir(FlatPtr path, size_t path_length) int Emulator::virt$unlink(FlatPtr path, size_t path_length) { auto buffer = mmu().copy_buffer_from_vm(path, path_length); - return syscall(SC_unlink, buffer.data(), buffer.size()); + return syscall(SC_unlink, AT_FDCWD, buffer.data(), buffer.size(), 0); } int Emulator::virt$symlink(FlatPtr params_addr) diff --git a/Userland/Libraries/LibC/unistd.cpp b/Userland/Libraries/LibC/unistd.cpp index f613be7a19d..cd88b63a901 100644 --- a/Userland/Libraries/LibC/unistd.cpp +++ b/Userland/Libraries/LibC/unistd.cpp @@ -644,7 +644,13 @@ int link(char const* old_path, char const* new_path) // https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html int unlink(char const* pathname) { - int rc = syscall(SC_unlink, pathname, strlen(pathname)); + return unlinkat(AT_FDCWD, pathname, 0); +} + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html +int unlinkat(int dirfd, char const* pathname, int flags) +{ + int rc = syscall(SC_unlink, dirfd, pathname, strlen(pathname), flags); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/Userland/Libraries/LibC/unistd.h b/Userland/Libraries/LibC/unistd.h index 8ce3ac92e4e..b6e56d9591d 100644 --- a/Userland/Libraries/LibC/unistd.h +++ b/Userland/Libraries/LibC/unistd.h @@ -92,6 +92,7 @@ int ttyname_r(int fd, char* buffer, size_t); off_t lseek(int fd, off_t, int whence); int link(char const* oldpath, char const* newpath); int unlink(char const* pathname); +int unlinkat(int dirfd, char const* pathname, int flags); int symlink(char const* target, char const* linkpath); int rmdir(char const* pathname); int dup(int old_fd); diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index 8ebc0c09623..92a6eaaee02 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -854,7 +854,7 @@ ErrorOr unlink(StringView path) return Error::from_errno(EFAULT); #ifdef __serenity__ - int rc = syscall(SC_unlink, path.characters_without_null_termination(), path.length()); + int rc = syscall(SC_unlink, AT_FDCWD, path.characters_without_null_termination(), path.length(), 0); HANDLE_SYSCALL_RETURN_VALUE("unlink"sv, rc, {}); #else String path_string = path;