From 13c9caa8561eb21ccd98cda3b9e6c4d59e53d90f Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 10 Apr 2023 19:56:03 +0200 Subject: [PATCH] kernel+libc: Add stat() + fstat() --- kernel/CMakeLists.txt | 1 + kernel/src/sys/stat.cpp | 60 +++++++++++++++++++++++++++++++++ libc/include/bits/modes.h | 8 +++-- libc/include/bits/struct_stat.h | 18 ++++++++++ libc/include/sys/stat.h | 12 +++++++ libc/include/sys/types.h | 1 + libc/src/sys/stat.cpp | 12 +++++++ libluna/include/luna/Syscall.h | 2 +- 8 files changed, 110 insertions(+), 4 deletions(-) create mode 100644 kernel/src/sys/stat.cpp create mode 100644 libc/include/bits/struct_stat.h diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index a924291f..b46efcc5 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -34,6 +34,7 @@ set(SOURCES src/sys/mknod.cpp src/sys/waitpid.cpp src/sys/getdents.cpp + src/sys/stat.cpp src/fs/VFS.cpp src/fs/tmpfs/FileSystem.cpp src/fs/devices/DeviceRegistry.cpp diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp new file mode 100644 index 00000000..782e1960 --- /dev/null +++ b/kernel/src/sys/stat.cpp @@ -0,0 +1,60 @@ +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "thread/Scheduler.h" +#include +#include + +static mode_t make_mode(mode_t mode, VFS::InodeType type) +{ + mode_t result = mode; + + switch (type) + { + case VFS::InodeType::RegularFile: result |= S_IFREG; break; + case VFS::InodeType::Directory: result |= S_IFDIR; break; + case VFS::InodeType::Device: result |= S_IFCHR; break; + default: break; + } + + return result; +} + +static Result do_stat(SharedPtr inode, stat* st) +{ + stat kstat; + + kstat.st_ino = inode->inode_number(); + kstat.st_mode = make_mode(inode->mode(), inode->type()); + kstat.st_nlink = 1; // FIXME: Count hard links to files. + kstat.st_uid = inode->uid(); + kstat.st_gid = inode->gid(); + kstat.st_size = inode->size(); + + if (!MemoryManager::copy_to_user_typed(st, &kstat)) return err(EFAULT); + + return 0; +} + +Result sys_stat(Registers*, SyscallArgs args) +{ + auto path = TRY(MemoryManager::strdup_from_user(args[0])); + stat* st = (stat*)args[1]; + + Thread* current = Scheduler::current(); + + auto inode = TRY(VFS::resolve_path(path.chars(), current->auth)); + + return do_stat(inode, st); +} + +Result sys_fstat(Registers*, SyscallArgs args) +{ + int fd = (int)args[0]; + stat* st = (stat*)args[1]; + + Thread* current = Scheduler::current(); + + auto descriptor = *TRY(current->resolve_fd(fd)); + + return do_stat(descriptor.inode, st); +} diff --git a/libc/include/bits/modes.h b/libc/include/bits/modes.h index cf9c572a..29c5520d 100644 --- a/libc/include/bits/modes.h +++ b/libc/include/bits/modes.h @@ -6,6 +6,11 @@ #define S_IFMT 070000 #define S_IFREG 000000 #define S_IFDIR 040000 +#define S_IFCHR 050000 + +#define S_ISREG(mode) ((mode)&S_IFMT == S_IFREG) +#define S_ISDIR(mode) ((mode)&S_IFMT == S_IFDIR) +#define S_ISCHR(mode) ((mode)&S_IFMT == S_IFCHR) #define S_IRWXU 0700 #define S_IRUSR 0400 @@ -23,7 +28,4 @@ #define S_ISGID 02000 #define S_ISVTX 01000 -#define S_ISREG(m) ((m & S_IFMT) == S_IFREG) -#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) - #endif diff --git a/libc/include/bits/struct_stat.h b/libc/include/bits/struct_stat.h new file mode 100644 index 00000000..8b53603e --- /dev/null +++ b/libc/include/bits/struct_stat.h @@ -0,0 +1,18 @@ +/* bits/struct_stat.h: The stat structure. */ + +#ifndef _BITS_STRUCT_STAT_H +#define _BITS_STRUCT_STAT_H + +#include + +struct stat +{ + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + off_t st_size; +}; + +#endif diff --git a/libc/include/sys/stat.h b/libc/include/sys/stat.h index 1b77922d..f6e76e04 100644 --- a/libc/include/sys/stat.h +++ b/libc/include/sys/stat.h @@ -4,6 +4,7 @@ #define _SYS_STAT_H #include +#include #include #ifdef __cplusplus @@ -17,6 +18,17 @@ extern "C" /* Create a special file. */ int mknod(const char* path, mode_t mode, dev_t dev); +#pragma GCC push_options +#pragma GCC diagnostic ignored "-Wshadow" + + /* Retrieve information about a file. */ + int stat(const char* path, struct stat* st); + +#pragma GCC pop_options + + /* Retrieve information about a file. */ + int fstat(int fd, struct stat* st); + #ifdef __cplusplus } #endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index f769ab67..f082063f 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -18,6 +18,7 @@ typedef __u64_t dev_t; typedef __u64_t ino_t; typedef __u32_t uid_t; typedef __u32_t gid_t; +typedef __u64_t nlink_t; typedef off_t fpos_t; diff --git a/libc/src/sys/stat.cpp b/libc/src/sys/stat.cpp index 8775170d..7eb709bf 100644 --- a/libc/src/sys/stat.cpp +++ b/libc/src/sys/stat.cpp @@ -16,4 +16,16 @@ extern "C" long rc = syscall(SYS_mknod, path, mode, dev); __errno_return(rc, int); } + + int stat(const char* path, struct stat* st) + { + long rc = syscall(SYS_stat, path, st); + __errno_return(rc, int); + } + + int fstat(int fd, struct stat* st) + { + long rc = syscall(SYS_fstat, fd, st); + __errno_return(rc, int); + } } diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index beec457b..00eb17dc 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -4,7 +4,7 @@ _e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \ _e(lseek) _e(mkdir) _e(execve) _e(mknod) _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(chmod) _e(chown) \ - _e(ioctl) + _e(ioctl) _e(stat) _e(fstat) enum Syscalls {