mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:34:57 +00:00
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.
This commit is contained in:
parent
cbf78975f1
commit
d05d938e73
3 changed files with 42 additions and 7 deletions
18
Userland/Libraries/LibC/bits/utimens.h
Normal file
18
Userland/Libraries/LibC/bits/utimens.h
Normal file
|
@ -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
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <bits/pthread_cancel.h>
|
||||
#include <bits/utimens.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
@ -127,12 +128,19 @@ 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);
|
||||
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.
|
||||
if (flag & ~AT_SYMLINK_NOFOLLOW) {
|
||||
|
@ -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, ¶ms);
|
||||
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, ¶ms);
|
||||
} else {
|
||||
Syscall::SC_futimens_params params { fd, times };
|
||||
rc = syscall(SC_futimens, ¶ms);
|
||||
}
|
||||
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue