2020-01-18 11:38:21 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
2021-05-09 20:09:30 +03:00
|
|
|
* Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
|
2020-01-18 11:38:21 +03:00
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2022-06-12 16:15:09 +03:00
|
|
|
#include <bits/pthread_cancel.h>
|
2023-04-08 11:39:28 +03:00
|
|
|
#include <bits/utimens.h>
|
2018-11-11 12:38:33 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
2021-08-14 16:36:26 +03:00
|
|
|
#include <limits.h>
|
2018-11-11 12:38:33 +03:00
|
|
|
#include <stdarg.h>
|
2019-11-16 19:08:11 +03:00
|
|
|
#include <string.h>
|
2021-02-05 14:16:30 +03:00
|
|
|
#include <syscall.h>
|
2022-05-02 23:26:10 +03:00
|
|
|
#include <time.h>
|
2018-11-11 12:38:33 +03:00
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
int fcntl(int fd, int cmd, ...)
|
|
|
|
{
|
2022-06-12 16:15:09 +03:00
|
|
|
__pthread_maybe_cancel();
|
|
|
|
|
2018-11-11 12:38:33 +03:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, cmd);
|
2022-07-03 02:02:45 +03:00
|
|
|
uintptr_t extra_arg = va_arg(ap, uintptr_t);
|
2018-12-21 05:02:06 +03:00
|
|
|
int rc = syscall(SC_fcntl, fd, cmd, extra_arg);
|
2020-08-17 03:40:07 +03:00
|
|
|
va_end(ap);
|
2018-11-11 12:38:33 +03:00
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
|
|
|
}
|
2019-07-22 21:01:11 +03:00
|
|
|
|
2021-05-09 20:09:30 +03:00
|
|
|
int create_inode_watcher(unsigned flags)
|
2019-07-22 21:01:11 +03:00
|
|
|
{
|
2021-05-09 20:09:30 +03:00
|
|
|
int rc = syscall(SC_create_inode_watcher, flags);
|
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
|
|
|
}
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
int inode_watcher_add_watch(int fd, char const* path, size_t path_length, unsigned event_mask)
|
2021-05-09 20:09:30 +03:00
|
|
|
{
|
2021-09-16 09:37:39 +03:00
|
|
|
Syscall::SC_inode_watcher_add_watch_params params { { path, path_length }, fd, event_mask };
|
2021-05-09 20:09:30 +03:00
|
|
|
int rc = syscall(SC_inode_watcher_add_watch, ¶ms);
|
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int inode_watcher_remove_watch(int fd, int wd)
|
|
|
|
{
|
|
|
|
int rc = syscall(SC_inode_watcher_remove_watch, fd, wd);
|
2019-07-22 21:01:11 +03:00
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
|
|
|
}
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
int creat(char const* path, mode_t mode)
|
2019-11-16 19:08:11 +03:00
|
|
|
{
|
2022-06-12 16:15:09 +03:00
|
|
|
__pthread_maybe_cancel();
|
|
|
|
|
2019-11-16 19:08:11 +03:00
|
|
|
return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
|
|
|
|
}
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
int open(char const* path, int options, ...)
|
2019-11-16 19:08:11 +03:00
|
|
|
{
|
2022-06-12 16:15:09 +03:00
|
|
|
__pthread_maybe_cancel();
|
|
|
|
|
2020-01-11 14:47:47 +03:00
|
|
|
if (!path) {
|
|
|
|
errno = EFAULT;
|
|
|
|
return -1;
|
|
|
|
}
|
2021-01-12 21:21:59 +03:00
|
|
|
auto path_length = strlen(path);
|
2019-11-16 19:08:11 +03:00
|
|
|
if (path_length > INT32_MAX) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, options);
|
|
|
|
auto mode = (mode_t)va_arg(ap, unsigned);
|
|
|
|
va_end(ap);
|
2021-01-12 21:21:59 +03:00
|
|
|
Syscall::SC_open_params params { AT_FDCWD, { path, path_length }, options, mode };
|
|
|
|
int rc = syscall(SC_open, ¶ms);
|
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
2019-11-16 19:08:11 +03:00
|
|
|
}
|
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
int openat(int dirfd, char const* path, int options, ...)
|
2019-11-16 19:08:11 +03:00
|
|
|
{
|
2022-06-12 16:15:09 +03:00
|
|
|
__pthread_maybe_cancel();
|
|
|
|
|
2019-11-16 19:08:11 +03:00
|
|
|
if (!path) {
|
|
|
|
errno = EFAULT;
|
|
|
|
return -1;
|
|
|
|
}
|
2021-01-12 21:21:59 +03:00
|
|
|
auto path_length = strlen(path);
|
|
|
|
if (path_length > INT32_MAX) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
2019-11-16 19:08:11 +03:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, options);
|
|
|
|
auto mode = (mode_t)va_arg(ap, unsigned);
|
|
|
|
va_end(ap);
|
2021-01-12 21:21:59 +03:00
|
|
|
Syscall::SC_open_params params { dirfd, { path, path_length }, options, mode };
|
|
|
|
int rc = syscall(SC_open, ¶ms);
|
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
2019-11-16 19:08:11 +03:00
|
|
|
}
|
2022-04-29 21:54:43 +03:00
|
|
|
|
|
|
|
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html
|
|
|
|
int posix_fadvise(int fd, off_t offset, off_t len, int advice)
|
|
|
|
{
|
|
|
|
// Per POSIX:
|
|
|
|
// "The posix_fadvise() function shall have no effect on the semantics of other operations on the specified data,
|
|
|
|
// although it may affect the performance of other operations."
|
|
|
|
|
|
|
|
// For now, we simply ignore posix_fadvise() requests. In the future we may use them to optimize performance.
|
|
|
|
(void)fd;
|
|
|
|
(void)offset;
|
|
|
|
(void)len;
|
|
|
|
(void)advice;
|
|
|
|
return 0;
|
|
|
|
}
|
2022-05-02 23:26:10 +03:00
|
|
|
|
2022-06-18 19:37:54 +03:00
|
|
|
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html
|
|
|
|
int posix_fallocate(int fd, off_t offset, off_t len)
|
|
|
|
{
|
|
|
|
// posix_fallocate does not set errno.
|
2023-08-11 11:47:31 +03:00
|
|
|
return -static_cast<int>(syscall(SC_posix_fallocate, fd, offset, len));
|
2022-06-18 19:37:54 +03:00
|
|
|
}
|
|
|
|
|
2022-05-02 23:26:10 +03:00
|
|
|
// 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;
|
|
|
|
}
|
2023-04-08 11:39:28 +03:00
|
|
|
return __utimens(dirfd, path, times, flag);
|
|
|
|
}
|
2022-05-02 23:26:10 +03:00
|
|
|
|
2023-04-08 11:39:28 +03:00
|
|
|
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;
|
|
|
|
}
|
2022-05-02 23:26:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-08 11:39:28 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-05-02 23:26:10 +03:00
|
|
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
|
|
|
}
|
2018-11-11 12:38:33 +03:00
|
|
|
}
|