diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 87ea9620..99d3ddfe 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -24,3 +24,5 @@ luna_app(uname.cpp uname) luna_app(base64.cpp base64) luna_app(login.cpp login) luna_app(ipc-test.cpp ipc-test) +luna_app(mount.cpp mount) +luna_app(umount.cpp umount) diff --git a/apps/mount.cpp b/apps/mount.cpp new file mode 100644 index 00000000..5a18132c --- /dev/null +++ b/apps/mount.cpp @@ -0,0 +1,24 @@ +#include +#include +#include + +Result luna_main(int argc, char** argv) +{ + StringView target; + StringView fstype; + + os::ArgumentParser parser; + parser.add_description("Mount a file system."); + parser.add_system_program_info("mount"_sv); + parser.add_positional_argument(target, "mountpoint"_sv, true); + parser.add_value_argument(fstype, 't', "type"_sv, "auto"_sv, "the file system type to use"); + parser.parse(argc, argv); + + if (mount(target.chars(), fstype.chars()) < 0) + { + perror("mount"); + return 1; + } + + return 0; +} diff --git a/apps/umount.cpp b/apps/umount.cpp new file mode 100644 index 00000000..4ba07fae --- /dev/null +++ b/apps/umount.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +Result luna_main(int argc, char** argv) +{ + StringView target; + + os::ArgumentParser parser; + parser.add_description("Unmount a file system."); + parser.add_system_program_info("umount"_sv); + parser.add_positional_argument(target, "mountpoint"_sv, true); + parser.parse(argc, argv); + + if (umount(target.chars()) < 0) + { + perror("umount"); + return 1; + } + + return 0; +} diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 0106b734..f309e3e6 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -38,6 +38,7 @@ set(SOURCES src/sys/chdir.cpp src/sys/link.cpp src/sys/uname.cpp + src/sys/mount.cpp src/fs/VFS.cpp src/fs/Pipe.cpp src/fs/Mount.cpp diff --git a/kernel/src/sys/exec.cpp b/kernel/src/sys/exec.cpp index 231c4ad2..27f1359c 100644 --- a/kernel/src/sys/exec.cpp +++ b/kernel/src/sys/exec.cpp @@ -88,7 +88,11 @@ Result sys_execve(Registers* regs, SyscallArgs args) { auto& descriptor = current->fd_table[i]; if (!descriptor.has_value()) continue; - if (descriptor->flags & O_CLOEXEC) descriptor = {}; + if (descriptor->flags & O_CLOEXEC) + { + descriptor->inode->fs()->remove_handle(); + descriptor = {}; + } } MMU::delete_userspace_page_directory(current->directory); @@ -132,7 +136,11 @@ Result sys_fork(Registers* regs, SyscallArgs) thread->current_directory_path = move(current_directory_path); thread->parent = current; - for (int i = 0; i < FD_MAX; i++) { thread->fd_table[i] = current->fd_table[i]; } + for (int i = 0; i < FD_MAX; i++) + { + thread->fd_table[i] = current->fd_table[i]; + if (current->fd_table[i].has_value()) current->fd_table[i]->inode->fs()->add_handle(); + } image->apply(thread); diff --git a/kernel/src/sys/mount.cpp b/kernel/src/sys/mount.cpp new file mode 100644 index 00000000..bf197b06 --- /dev/null +++ b/kernel/src/sys/mount.cpp @@ -0,0 +1,34 @@ +#include "fs/VFS.h" +#include "fs/tmpfs/FileSystem.h" +#include "memory/MemoryManager.h" +#include "sys/Syscall.h" +#include "thread/Scheduler.h" + +Result sys_mount(Registers*, SyscallArgs args) +{ + auto target = TRY(MemoryManager::strdup_from_user(args[0])); + auto fstype = TRY(MemoryManager::strdup_from_user(args[1])); + + auto* current = Scheduler::current(); + if (current->auth.euid != 0) return err(EPERM); + + // Right now we only support one file system. + if (fstype.view() != "tmpfs") return err(ENODEV); + + auto fs = TRY(TmpFS::FileSystem::create()); + TRY(VFS::mount(target.chars(), fs, current->auth, current->current_directory)); + + return 0; +} + +Result sys_umount(Registers*, SyscallArgs args) +{ + auto target = TRY(MemoryManager::strdup_from_user(args[0])); + + auto* current = Scheduler::current(); + if (current->auth.euid != 0) return err(EPERM); + + TRY(VFS::umount(target.chars(), current->auth, current->current_directory)); + + return 0; +} diff --git a/kernel/src/sys/open.cpp b/kernel/src/sys/open.cpp index 9453e574..f8d11bc5 100644 --- a/kernel/src/sys/open.cpp +++ b/kernel/src/sys/open.cpp @@ -72,6 +72,8 @@ Result sys_openat(Registers*, SyscallArgs args) kinfoln("openat: opening file %s from dirfd %d, flags %d, mode %#o = fd %d", path.chars(), dirfd, flags, mode, fd); + inode->fs()->add_handle(); + current->fd_table[fd] = FileDescriptor { inode, 0, flags & FLAGS_TO_KEEP }; return (u64)fd; @@ -88,6 +90,8 @@ Result sys_close(Registers*, SyscallArgs args) if (!descriptor.has_value()) return err(EBADF); + descriptor->inode->fs()->remove_handle(); + descriptor = {}; return 0; diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 45887a76..824a13a5 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -182,6 +182,11 @@ namespace Scheduler { auto stack = thread->kernel_stack; MemoryManager::unmap_owned_and_free_vm(stack.bottom(), stack.bytes() / ARCH_PAGE_SIZE).release_value(); + + for (int i = 0; i < FD_MAX; i++) + { + if (thread->fd_table[i].has_value()) thread->fd_table[i]->inode->fs()->remove_handle(); + } } if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->directory); diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index 493286f9..4a45ebde 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -66,22 +66,6 @@ Result> Thread::resolve_atfile(int dirfd, const String& pa return VFS::resolve_path(path.chars(), this->auth, descriptor->inode); } -FileDescriptor::FileDescriptor(SharedPtr _inode, usize _offset, int _flags) - : inode(_inode), offset(_offset), flags(_flags) -{ - inode->fs()->add_handle(); -} - -FileDescriptor::FileDescriptor(const FileDescriptor& f) : inode(f.inode), offset(f.offset), flags(f.flags) -{ - inode->fs()->add_handle(); -} - -FileDescriptor::~FileDescriptor() -{ - inode->fs()->remove_handle(); -} - bool FileDescriptor::should_append() { return flags & O_APPEND; diff --git a/kernel/src/thread/Thread.h b/kernel/src/thread/Thread.h index 62baf50c..e50fa45e 100644 --- a/kernel/src/thread/Thread.h +++ b/kernel/src/thread/Thread.h @@ -33,10 +33,6 @@ struct FileDescriptor usize offset { 0 }; int flags { 0 }; - FileDescriptor(SharedPtr inode, usize offset, int flags); - FileDescriptor(const FileDescriptor& f); - ~FileDescriptor(); - bool should_append(); bool should_block(); bool is_writable(); diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 734347af..e781678e 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -24,6 +24,7 @@ set(SOURCES src/sys/wait.cpp src/sys/ioctl.cpp src/sys/utsname.cpp + src/sys/mount.cpp ) if(${LUNA_ARCH} STREQUAL "x86_64") diff --git a/libc/include/sys/mount.h b/libc/include/sys/mount.h new file mode 100644 index 00000000..2711e287 --- /dev/null +++ b/libc/include/sys/mount.h @@ -0,0 +1,21 @@ +/* sys/mount.h: Virtual file system mounting operations. */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Mount a file system on target. */ + int mount(const char* target, const char* fstype); + + /* Unmount the file system mounted on target. */ + int umount(const char* target); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libc/src/sys/mount.cpp b/libc/src/sys/mount.cpp new file mode 100644 index 00000000..cf8384ee --- /dev/null +++ b/libc/src/sys/mount.cpp @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +extern "C" +{ + int mount(const char* target, const char* fstype) + { + long rc = syscall(SYS_mount, target, fstype); + __errno_return(rc, int); + } + + int umount(const char* target) + { + long rc = syscall(SYS_umount, target); + __errno_return(rc, int); + } +} diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index e1d1354c..ad8c6333 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -4,7 +4,8 @@ _e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(openat) _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(fchmodat) _e(fchownat) \ - _e(ioctl) _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) + _e(ioctl) _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) \ + _e(mount) _e(umount) enum Syscalls {