diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index fa44563a1ca57d..52f3870172ce67 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 84ef0a2de34b8f..5c6365d9dd9ed8 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -126,6 +126,9 @@ class Process : public InlineLinkedListNode { 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 @@ class Process : public InlineLinkedListNode { 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 cef16f864c3ab7..c4e5fd704ad338 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 1582b45dcffa18..c5a210d0999251 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 07d50d01d41e3d..0914e856f3ee0a 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 890a2d16f3b950..9b0e77cdb30bdb 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 97c2cdcf12fde6..49548d6a0cf732 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 8ad7074a39ab8a..a03f735341ca04 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 00000000000000..e69de29bb2d1d6 diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index a6c8eee738290f..46cb713996d7dc 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 7d4eebbbdb7fa4..9b388e07332e04 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 b249921bad390a..312c4cc9cb8eb6 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 a8bcaf99331952..f3d0e41019ec64 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 f56b43cd6b36f1..e74e9872528523 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 1a9757e3aef4ad..51bcf9ed538558 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 @@ class FileHandle { 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 @@ class FileHandle { private: friend class VirtualFileSystem; + explicit FileHandle(RetainPtr&&); RetainPtr m_vnode; diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 4ef6ba5df178e9..79632ccbae3155 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 1ce34a36044934..ad2c3998452c1a 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -93,10 +93,10 @@ class VirtualFileSystem { 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;