From ed2422d7afbf0368c5dc828c7280a4d1c0473039 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 23 Oct 2018 11:57:38 +0200 Subject: [PATCH] Start adding a basic /proc filesystem and a "ps" utility. --- AK/Function.h | 6 +-- Kernel/Makefile | 6 ++- Kernel/ProcFileSystem.cpp | 29 ++++++++++++ Kernel/ProcFileSystem.h | 17 +++++++ Kernel/Task.cpp | 2 + Kernel/_fs_contents | Bin 1024000 -> 1024000 bytes Kernel/init.cpp | 5 ++- Kernel/sync-sh | 2 + Userland/.gitignore | 1 + Userland/Makefile | 9 +++- Userland/ps.cpp | 25 +++++++++++ VirtualFileSystem/SyntheticFileSystem.cpp | 52 ++++++++++++++++------ VirtualFileSystem/SyntheticFileSystem.h | 8 +++- 13 files changed, 139 insertions(+), 23 deletions(-) create mode 100644 Kernel/ProcFileSystem.cpp create mode 100644 Kernel/ProcFileSystem.h create mode 100644 Userland/ps.cpp diff --git a/AK/Function.h b/AK/Function.h index 34a2bc68fc..99fc8089b5 100644 --- a/AK/Function.h +++ b/AK/Function.h @@ -51,7 +51,7 @@ public: { } - Out operator()(In... in) + Out operator()(In... in) const { ASSERT(m_callableWrapper); return m_callableWrapper->call(forward(in)...); @@ -83,7 +83,7 @@ private: class CallableWrapperBase { public: virtual ~CallableWrapperBase() { } - virtual Out call(In...) = 0; + virtual Out call(In...) const = 0; }; template @@ -97,7 +97,7 @@ private: CallableWrapper(const CallableWrapper&) = delete; CallableWrapper& operator=(const CallableWrapper&) = delete; - Out call(In... in) final { return m_callable(forward(in)...); } + Out call(In... in) const final { return m_callable(forward(in)...); } private: CallableType m_callable; diff --git a/Kernel/Makefile b/Kernel/Makefile index 6cedc78961..5929be1044 100644 --- a/Kernel/Makefile +++ b/Kernel/Makefile @@ -21,7 +21,8 @@ KERNEL_OBJS = \ MemoryManager.o \ Console.o \ IRQHandler.o \ - kprintf.o + kprintf.o \ + ProcFileSystem.o VFS_OBJS = \ ../VirtualFileSystem/DiskDevice.o \ @@ -35,7 +36,8 @@ VFS_OBJS = \ ../VirtualFileSystem/Ext2FileSystem.o \ ../VirtualFileSystem/InodeIdentifier.o \ ../VirtualFileSystem/VirtualFileSystem.o \ - ../VirtualFileSystem/FileHandle.o + ../VirtualFileSystem/FileHandle.o \ + ../VirtualFileSystem/SyntheticFileSystem.o ELFLOADER_OBJS = \ ../ELFLoader/ELFImage.o \ diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp new file mode 100644 index 0000000000..751d5e9c8d --- /dev/null +++ b/Kernel/ProcFileSystem.cpp @@ -0,0 +1,29 @@ +#include "ProcFileSystem.h" +#include + +RetainPtr ProcFileSystem::create() +{ + return adopt(*new ProcFileSystem); +} + +ProcFileSystem::ProcFileSystem() +{ +} + +ProcFileSystem::~ProcFileSystem() +{ +} + +bool ProcFileSystem::initialize() +{ + SyntheticFileSystem::initialize(); + addFile(createGeneratedFile("summary", [] { + return String("Process summary!").toByteBuffer(); + })); + return true; +} + +const char* ProcFileSystem::className() const +{ + return "procfs"; +} diff --git a/Kernel/ProcFileSystem.h b/Kernel/ProcFileSystem.h new file mode 100644 index 0000000000..68d8d04a68 --- /dev/null +++ b/Kernel/ProcFileSystem.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +class ProcFileSystem final : public SyntheticFileSystem { +public: + virtual ~ProcFileSystem() override; + static RetainPtr create(); + + virtual bool initialize() override; + virtual const char* className() const override; + +private: + ProcFileSystem(); +}; + diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 10f111ea50..065fe02869 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -645,7 +645,9 @@ FileHandle* Task::openFile(String&& path) { auto handle = VirtualFileSystem::the().open(move(path)); if (!handle) { +#ifdef DEBUG_IO kprintf("vfs::open() failed\n"); +#endif return nullptr; } handle->setFD(m_fileHandles.size()); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index 344bc920023630414f0ac97177141b3b830e0b44..3aaa2fc34ea7bf0a231bd408d99f254cdb331cd0 100644 GIT binary patch delta 3153 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 VA%VADA%SnZLIVE-`^61rG63weeU1PC diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 743c2b06ca..c71010136f 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -25,6 +25,7 @@ #include "MemoryManager.h" #include #include "Console.h" +#include "ProcFileSystem.h" #define TEST_VFS //#define TEST_ELF_LOADER @@ -132,7 +133,9 @@ static void init_stage2() vfs->mountRoot(e2fs.copyRef()); - //vfs->listDirectory("/"); + auto procfs = ProcFileSystem::create(); + procfs->initialize(); + vfs->mount(procfs.copyRef(), "/proc"); { auto motdFile = vfs->open("/motd.txt"); diff --git a/Kernel/sync-sh b/Kernel/sync-sh index 3a32e3b5cb..971ab5c9cb 100755 --- a/Kernel/sync-sh +++ b/Kernel/sync-sh @@ -1,5 +1,7 @@ mkdir mnt mount -o loop _fs_contents mnt/ cp ../Userland/sh mnt/bin/sh +cp ../Userland/id mnt/bin/id +cp ../Userland/ps mnt/bin/ps umount mnt sync diff --git a/Userland/.gitignore b/Userland/.gitignore index 89dadc36dd..27529b9b9b 100644 --- a/Userland/.gitignore +++ b/Userland/.gitignore @@ -1,3 +1,4 @@ id sh +ps *.o diff --git a/Userland/Makefile b/Userland/Makefile index 0266a2edd0..ec3fddd381 100644 --- a/Userland/Makefile +++ b/Userland/Makefile @@ -1,10 +1,12 @@ OBJS = \ id.o \ - sh.o + sh.o \ + ps.o APPS = \ id \ - sh + sh \ + ps ARCH_FLAGS = STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib @@ -30,6 +32,9 @@ id: id.o sh: sh.o $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a +ps: ps.o + $(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a + .cpp.o: @echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $< diff --git a/Userland/ps.cpp b/Userland/ps.cpp new file mode 100644 index 0000000000..5b620d96e4 --- /dev/null +++ b/Userland/ps.cpp @@ -0,0 +1,25 @@ +#include +#include + +int main(int c, char** v) +{ + int fd = open("/proc/summary"); + if (fd == -1) { + printf("failed to open /proc/summary :(\n"); + return 1; + } + for (;;) { + char buf[16]; + ssize_t nread = read(fd, buf, sizeof(buf)); + if (nread == 0) + break; + if (nread < 0) { + printf("failed to read :(\n"); + return 2; + } + for (ssize_t i = 0; i < nread; ++i) { + putchar(buf[i]); + } + } + return 0; +} diff --git a/VirtualFileSystem/SyntheticFileSystem.cpp b/VirtualFileSystem/SyntheticFileSystem.cpp index 4da29bbf95..76de74499e 100644 --- a/VirtualFileSystem/SyntheticFileSystem.cpp +++ b/VirtualFileSystem/SyntheticFileSystem.cpp @@ -1,6 +1,8 @@ #include "SyntheticFileSystem.h" #include +//#define SYNTHFS_DEBUG + RetainPtr SyntheticFileSystem::create() { return adopt(*new SyntheticFileSystem); @@ -25,10 +27,12 @@ bool SyntheticFileSystem::initialize() rootDir->metadata.gid = 0; rootDir->metadata.size = 0; rootDir->metadata.mtime = mepoch; - m_files.append(std::move(rootDir)); + m_files.append(move(rootDir)); +#ifndef SERENITY addFile(createTextFile("file", "I'm a synthetic file!\n")); addFile(createTextFile("message", "Hey! This isn't my bottle!\n")); +#endif return true; } @@ -36,7 +40,7 @@ auto SyntheticFileSystem::createTextFile(String&& name, String&& text) -> OwnPtr { auto file = make(); file->data = text.toByteBuffer(); - file->name = std::move(name); + file->name = move(name); file->metadata.size = file->data.size(); file->metadata.uid = 100; file->metadata.gid = 200; @@ -45,11 +49,24 @@ auto SyntheticFileSystem::createTextFile(String&& name, String&& text) -> OwnPtr return file; } +auto SyntheticFileSystem::createGeneratedFile(String&& name, Function&& generator) -> OwnPtr +{ + auto file = make(); + file->generator = move(generator); + file->name = move(name); + file->metadata.size = 0; + file->metadata.uid = 0; + file->metadata.gid = 0; + file->metadata.mode = 0100644; + file->metadata.mtime = mepoch; + return file; +} + void SyntheticFileSystem::addFile(OwnPtr&& file) { ASSERT(file); file->metadata.inode = { id(), m_files.size() + 1 }; - m_files.append(std::move(file)); + m_files.append(move(file)); } const char* SyntheticFileSystem::className() const @@ -66,7 +83,7 @@ bool SyntheticFileSystem::enumerateDirectoryInode(InodeIdentifier inode, Functio { ASSERT(inode.fileSystemID() == id()); #ifdef SYNTHFS_DEBUG - printf("[synthfs] enumerateDirectoryInode %u\n", inode.index()); + kprintf("[synthfs] enumerateDirectoryInode %u\n", inode.index()); #endif if (inode.index() != 1) return false; @@ -83,17 +100,21 @@ InodeMetadata SyntheticFileSystem::inodeMetadata(InodeIdentifier inode) const { ASSERT(inode.fileSystemID() == id()); #ifdef SYNTHFS_DEBUG - printf("[synthfs] inodeMetadata(%u)\n", inode.index); + kprintf("[synthfs] inodeMetadata(%u)\n", inode.index()); #endif if (inode.index() == 0 || inode.index() > m_files.size()) return InodeMetadata(); - return m_files[inode.index() - 1]->metadata; + auto& file = *m_files[inode.index() - 1]; + auto metadata = file.metadata; + if (file.generator) + metadata.size = file.generator().size(); + return metadata; } bool SyntheticFileSystem::setModificationTime(InodeIdentifier, dword timestamp) { (void) timestamp; - printf("FIXME: Implement SyntheticFileSystem::setModificationTime().\n"); + kprintf("FIXME: Implement SyntheticFileSystem::setModificationTime().\n"); return false; } @@ -102,13 +123,13 @@ InodeIdentifier SyntheticFileSystem::createInode(InodeIdentifier parentInode, co (void) parentInode; (void) name; (void) mode; - printf("FIXME: Implement SyntheticFileSystem::createDirectoryInode().\n"); + kprintf("FIXME: Implement SyntheticFileSystem::createDirectoryInode().\n"); return { }; } bool SyntheticFileSystem::writeInode(InodeIdentifier, const ByteBuffer&) { - printf("FIXME: Implement SyntheticFileSystem::writeInode().\n"); + kprintf("FIXME: Implement SyntheticFileSystem::writeInode().\n"); return false; } @@ -116,7 +137,7 @@ Unix::ssize_t SyntheticFileSystem::readInodeBytes(InodeIdentifier inode, Unix::o { ASSERT(inode.fileSystemID() == id()); #ifdef SYNTHFS_DEBUG - printf("[synthfs] readInode %u\n", inode.index()); + kprintf("[synthfs] readInode %u\n", inode.index()); #endif ASSERT(inode.index() != 1); ASSERT(inode.index() <= m_files.size()); @@ -124,13 +145,18 @@ Unix::ssize_t SyntheticFileSystem::readInodeBytes(InodeIdentifier inode, Unix::o ASSERT(buffer); auto& file = *m_files[inode.index() - 1]; - Unix::ssize_t nread = min(static_cast(file.data.size() - offset), static_cast(count)); - memcpy(buffer, file.data.pointer() + offset, nread); + ByteBuffer generatedData; + if (file.generator) + generatedData = file.generator(); + auto* data = generatedData ? &generatedData : &file.data; + + Unix::ssize_t nread = min(static_cast(data->size() - offset), static_cast(count)); + memcpy(buffer, data->pointer() + offset, nread); return nread; } InodeIdentifier SyntheticFileSystem::makeDirectory(InodeIdentifier parentInode, const String& name, Unix::mode_t) { - printf("FIXME: Implement SyntheticFileSystem::makeDirectory().\n"); + kprintf("FIXME: Implement SyntheticFileSystem::makeDirectory().\n"); return { }; } diff --git a/VirtualFileSystem/SyntheticFileSystem.h b/VirtualFileSystem/SyntheticFileSystem.h index 97f48e883a..419ea647a9 100644 --- a/VirtualFileSystem/SyntheticFileSystem.h +++ b/VirtualFileSystem/SyntheticFileSystem.h @@ -4,7 +4,7 @@ #include "UnixTypes.h" #include -class SyntheticFileSystem final : public FileSystem { +class SyntheticFileSystem : public FileSystem { public: virtual ~SyntheticFileSystem() override; static RetainPtr create(); @@ -20,18 +20,22 @@ public: virtual Unix::ssize_t readInodeBytes(InodeIdentifier, Unix::off_t offset, Unix::size_t count, byte* buffer) const override; virtual InodeIdentifier makeDirectory(InodeIdentifier parentInode, const String& name, Unix::mode_t) override; -private: +protected: SyntheticFileSystem(); struct File { String name; InodeMetadata metadata; ByteBuffer data; + Function generator; }; OwnPtr createTextFile(String&& name, String&& text); + OwnPtr createGeneratedFile(String&& name, Function&&); + void addFile(OwnPtr&&); +private: Vector> m_files; };