mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 04:27:45 +00:00
Kernel+LibC+VFS: Implement utimensat(3)
Create POSIX utimensat() library call and corresponding system call to update file access and modification times.
This commit is contained in:
parent
7550017f97
commit
9a6bd85924
10 changed files with 146 additions and 0 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <time.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -102,4 +103,50 @@ int posix_fadvise(int fd, off_t offset, off_t len, int advice)
|
|||
(void)advice;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/utimensat.html
|
||||
int utimensat(int dirfd, char const* path, struct timespec const times[2], int flag)
|
||||
{
|
||||
if (!path) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t 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) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return early without error since both changes are to be omitted.
|
||||
if (times && times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
|
||||
return 0;
|
||||
|
||||
// According to POSIX, when times is a nullptr, it's equivalent to setting
|
||||
// both last access time and last modification time to the current time.
|
||||
// Setting the times argument to nullptr if it matches this case prevents
|
||||
// the need to copy it in the kernel.
|
||||
if (times && times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW)
|
||||
times = nullptr;
|
||||
|
||||
if (times) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if ((times[i].tv_nsec != UTIME_NOW && times[i].tv_nsec != UTIME_OMIT)
|
||||
&& (times[i].tv_nsec < 0 || times[i].tv_nsec >= 1'000'000'000L)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Syscall::SC_utimensat_params params { dirfd, { path, path_length }, times, flag };
|
||||
int rc = syscall(SC_utimensat, ¶ms);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue