Kernel/LibC: Implement `readlink` in terms of `readlinkat`

This commit is contained in:
Bananymous 2024-09-17 16:38:15 +03:00
parent f1a4bbce53
commit 3666525d24
4 changed files with 18 additions and 29 deletions

View File

@ -109,8 +109,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_access(const char* path, int amode); BAN::ErrorOr<long> sys_access(const char* path, int amode);
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t); BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
BAN::ErrorOr<long> sys_unlink(const char*); BAN::ErrorOr<long> sys_unlink(const char*);
BAN::ErrorOr<long> readlink_impl(BAN::RefPtr<Inode>, char* buffer, size_t bufsize);
BAN::ErrorOr<long> sys_readlink(const char* path, char* buffer, size_t bufsize);
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize); BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset); BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);

View File

@ -994,37 +994,28 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::readlink_impl(BAN::RefPtr<Inode> inode, char* buffer, size_t bufsize)
{
// FIXME: no allocation needed
auto link_target = TRY(inode->link_target());
size_t byte_count = BAN::Math::min<size_t>(link_target.size(), bufsize);
memcpy(buffer, link_target.data(), byte_count);
return byte_count;
}
BAN::ErrorOr<long> Process::sys_readlink(const char* path, char* buffer, size_t bufsize)
{
LockGuard _(m_process_lock);
TRY(validate_string_access(path));
TRY(validate_pointer_access(buffer, bufsize, true));
auto absolute_path = TRY(absolute_path_of(path));
auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_NOFOLLOW | O_RDONLY));
return readlink_impl(file.inode, buffer, bufsize);
}
BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize) BAN::ErrorOr<long> Process::sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
TRY(validate_string_access(path)); TRY(validate_string_access(path));
TRY(validate_pointer_access(buffer, bufsize, true)); TRY(validate_pointer_access(buffer, bufsize, true));
auto parent_file = TRY(m_open_file_descriptors.file_of(fd)); VirtualFileSystem::File parent_file;
auto file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, O_NOFOLLOW | O_RDONLY)); if (path[0] == '/')
return readlink_impl(file.inode, buffer, bufsize); parent_file = VirtualFileSystem::get().root_file();
else if (fd == AT_FDCWD)
parent_file = TRY(m_working_directory.clone());
else
parent_file = TRY(m_open_file_descriptors.file_of(fd));
auto inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, O_NOFOLLOW | O_RDONLY)).inode;
// FIXME: no allocation needed
auto link_target = TRY(inode->link_target());
const size_t byte_count = BAN::Math::min<size_t>(link_target.size(), bufsize);
memcpy(buffer, link_target.data(), byte_count);
return byte_count;
} }
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset) BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)

View File

@ -55,7 +55,6 @@ __BEGIN_DECLS
O(SYS_FCHMOD, fchmod) \ O(SYS_FCHMOD, fchmod) \
O(SYS_CREATE_DIR, create_dir) \ O(SYS_CREATE_DIR, create_dir) \
O(SYS_UNLINK, unlink) \ O(SYS_UNLINK, unlink) \
O(SYS_READLINK, readlink) \
O(SYS_READLINKAT, readlinkat) \ O(SYS_READLINKAT, readlinkat) \
O(SYS_MSYNC, msync) \ O(SYS_MSYNC, msync) \
O(SYS_PREAD, pread) \ O(SYS_PREAD, pread) \

View File

@ -3,6 +3,7 @@
#include <kernel/Syscall.h> #include <kernel/Syscall.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -86,7 +87,7 @@ ssize_t write(int fildes, const void* buf, size_t nbyte)
ssize_t readlink(const char* __restrict path, char* __restrict buf, size_t bufsize) ssize_t readlink(const char* __restrict path, char* __restrict buf, size_t bufsize)
{ {
return syscall(SYS_READLINK, path, buf, bufsize); return readlinkat(AT_FDCWD, path, buf, bufsize);
} }
ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, size_t bufsize) ssize_t readlinkat(int fd, const char* __restrict path, char* __restrict buf, size_t bufsize)