Kernel/LibC: Implement utime* family functions
This patch adds *working* - utime - utimes - utimensat - futimens
This commit is contained in:
@@ -46,6 +46,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Kernel
|
||||
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
//virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
|
||||
@@ -119,6 +119,7 @@ namespace Kernel
|
||||
BAN::ErrorOr<void> truncate(size_t);
|
||||
BAN::ErrorOr<void> chmod(mode_t);
|
||||
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
||||
BAN::ErrorOr<void> utimens(const timespec[2]);
|
||||
BAN::ErrorOr<void> fsync();
|
||||
|
||||
// Select/Non blocking API
|
||||
@@ -165,6 +166,7 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> fsync_impl() = 0;
|
||||
|
||||
// Select/Non blocking API
|
||||
|
||||
@@ -47,6 +47,8 @@ namespace Kernel
|
||||
protected:
|
||||
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> utimens_impl(const timespec[2]) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
void sync();
|
||||
@@ -75,7 +77,6 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
@@ -98,7 +99,6 @@ namespace Kernel
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(ENODEV); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
|
||||
virtual bool can_read_impl() const override { return false; }
|
||||
virtual bool can_write_impl() const override { return false; }
|
||||
|
||||
@@ -116,6 +116,7 @@ namespace Kernel
|
||||
|
||||
BAN::ErrorOr<long> sys_fchmodat(int fd, const char* path, mode_t mode, int flag);
|
||||
BAN::ErrorOr<long> sys_fchownat(int fd, const char* path, uid_t uid, gid_t gid, int flag);
|
||||
BAN::ErrorOr<long> sys_utimensat(int fd, const char* path, const struct timespec times[2], int flag);
|
||||
|
||||
BAN::ErrorOr<long> sys_socket(int domain, int type, int protocol);
|
||||
BAN::ErrorOr<long> sys_socketpair(int domain, int type, int protocol, int socket_vector[2]);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <kernel/FS/Ext2/Inode.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -287,6 +289,28 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::utimens_impl(const timespec times[2])
|
||||
{
|
||||
const uint32_t old_times[2] {
|
||||
m_inode.atime,
|
||||
m_inode.mtime,
|
||||
};
|
||||
|
||||
if (times[0].tv_nsec != UTIME_OMIT)
|
||||
m_inode.atime = times[0].tv_sec;
|
||||
if (times[1].tv_nsec != UTIME_OMIT)
|
||||
m_inode.mtime = times[1].tv_sec;
|
||||
|
||||
if (auto ret = sync(); ret.is_error())
|
||||
{
|
||||
m_inode.atime = old_times[0];
|
||||
m_inode.mtime = old_times[1];
|
||||
return ret.release_error();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
||||
{
|
||||
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
||||
|
||||
@@ -231,6 +231,12 @@ namespace Kernel
|
||||
return chown_impl(uid, gid);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::utimens(const timespec times[2])
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
return utimens_impl(times);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::fsync()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <kernel/FS/TmpFS/Inode.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
@@ -90,6 +92,23 @@ namespace Kernel
|
||||
m_fs.delete_inode(ino());
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpInode::chmod_impl(mode_t new_mode)
|
||||
{
|
||||
ASSERT(!(new_mode & Mode::TYPE_MASK));
|
||||
m_inode_info.mode &= ~Mode::TYPE_MASK;
|
||||
m_inode_info.mode |= new_mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpInode::utimens_impl(const timespec times[2])
|
||||
{
|
||||
if (times[0].tv_nsec != UTIME_OMIT)
|
||||
m_inode_info.atime = times[0];
|
||||
if (times[1].tv_nsec != UTIME_OMIT)
|
||||
m_inode_info.atime = times[1];
|
||||
return {};
|
||||
}
|
||||
|
||||
void TmpInode::sync()
|
||||
{
|
||||
m_fs.write_inode(m_ino, m_inode_info);
|
||||
@@ -219,12 +238,6 @@ namespace Kernel
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpFileInode::chmod_impl(mode_t new_mode)
|
||||
{
|
||||
m_inode_info.mode = new_mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
/* SOCKET INODE */
|
||||
BAN::ErrorOr<BAN::RefPtr<TmpSocketInode>> TmpSocketInode::create_new(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
@@ -248,12 +261,6 @@ namespace Kernel
|
||||
{
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> TmpSocketInode::chmod_impl(mode_t new_mode)
|
||||
{
|
||||
m_inode_info.mode = new_mode;
|
||||
return {};
|
||||
}
|
||||
|
||||
/* SYMLINK INODE */
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<TmpSymlinkInode>> TmpSymlinkInode::create_new(TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid, BAN::StringView target)
|
||||
|
||||
@@ -1262,6 +1262,56 @@ namespace Kernel
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_utimensat(int fd, const char* path, const struct timespec _times[2], int flag)
|
||||
{
|
||||
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (flag == AT_SYMLINK_NOFOLLOW)
|
||||
flag = O_NOFOLLOW;
|
||||
|
||||
timespec times[2];
|
||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||
times[0] = times[1] = timespec {
|
||||
.tv_sec = static_cast<time_t>(current_ns / 1'000'000),
|
||||
.tv_nsec = static_cast<long>(current_ns % 1'000'000),
|
||||
};
|
||||
|
||||
if (_times)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_pointer_access(_times, sizeof(timespec) * 2, false));
|
||||
if (_times[0].tv_nsec != UTIME_NOW)
|
||||
{
|
||||
times[0] = _times[0];
|
||||
if (auto ns = times[0].tv_nsec; ns != UTIME_OMIT && (ns < 0 || ns >= 1'000'000'000))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
if (_times[1].tv_nsec != UTIME_NOW)
|
||||
{
|
||||
times[1] = _times[1];
|
||||
if (auto ns = times[1].tv_nsec; ns != UTIME_OMIT && (ns < 0 || ns >= 1'000'000'000))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
|
||||
return 0;
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
auto inode = TRY(find_file(fd, path, flag)).inode;
|
||||
|
||||
if (!m_credentials.is_superuser() && inode->uid() != m_credentials.euid())
|
||||
{
|
||||
dwarnln("cannot chmod uid {} vs {}", inode->uid(), m_credentials.euid());
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
TRY(inode->utimens(times));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_socket(int domain, int type, int protocol)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
Reference in New Issue
Block a user