Browse Source

Kernel+LibC+LibCore: Implement the unlinkat(2) syscall

sin-ack 3 năm trước cách đây
mục cha
commit
bc7c8879c5

+ 1 - 0
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;

+ 1 - 1
Kernel/Process.h

@@ -354,7 +354,7 @@ public:
     ErrorOr<FlatPtr> sys$times(Userspace<tms*>);
     ErrorOr<FlatPtr> sys$utime(Userspace<char const*> pathname, size_t path_length, Userspace<const struct utimbuf*>);
     ErrorOr<FlatPtr> sys$link(Userspace<Syscall::SC_link_params const*>);
-    ErrorOr<FlatPtr> sys$unlink(Userspace<char const*> pathname, size_t path_length);
+    ErrorOr<FlatPtr> sys$unlink(int dirfd, Userspace<char const*> pathname, size_t path_length, int flags);
     ErrorOr<FlatPtr> sys$symlink(Userspace<Syscall::SC_symlink_params const*>);
     ErrorOr<FlatPtr> sys$rmdir(Userspace<char const*> pathname, size_t path_length);
     ErrorOr<FlatPtr> sys$mount(Userspace<Syscall::SC_mount_params const*>);

+ 19 - 2
Kernel/Syscalls/unlink.cpp

@@ -10,12 +10,29 @@
 
 namespace Kernel {
 
-ErrorOr<FlatPtr> Process::sys$unlink(Userspace<char const*> user_path, size_t path_length)
+ErrorOr<FlatPtr> Process::sys$unlink(int dirfd, Userspace<char const*> 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<Custody> 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;
 }
 

+ 1 - 1
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)

+ 7 - 1
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);
 }
 

+ 1 - 0
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);

+ 1 - 1
Userland/Libraries/LibCore/System.cpp

@@ -854,7 +854,7 @@ ErrorOr<void> 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;