From 9f2b9c82bf0424bb8d0bbc832a0fa6366c3def9a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 5 Nov 2018 19:01:22 +0100 Subject: [PATCH] More work towards getting bash to build. Implemented some syscalls: dup(), dup2(), getdtablesize(). FileHandle is now a retainable, since that's needed for dup()'ed fd's. I didn't really test any of this beyond a basic smoke check. --- Kernel/Process.cpp | 33 ++++++++++++++++++++++++- Kernel/Process.h | 5 +++- Kernel/Syscall.cpp | 6 +++++ Kernel/Syscall.h | 3 +++ LibC/dirent.cpp | 11 +++++++++ LibC/dirent.h | 3 ++- LibC/stdio.cpp | 11 +++++++++ LibC/stdio.h | 1 + LibC/sys/resource.h | 0 LibC/unistd.cpp | 17 +++++++++++++ LibC/unistd.h | 3 +++ VirtualFileSystem/CharacterDevice.cpp | 2 +- VirtualFileSystem/CharacterDevice.h | 2 +- VirtualFileSystem/FileHandle.cpp | 9 +++++-- VirtualFileSystem/FileHandle.h | 11 ++++----- VirtualFileSystem/VirtualFileSystem.cpp | 12 ++++----- VirtualFileSystem/VirtualFileSystem.h | 8 +++--- 17 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 LibC/sys/resource.h diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fa44563a1ca..52f3870172c 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1158,7 +1158,6 @@ int Process::sys$open(const char* path, int options) if (!m_file_descriptors[fd]) break; } - handle->setFD(fd); m_file_descriptors[fd] = move(handle); return fd; } @@ -1435,3 +1434,35 @@ int Process::sys$tcsetpgrp(int fd, pid_t pgid) tty.set_pgid(pgid); return 0; } + +int Process::sys$getdtablesize() +{ + return m_max_open_file_descriptors; +} + +int Process::sys$dup(int old_fd) +{ + auto* handle = fileHandleIfExists(old_fd); + if (!handle) + return -EBADF; + if (number_of_open_file_descriptors() == m_max_open_file_descriptors) + return -EMFILE; + int new_fd = 0; + for (; new_fd < m_max_open_file_descriptors; ++new_fd) { + if (!m_file_descriptors[new_fd]) + break; + } + m_file_descriptors[new_fd] = handle; + return new_fd; +} + +int Process::sys$dup2(int old_fd, int new_fd) +{ + auto* handle = fileHandleIfExists(old_fd); + if (!handle) + return -EBADF; + if (number_of_open_file_descriptors() == m_max_open_file_descriptors) + return -EMFILE; + m_file_descriptors[new_fd] = handle; + return new_fd; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index 84ef0a2de34..5c6365d9dd9 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -126,6 +126,9 @@ public: int sys$execve(const char* filename, const char** argv, const char** envp); Unix::sighandler_t sys$signal(int signum, Unix::sighandler_t); int sys$isatty(int fd); + int sys$getdtablesize(); + int sys$dup(int oldfd); + int sys$dup2(int oldfd, int newfd); static void initialize(); @@ -193,7 +196,7 @@ private: State m_state { Invalid }; DWORD m_wakeupTime { 0 }; TSS32 m_tss; - Vector> m_file_descriptors; + Vector> m_file_descriptors; RingLevel m_ring { Ring0 }; int m_error { 0 }; void* m_kernelStack { nullptr }; diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index cef16f864c3..c4e5fd704ad 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -140,6 +140,12 @@ static DWORD handle(RegisterDump& regs, DWORD function, DWORD arg1, DWORD arg2, return (dword)current->sys$signal((int)arg1, (Unix::sighandler_t)arg2); case Syscall::PosixIsatty: return current->sys$isatty((int)arg1); + case Syscall::Getdtablesize: + return current->sys$getdtablesize(); + case Syscall::Dup: + return current->sys$dup((int)arg1); + case Syscall::Dup2: + return current->sys$dup2((int)arg1, (int)arg2); default: kprintf("<%u> int0x80: Unknown function %x requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 1582b45dcff..c5a210d0999 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -53,6 +53,9 @@ enum Function { PosixGetegid = 0x2021, PosixSignal = 0x2022, PosixIsatty = 0x2023, + Getdtablesize = 0x2024, + Dup = 0x2025, + Dup2 = 0x2026, }; void initialize(); diff --git a/LibC/dirent.cpp b/LibC/dirent.cpp index 07d50d01d41..0914e856f3e 100644 --- a/LibC/dirent.cpp +++ b/LibC/dirent.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include extern "C" { @@ -20,6 +21,16 @@ DIR* opendir(const char* name) return dirp; } +int closedir(DIR* dirp) +{ + if (!dirp || dirp->fd == -1) + return -EBADF; + int rc = close(dirp->fd); + if (rc == 0) + dirp->fd = -1; + return rc; +} + struct sys_dirent { ino_t ino; byte file_type; diff --git a/LibC/dirent.h b/LibC/dirent.h index 890a2d16f3b..9b0e77cdb30 100644 --- a/LibC/dirent.h +++ b/LibC/dirent.h @@ -23,7 +23,8 @@ struct __DIR { typedef struct __DIR DIR; DIR* opendir(const char* name); -struct dirent* readdir(DIR* dirp); +int closedir(DIR*); +struct dirent* readdir(DIR*); __END_DECLS diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 97c2cdcf12f..49548d6a0cf 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -193,6 +193,17 @@ FILE* fopen(const char* pathname, const char* mode) return fp; } +FILE* fdopen(int fd, const char* mode) +{ + assert(!strcmp(mode, "r") || !strcmp(mode, "rb")); + if (fd < 0) + return nullptr; + auto* fp = (FILE*)malloc(sizeof(FILE)); + fp->fd = fd; + fp->eof = false; + return fp; +} + int fclose(FILE* stream) { int rc = close(stream->fd); diff --git a/LibC/stdio.h b/LibC/stdio.h index 8ad7074a39a..a03f735341c 100644 --- a/LibC/stdio.h +++ b/LibC/stdio.h @@ -29,6 +29,7 @@ int fileno(FILE*); int fgetc(FILE*); int getc(FILE*); int getchar(); +FILE* fdopen(int fd, const char* mode); FILE* fopen(const char* pathname, const char* mode); int fclose(FILE*); void rewind(FILE*); diff --git a/LibC/sys/resource.h b/LibC/sys/resource.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index a6c8eee7382..46cb713996d 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -190,5 +190,22 @@ int isatty(int fd) __RETURN_WITH_ERRNO(rc, 1, 0); } +int getdtablesize() +{ + int rc = Syscall::invoke(Syscall::Getdtablesize); + __RETURN_WITH_ERRNO(rc, 1, 0); } +int dup(int old_fd) +{ + int rc = Syscall::invoke(Syscall::Dup, (dword)old_fd); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +int dup2(int old_fd, int new_fd) +{ + int rc = Syscall::invoke(Syscall::Dup2, (dword)old_fd, (dword)new_fd); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +} diff --git a/LibC/unistd.h b/LibC/unistd.h index 7d4eebbbdb7..9b388e07332 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -39,6 +39,9 @@ int ttyname_r(int fd, char* buffer, size_t); off_t lseek(int fd, off_t, int whence); int link(const char* oldpath, const char* newpath); int unlink(const char* pathname); +int getdtablesize(); +int dup(int old_fd); +int dup2(int old_fd, int new_fd); #define WEXITSTATUS(status) (((status) & 0xff00) >> 8) #define WTERMSIG(status) ((status) & 0x7f) diff --git a/VirtualFileSystem/CharacterDevice.cpp b/VirtualFileSystem/CharacterDevice.cpp index b249921bad3..312c4cc9cb8 100644 --- a/VirtualFileSystem/CharacterDevice.cpp +++ b/VirtualFileSystem/CharacterDevice.cpp @@ -4,7 +4,7 @@ CharacterDevice::~CharacterDevice() { } -OwnPtr CharacterDevice::open(int options) +RetainPtr CharacterDevice::open(int options) { return VirtualFileSystem::the().open(*this, options); } diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h index a8bcaf99331..f3d0e41019e 100644 --- a/VirtualFileSystem/CharacterDevice.h +++ b/VirtualFileSystem/CharacterDevice.h @@ -8,7 +8,7 @@ class CharacterDevice { public: virtual ~CharacterDevice(); - virtual OwnPtr open(int options); + RetainPtr open(int options); virtual bool hasDataAvailableForRead() const = 0; diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index f56b43cd6b3..e74e9872528 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -6,6 +6,11 @@ #include "TTY.h" #include +RetainPtr FileHandle::create(RetainPtr&& vnode) +{ + return adopt(*new FileHandle(move(vnode))); +} + FileHandle::FileHandle(RetainPtr&& vnode) : m_vnode(move(vnode)) { @@ -15,9 +20,9 @@ FileHandle::~FileHandle() { } -OwnPtr FileHandle::clone() +RetainPtr FileHandle::clone() { - auto handle = make(m_vnode.copyRef()); + auto handle = FileHandle::create(m_vnode.copyRef()); if (!handle) return nullptr; handle->m_currentOffset = m_currentOffset; diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index 1a9757e3aef..51bcf9ed538 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -3,15 +3,16 @@ #include "VirtualFileSystem.h" #include "InodeMetadata.h" #include +#include class TTY; -class FileHandle { +class FileHandle : public Retainable { public: - explicit FileHandle(RetainPtr&&); + static RetainPtr create(RetainPtr&&); ~FileHandle(); - OwnPtr clone(); + RetainPtr clone(); int close(); @@ -39,9 +40,6 @@ public: VirtualFileSystem::Node* vnode() { return m_vnode.ptr(); } #ifdef SERENITY - int fd() const { return m_fd; } - void setFD(int fd) { m_fd = fd; } - bool isBlocking() const { return m_isBlocking; } void setBlocking(bool b) { m_isBlocking = b; } #endif @@ -50,6 +48,7 @@ public: private: friend class VirtualFileSystem; + explicit FileHandle(RetainPtr&&); RetainPtr m_vnode; diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 4ef6ba5df17..79632ccbae3 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -398,15 +398,15 @@ bool VirtualFileSystem::touch(const String& path) return inode.fileSystem()->setModificationTime(inode, ktime(nullptr)); } -OwnPtr VirtualFileSystem::open(CharacterDevice& device, int options) +RetainPtr VirtualFileSystem::open(CharacterDevice& device, int options) { auto vnode = getOrCreateNode(device); if (!vnode) return nullptr; - return make(move(vnode)); + return FileHandle::create(move(vnode)); } -OwnPtr VirtualFileSystem::open(const String& path, int& error, int options, InodeIdentifier base) +RetainPtr VirtualFileSystem::open(const String& path, int& error, int options, InodeIdentifier base) { auto inode = resolvePath(path, error, base, options); if (!inode.isValid()) @@ -414,10 +414,10 @@ OwnPtr VirtualFileSystem::open(const String& path, int& error, int o auto vnode = getOrCreateNode(inode); if (!vnode) return nullptr; - return make(move(vnode)); + return FileHandle::create(move(vnode)); } -OwnPtr VirtualFileSystem::create(const String& path, InodeIdentifier base) +RetainPtr VirtualFileSystem::create(const String& path, InodeIdentifier base) { // FIXME: Do the real thing, not just this fake thing! (void) path; @@ -425,7 +425,7 @@ OwnPtr VirtualFileSystem::create(const String& path, InodeIdentifier return nullptr; } -OwnPtr VirtualFileSystem::mkdir(const String& path, InodeIdentifier base) +RetainPtr VirtualFileSystem::mkdir(const String& path, InodeIdentifier base) { // FIXME: Do the real thing, not just this fake thing! (void) path; diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 1ce34a36044..ad2c3998452 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -93,10 +93,10 @@ public: bool mountRoot(RetainPtr&&); bool mount(RetainPtr&&, const String& path); - OwnPtr open(CharacterDevice&, int options); - OwnPtr open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier()); - OwnPtr create(const String& path, InodeIdentifier base = InodeIdentifier()); - OwnPtr mkdir(const String& path, InodeIdentifier base = InodeIdentifier()); + RetainPtr open(CharacterDevice&, int options); + RetainPtr open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier()); + RetainPtr create(const String& path, InodeIdentifier base = InodeIdentifier()); + RetainPtr mkdir(const String& path, InodeIdentifier base = InodeIdentifier()); bool isRoot(InodeIdentifier) const;