kernel+libc: Add all variants of utime
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-08-08 14:14:35 +02:00
parent 1481a4736a
commit a92077d311
Signed by: apio
GPG Key ID: B8A7D06E42258954
9 changed files with 171 additions and 1 deletions

View File

@ -4,9 +4,11 @@
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include <bits/atfile.h>
#include <bits/fcntl.h>
#include <bits/open-flags.h>
#include <bits/seek.h>
#include <bits/utime.h>
#include <luna/SafeArithmetic.h>
#include <sys/types.h>
@ -262,3 +264,52 @@ Result<u64> sys_ftruncate(Registers*, SyscallArgs args)
return 0;
}
Result<u64> sys_utimensat(Registers*, SyscallArgs args)
{
int dirfd = (int)args[0];
auto path = TRY(MemoryManager::strdup_from_user(args[1]));
const auto* times = (const struct timespec*)args[2];
int flags = (int)args[3];
auto* current = Scheduler::current();
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
struct timespec ktimes[2];
ktimes[0].tv_sec = ktimes[1].tv_sec = 0;
ktimes[0].tv_nsec = ktimes[1].tv_nsec = UTIME_NOW;
if (times && !MemoryManager::copy_from_user(times, ktimes, sizeof(ktimes))) return err(EFAULT);
// No permission checks are performed, since no actual modification is done, but the above checks are still
// performed.
if (ktimes[0].tv_nsec == UTIME_OMIT && ktimes[1].tv_nsec == UTIME_OMIT) return 0;
bool allow_write_access = ktimes[0].tv_nsec == UTIME_NOW && ktimes[1].tv_nsec == UTIME_NOW;
if (allow_write_access)
{
if (!VFS::can_write(inode, current->auth) && current->auth.euid != inode->metadata().uid &&
current->auth.euid != 0)
return err(EACCES);
}
else if (current->auth.euid != inode->metadata().uid && current->auth.euid != 0)
return err(EPERM);
auto metadata = inode->metadata();
if (ktimes[0].tv_nsec != UTIME_OMIT)
{
if (ktimes[0].tv_nsec == UTIME_NOW) metadata.atime = *Timer::realtime_clock();
if (ktimes[0].tv_nsec < 0 || ktimes[0].tv_nsec > 999'999'999) return err(EINVAL);
metadata.atime = ktimes[0];
}
if (ktimes[1].tv_nsec != UTIME_OMIT)
{
if (ktimes[1].tv_nsec == UTIME_NOW) metadata.mtime = *Timer::realtime_clock();
if (ktimes[1].tv_nsec < 0 || ktimes[1].tv_nsec > 999'999'999) return err(EINVAL);
metadata.mtime = ktimes[1];
}
TRY(inode->set_metadata(metadata));
return 0;
}

View File

@ -23,6 +23,7 @@ set(SOURCES
src/scanf.cpp
src/signal.cpp
src/termios.cpp
src/utime.cpp
src/sys/stat.cpp
src/sys/mman.cpp
src/sys/wait.cpp

View File

@ -0,0 +1,9 @@
/* bits/utime.h: Definitions for UTIME_NOW and UTIME_OMIT. */
#ifndef _BITS_UTIME_H
#define _BITS_UTIME_H
#define UTIME_NOW -1
#define UTIME_OMIT -2
#endif

View File

@ -5,6 +5,8 @@
#include <bits/modes.h>
#include <bits/struct_stat.h>
#include <bits/timespec.h>
#include <bits/utime.h>
#include <sys/types.h>
#ifdef __cplusplus
@ -41,6 +43,12 @@ extern "C"
/* Change the process's file creation mask. */
mode_t umask(mode_t mask);
/* Change a file's access and modification timestamps, with nanosecond precision. */
int utimensat(int dirfd, const char* path, const struct timespec times[2], int flags);
/* Change a file's access and modification timestamps, with nanosecond precision. */
int futimens(int fd, const struct timespec times[2], int flags);
#ifdef __cplusplus
}
#endif

View File

@ -16,6 +16,15 @@ extern "C"
/* Get the current time of day. */
__deprecated int gettimeofday(struct timeval* tp, void* timezone);
/* Change a file's access and modification timestamps, with microsecond precision. */
int utimes(const char* path, const struct timeval buf[2]);
/* Change a file descriptor's access and modification timestamps, with microsecond precision. */
int futimes(int fd, const struct timeval buf[2]);
/* Change a symlink's access and modification timestamps, with microsecond precision. */
int lutimes(const char* path, const struct timeval buf[2]);
#ifdef __cplusplus
}
#endif

26
libc/include/utime.h Normal file
View File

@ -0,0 +1,26 @@
/* utime.h: The utime function. */
#ifndef _UTIME_H
#define _UTIME_H
#include <sys/types.h>
struct utimbuf
{
time_t actime;
time_t modtime;
};
#ifdef __cplusplus
extern "C"
{
#endif
/* Change a file's access and modification timestamps. */
int utime(const char* path, const struct utimbuf* buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -52,4 +52,15 @@ extern "C"
{
return (mode_t)syscall(SYS_umask, mask);
}
int utimensat(int dirfd, const char* path, const struct timespec* times, int flags)
{
long rc = syscall(SYS_utimensat, dirfd, path, times, flags);
__errno_return(rc, int);
}
int futimens(int fd, const struct timespec* times, int flags)
{
return utimensat(fd, "", times, flags | AT_EMPTY_PATH);
}
}

55
libc/src/utime.cpp Normal file
View File

@ -0,0 +1,55 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <utime.h>
extern "C"
{
int utime(const char* path, const struct utimbuf* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, 0);
struct timespec times[2] = {
{ .tv_sec = buf->actime, .tv_nsec = 0 },
{ .tv_sec = buf->modtime, .tv_nsec = 0 },
};
return utimensat(AT_FDCWD, path, times, 0);
}
int utimes(const char* path, const struct timeval* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, 0);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(AT_FDCWD, path, times, 0);
}
int futimes(int fd, const struct timeval* buf)
{
if (!buf) return utimensat(fd, "", nullptr, AT_EMPTY_PATH);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(fd, "", times, AT_EMPTY_PATH);
}
int lutimes(const char* path, const struct timeval* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, AT_SYMLINK_NOFOLLOW);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
}
}

View File

@ -8,7 +8,7 @@
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \
_e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \
_e(truncate) _e(ftruncate)
_e(truncate) _e(ftruncate) _e(utimensat)
enum Syscalls
{