kernel+libc+libos+ls: Add readlink()
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-05-23 15:42:38 +02:00
parent b61307e5cb
commit 1a6ad11462
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 71 additions and 5 deletions

View File

@ -85,6 +85,8 @@ Result<int> luna_main(int argc, char** argv)
struct stat st;
TRY(os::FileSystem::stat({ dirfd, file.view() }, st, false));
auto link = TRY(os::FileSystem::readlink({ dirfd, file.view() }));
StringView owner;
StringView group;
@ -92,14 +94,14 @@ Result<int> luna_main(int argc, char** argv)
if (!human_readable && !si)
{
os::println("%6o %u %4s %4s %10lu %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(),
st.st_size, file.chars());
os::println("%6o %u %4s %4s %10lu %s%s%s", st.st_mode, st.st_nlink, owner.chars(), group.chars(),
st.st_size, file.chars(), link.is_empty() ? "" : " -> ", link.chars());
}
else
{
auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false));
os::println("%6o %u %4s %4s %6s %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(),
size.chars(), file.chars());
os::println("%6o %u %4s %4s %6s %s%s%s", st.st_mode, st.st_nlink, owner.chars(), group.chars(),
size.chars(), file.chars(), link.is_empty() ? "" : " -> ", link.chars());
}
}
}

View File

@ -62,3 +62,29 @@ Result<u64> sys_symlinkat(Registers*, SyscallArgs args)
return 0;
}
Result<u64> sys_readlinkat(Registers*, SyscallArgs args)
{
int dirfd = (int)args[0];
auto path = TRY(MemoryManager::strdup_from_user(args[1]));
char* buf = (char*)args[2];
usize bufsiz = (usize)args[3];
auto* current = Scheduler::current();
auto symlink = TRY(current->resolve_atfile(dirfd, path, true, false));
if (symlink->type() != VFS::InodeType::Symlink) return err(EINVAL);
auto linkpath = TRY(symlink->readlink());
check(!linkpath.is_empty());
usize nread = linkpath.length();
if (nread > bufsiz) nread = bufsiz;
kdbgln("readlink: reading %zu bytes from symlink (%s)", nread, linkpath.chars());
if (!MemoryManager::copy_to_user(buf, linkpath.chars(), nread)) return err(EFAULT);
return nread;
}

View File

@ -139,6 +139,12 @@ extern "C"
/* Create a symbolic link relative to a file descriptor. */
int symlinkat(const char* target, int dirfd, const char* linkpath);
/* Read the contents of a symbolic link. */
ssize_t readlink(const char* path, char* buf, size_t max);
/* Read the contents of a symbolic link relative to a file descriptor. */
ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t max);
#ifdef __cplusplus
}
#endif

View File

@ -418,4 +418,16 @@ extern "C"
long rc = syscall(SYS_symlinkat, target, dirfd, linkpath);
__errno_return(rc, int);
}
ssize_t readlink(const char* path, char* buf, size_t max)
{
long rc = syscall(SYS_readlinkat, AT_FDCWD, path, buf, max);
__errno_return(rc, ssize_t);
}
ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t max)
{
long rc = syscall(SYS_readlinkat, dirfd, path, buf, max);
__errno_return(rc, ssize_t);
}
}

View File

@ -5,7 +5,7 @@
_e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat)
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat)
enum Syscalls
{

View File

@ -21,6 +21,8 @@ namespace os
Result<void> remove_tree(const Path& path);
Result<String> readlink(const Path& path);
Result<String> working_directory();
Result<String> home_directory();

View File

@ -2,6 +2,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <luna/PathParser.h>
#include <luna/String.h>
#include <os/Directory.h>
#include <os/FileSystem.h>
@ -68,6 +69,23 @@ namespace os::FileSystem
return remove(path);
}
Result<String> readlink(const Path& path)
{
struct stat st;
TRY(stat(path, st, false));
if (!S_ISLNK(st.st_mode)) return String {};
char* buf = TRY(make_array<char>(st.st_size + 1));
auto guard = make_scope_guard([buf] { delete[] buf; });
usize nread = TRY(
Result<usize>::from_syscall(syscall(SYS_readlinkat, path.dirfd(), path.name().chars(), buf, st.st_size)));
buf[nread] = '\0';
guard.deactivate();
return String { buf, nread };
}
Result<String> working_directory()
{
char* ptr = getcwd(NULL, 0);