libos: Add FileSystem::stat()
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-05-12 23:47:20 +02:00
parent 64d0f30bd9
commit 300d68088b
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 75 additions and 17 deletions

View File

@ -1,10 +1,59 @@
#include <fcntl.h>
#include <grp.h>
#include <os/ArgumentParser.h>
#include <os/Directory.h>
#include <os/File.h>
#include <os/FileSystem.h>
#include <stdio.h>
#include <sys/stat.h>
#include <pwd.h>
struct UsernameCache
{
uid_t uid;
String name;
};
struct GroupCache
{
gid_t gid;
String name;
};
Vector<UsernameCache> g_user_cache;
Vector<GroupCache> g_group_cache;
Result<void> find_user_and_group(struct stat& st, StringView& owner, StringView& group)
{
for (const auto& user : g_user_cache)
{
if (user.uid == st.st_uid) owner = user.name.view();
}
if (owner.is_empty())
{
auto* pw = getpwuid(st.st_uid);
if (!pw) owner = "???";
else
owner = pw->pw_name;
auto name = TRY(String::from_string_view(owner));
TRY(g_user_cache.try_append({ st.st_uid, move(name) }));
}
for (const auto& grp : g_group_cache)
{
if (grp.gid == st.st_gid) group = grp.name.view();
}
if (group.is_empty())
{
auto* grp = getgrgid(st.st_gid);
if (!grp) group = "???";
else
group = grp->gr_name;
auto name = TRY(String::from_string_view(group));
TRY(g_group_cache.try_append({ st.st_gid, move(name) }));
}
return {};
}
Result<int> luna_main(int argc, char** argv)
{
@ -56,13 +105,14 @@ Result<int> luna_main(int argc, char** argv)
for (const auto& file : files)
{
struct stat st;
if (fstatat(dirfd, file.chars(), &st, 0) < 0)
{
perror(file.chars());
return 1;
}
TRY(os::FileSystem::stat({ dirfd, file.view() }, st));
os::println("%6o %u %4u %4u %10lu %s", st.st_mode, st.st_nlink, st.st_uid, st.st_gid, st.st_size,
StringView owner;
StringView group;
TRY(find_user_and_group(st, owner, group));
os::println("%6o %u %4s %4s %10lu %s", st.st_mode, st.st_nlink, owner.chars(), group.chars(), st.st_size,
file.chars());
}
}

View File

@ -1,4 +1,5 @@
#include <os/ArgumentParser.h>
#include <os/FileSystem.h>
#include <stdio.h>
#include <sys/stat.h>
@ -24,11 +25,7 @@ Result<int> luna_main(int argc, char** argv)
parser.parse(argc, argv);
struct stat st;
if (stat(path.chars(), &st) < 0)
{
perror("stat");
return 1;
}
TRY(os::FileSystem::stat(path, st));
printf(" File: %s\n", path.chars());
printf(" Size: %zu (%s)\n", st.st_size, file_type(st.st_mode));

View File

@ -1,4 +1,5 @@
#pragma once
#include <bits/struct_stat.h>
#include <luna/Result.h>
#include <luna/StringView.h>
#include <os/Path.h>
@ -12,6 +13,8 @@ namespace os
bool is_directory(const Path& path);
Result<void> stat(const Path& path, struct stat& st);
Result<void> create_directory(StringView path, mode_t mode);
Result<void> remove(const Path& path);

View File

@ -1,3 +1,4 @@
#include <bits/modes.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@ -6,7 +7,6 @@
#include <os/FileSystem.h>
#include <pwd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>
@ -16,7 +16,7 @@ namespace os::FileSystem
{
struct stat st;
if (fstatat(path.dirfd(), path.name().chars(), &st, path.is_empty_path()) < 0) return false;
if (stat(path, st).has_error()) return false;
return true;
}
@ -25,11 +25,19 @@ namespace os::FileSystem
{
struct stat st;
if (fstatat(path.dirfd(), path.name().chars(), &st, path.is_empty_path()) < 0) return false;
if (stat(path, st).has_error()) return false;
return S_ISDIR(st.st_mode);
}
Result<void> stat(const Path& path, struct stat& st)
{
long rc =
syscall(SYS_fstatat, path.dirfd(), path.name().chars(), &st, path.is_empty_path() ? AT_EMPTY_PATH : 0);
return Result<void>::from_syscall(rc);
}
Result<void> create_directory(StringView path, mode_t mode)
{
long rc = syscall(SYS_mkdir, path.chars(), mode);