Sfoglia il codice sorgente

LibC: Properly implement the futimens function

Use the new futimens syscall to ensure futimens can actually work.
This change for example allows a user to run "touch non-existing-file"
without getting any error, as expected.
Liav A 2 anni fa
parent
commit
d05d938e73

+ 18 - 0
Userland/Libraries/LibC/bits/utimens.h

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/API/POSIX/fcntl.h>
+#include <Kernel/API/POSIX/sys/stat.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+int __utimens(int fd, char const* path, struct timespec const times[2], int flag);
+
+__END_DECLS

+ 22 - 6
Userland/Libraries/LibC/fcntl.cpp

@@ -6,6 +6,7 @@
  */
 
 #include <bits/pthread_cancel.h>
+#include <bits/utimens.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
@@ -127,11 +128,18 @@ int utimensat(int dirfd, char const* path, struct timespec const times[2], int f
         errno = EFAULT;
         return -1;
     }
+    return __utimens(dirfd, path, times, flag);
+}
 
-    size_t path_length = strlen(path);
-    if (path_length > INT32_MAX) {
-        errno = EINVAL;
-        return -1;
+int __utimens(int fd, char const* path, struct timespec const times[2], int flag)
+{
+    size_t path_length = 0;
+    if (path) {
+        path_length = strlen(path);
+        if (path_length > INT32_MAX) {
+            errno = EINVAL;
+            return -1;
+        }
     }
 
     // POSIX allows AT_SYMLINK_NOFOLLOW flag or no flags.
@@ -161,8 +169,16 @@ int utimensat(int dirfd, char const* path, struct timespec const times[2], int f
         }
     }
 
-    Syscall::SC_utimensat_params params { dirfd, { path, path_length }, times, flag };
-    int rc = syscall(SC_utimensat, &params);
+    int rc = 0;
+    if (path) {
+        // NOTE: fd is treated as dirfd for this syscall.
+        Syscall::SC_utimensat_params params { fd, { path, path_length }, times, flag };
+        rc = syscall(SC_utimensat, &params);
+    } else {
+        Syscall::SC_futimens_params params { fd, times };
+        rc = syscall(SC_futimens, &params);
+    }
+
     __RETURN_WITH_ERRNO(rc, rc, -1);
 }
 }

+ 2 - 1
Userland/Libraries/LibC/stat.cpp

@@ -5,6 +5,7 @@
  */
 
 #include <assert.h>
+#include <bits/utimens.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -119,6 +120,6 @@ int fstatat(int fd, char const* path, struct stat* statbuf, int flags)
 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
 int futimens(int fd, struct timespec const times[2])
 {
-    return utimensat(fd, "", times, 0);
+    return __utimens(fd, nullptr, times, 0);
 }
 }