diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 6fdc6fbf..1c929c39 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -33,6 +33,7 @@ set(SOURCES src/sys/mkdir.cpp src/sys/mknod.cpp src/sys/waitpid.cpp + src/sys/getdents.cpp src/fs/VFS.cpp src/fs/tmpfs/FileSystem.cpp src/fs/devices/DeviceRegistry.cpp diff --git a/kernel/src/sys/getdents.cpp b/kernel/src/sys/getdents.cpp new file mode 100644 index 00000000..f56fd05c --- /dev/null +++ b/kernel/src/sys/getdents.cpp @@ -0,0 +1,40 @@ +#include "fs/VFS.h" +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "thread/Scheduler.h" +#include + +Result sys_getdents(Registers*, SyscallArgs args) +{ + int fd = (int)args[0]; + luna_dirent* ent = (luna_dirent*)args[1]; + usize count = (usize)args[2]; + + Thread* current = Scheduler::current(); + + auto& descriptor = *TRY(current->resolve_fd(fd)); + + if (descriptor.inode->type() != VFS::InodeType::Directory) return err(ENOTDIR); + + usize nwrite = 0; + while (nwrite < count) + { + auto maybe_entry = descriptor.inode->get(descriptor.offset); + if (!maybe_entry.has_value()) break; + + descriptor.offset++; + + auto entry = maybe_entry.release_value(); + + luna_dirent kent; + kent.inode = entry.inode->inode_number(); + strlcpy(kent.name, entry.name.chars(), entry.name.length() + 1); + + if (!MemoryManager::copy_to_user_typed(ent, &kent)) return err(EFAULT); + + ent++; + nwrite++; + } + + return nwrite; +} diff --git a/libc/include/bits/getdents.h b/libc/include/bits/getdents.h new file mode 100644 index 00000000..83fe9a2c --- /dev/null +++ b/libc/include/bits/getdents.h @@ -0,0 +1,14 @@ +/* bits/getdents.h: Definitions used for the getdents() system call. */ + +#ifndef _BITS_GETDENTS_H +#define _BITS_GETDENTS_H + +#include + +typedef struct +{ + ino_t inode; + char name[129]; +} luna_dirent; + +#endif diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h index fbf33018..aeecc9de 100644 --- a/libc/include/sys/types.h +++ b/libc/include/sys/types.h @@ -15,6 +15,7 @@ typedef __u16_t mode_t; typedef __u64_t useconds_t; typedef __i64_t off_t; typedef __u64_t dev_t; +typedef __u64_t ino_t; typedef off_t fpos_t; diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index ca5bb217..1d00a4a4 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -2,7 +2,7 @@ #define enumerate_syscalls(_e) \ _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(exec) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) + _e(lseek) _e(mkdir) _e(exec) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) enum Syscalls {