diff --git a/VirtualFileSystem/CharacterDevice.cpp b/VirtualFileSystem/CharacterDevice.cpp new file mode 100644 index 0000000000..dc743ff91f --- /dev/null +++ b/VirtualFileSystem/CharacterDevice.cpp @@ -0,0 +1,7 @@ +#include "CharacterDevice.h" + +CharacterDevice::~CharacterDevice() +{ +} + + diff --git a/VirtualFileSystem/CharacterDevice.h b/VirtualFileSystem/CharacterDevice.h new file mode 100644 index 0000000000..afb27a4509 --- /dev/null +++ b/VirtualFileSystem/CharacterDevice.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "Limits.h" + +class CharacterDevice { +public: + virtual ~CharacterDevice(); + + virtual ssize_t read(byte* buffer, size_t bufferSize) = 0; + virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0; + +protected: + CharacterDevice() { } +}; diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index 46760d9471..25f101f039 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -1,5 +1,6 @@ #include "FileHandle.h" #include "FileSystem.h" +#include "CharacterDevice.h" FileHandle::FileHandle(RetainPtr&& vnode) : m_vnode(std::move(vnode)) @@ -10,8 +11,15 @@ FileHandle::~FileHandle() { } -ByteBuffer FileHandle::read() const +ByteBuffer FileHandle::read() { + if (m_vnode->isCharacterDevice()) { + auto buffer = ByteBuffer::createUninitialized(1024); + ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size()); + buffer.trim(nread); + return buffer; + } + return m_vnode->fileSystem()->readInode(m_vnode->inode); } diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index b51c14b62a..66aa88508c 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -8,7 +8,7 @@ public: explicit FileHandle(RetainPtr&&); ~FileHandle(); - ByteBuffer read() const; + ByteBuffer read(); private: friend class VirtualFileSystem; diff --git a/VirtualFileSystem/Limits.h b/VirtualFileSystem/Limits.h new file mode 100644 index 0000000000..ebe763e2fe --- /dev/null +++ b/VirtualFileSystem/Limits.h @@ -0,0 +1,6 @@ +#pragma once + +typedef dword size_t; +typedef signed_dword ssize_t; + +static const size_t GoodBufferSize = 4096; diff --git a/VirtualFileSystem/Makefile b/VirtualFileSystem/Makefile index 06feb36de0..035039a658 100644 --- a/VirtualFileSystem/Makefile +++ b/VirtualFileSystem/Makefile @@ -20,6 +20,7 @@ VFS_OBJS = \ InodeIdentifier.o \ CharacterDevice.o \ ZeroDevice.o \ + NullDevice.o \ test.o OBJS = $(AK_OBJS) $(VFS_OBJS) diff --git a/VirtualFileSystem/NullDevice.cpp b/VirtualFileSystem/NullDevice.cpp new file mode 100644 index 0000000000..9c169055f2 --- /dev/null +++ b/VirtualFileSystem/NullDevice.cpp @@ -0,0 +1,25 @@ +#include "NullDevice.h" +#include "Limits.h" +#include +#include +#include + +NullDevice::NullDevice() +{ +} + +NullDevice::~NullDevice() +{ +} + +ssize_t NullDevice::read(byte*, size_t) +{ + printf("read from null\n"); + return 0; +} + +ssize_t NullDevice::write(const byte*, size_t bufferSize) +{ + return min(GoodBufferSize, bufferSize); +} + diff --git a/VirtualFileSystem/NullDevice.h b/VirtualFileSystem/NullDevice.h new file mode 100644 index 0000000000..703ef79c4b --- /dev/null +++ b/VirtualFileSystem/NullDevice.h @@ -0,0 +1,13 @@ +#pragma once + +#include "CharacterDevice.h" + +class NullDevice final : public CharacterDevice { +public: + NullDevice(); + virtual ~NullDevice(); + + ssize_t read(byte* buffer, size_t bufferSize) override; + ssize_t write(const byte* buffer, size_t bufferSize) override; +}; + diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index 293a3884c8..7676ae2e9a 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -7,6 +7,11 @@ //#define VFS_DEBUG +static dword encodedDevice(unsigned major, unsigned minor) +{ + return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); +} + VirtualFileSystem::VirtualFileSystem() { m_maxNodeCount = 16; @@ -28,6 +33,17 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr if (!metadata.isValid()) return nullptr; + CharacterDevice* characterDevice = nullptr; + if (metadata.isCharacterDevice()) { + auto it = m_characterDevices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice)); + if (it != m_characterDevices.end()) { + characterDevice = (*it).value; + } else { + printf("[VFS] makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice); + return nullptr; + } + } + auto vnode = allocateNode(); ASSERT(vnode); @@ -41,6 +57,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr #endif m_inode2vnode.set(inode, vnode.ptr()); + vnode->m_characterDevice = characterDevice; return vnode; } @@ -118,6 +135,7 @@ void VirtualFileSystem::freeNode(Node* node) m_inode2vnode.remove(node->inode); node->inode.fileSystem()->release(); node->inode = InodeIdentifier(); + node->m_characterDevice = nullptr; m_nodeFreeList.append(std::move(node)); } @@ -415,3 +433,7 @@ VirtualFileSystem::Mount::Mount(InodeIdentifier host, RetainPtr&& gu { } +void VirtualFileSystem::registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice& device) +{ + m_characterDevices.set(encodedDevice(major, minor), &device); +} diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 82a30e5513..9993b91f52 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -7,6 +7,7 @@ #include #include "InodeIdentifier.h" +class CharacterDevice; class FileHandle; class FileSystem; @@ -17,6 +18,9 @@ public: bool inUse() const { return inode.isValid(); } + bool isCharacterDevice() const { return m_characterDevice; } + CharacterDevice* characterDevice() { return m_characterDevice; } + void retain(); void release(); @@ -27,6 +31,7 @@ public: friend class VirtualFileSystem; VirtualFileSystem* vfs { nullptr }; unsigned retainCount { 0 }; + CharacterDevice* m_characterDevice { nullptr }; }; VirtualFileSystem(); @@ -52,6 +57,8 @@ public: bool touch(const String&path); + void registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice&); + private: template void enumerateDirectoryInode(InodeIdentifier, F func); InodeIdentifier resolvePath(const String& path); @@ -80,6 +87,7 @@ private: Mount* findMountForGuest(InodeIdentifier); HashMap m_inode2vnode; + HashMap m_device2vnode; Vector> m_mounts; @@ -89,5 +97,7 @@ private: Vector m_nodeFreeList; RetainPtr m_rootNode; + + HashMap m_characterDevices; }; diff --git a/VirtualFileSystem/ZeroDevice.cpp b/VirtualFileSystem/ZeroDevice.cpp new file mode 100644 index 0000000000..2ac3a16e5b --- /dev/null +++ b/VirtualFileSystem/ZeroDevice.cpp @@ -0,0 +1,27 @@ +#include "ZeroDevice.h" +#include "Limits.h" +#include +#include +#include + +ZeroDevice::ZeroDevice() +{ +} + +ZeroDevice::~ZeroDevice() +{ +} + +ssize_t ZeroDevice::read(byte* buffer, size_t bufferSize) +{ + printf("read from zero device\n"); + size_t count = min(GoodBufferSize, bufferSize); + memset(buffer, 0, count); + return count; +} + +ssize_t ZeroDevice::write(const byte*, size_t bufferSize) +{ + return min(GoodBufferSize, bufferSize); +} + diff --git a/VirtualFileSystem/ZeroDevice.h b/VirtualFileSystem/ZeroDevice.h new file mode 100644 index 0000000000..942a1b855a --- /dev/null +++ b/VirtualFileSystem/ZeroDevice.h @@ -0,0 +1,13 @@ +#pragma once + +#include "CharacterDevice.h" + +class ZeroDevice final : public CharacterDevice { +public: + ZeroDevice(); + virtual ~ZeroDevice(); + + ssize_t read(byte* buffer, size_t bufferSize) override; + ssize_t write(const byte* buffer, size_t bufferSize) override; +}; + diff --git a/VirtualFileSystem/small.fs b/VirtualFileSystem/small.fs index 28acc6a8fa..2970765b73 100644 Binary files a/VirtualFileSystem/small.fs and b/VirtualFileSystem/small.fs differ diff --git a/VirtualFileSystem/test.cpp b/VirtualFileSystem/test.cpp index f47067fa19..e95975dd3b 100644 --- a/VirtualFileSystem/test.cpp +++ b/VirtualFileSystem/test.cpp @@ -3,6 +3,8 @@ #include "VirtualFileSystem.h" #include "FileHandle.h" #include "SyntheticFileSystem.h" +#include "ZeroDevice.h" +#include "NullDevice.h" #include #include #include @@ -17,6 +19,12 @@ int main(int c, char** v) VirtualFileSystem vfs; + auto zero = make(); + vfs.registerCharacterDevice(1, 5, *zero); + + auto null = make(); + vfs.registerCharacterDevice(1, 3, *null); + if (!vfs.mountRoot(makeFileSystem(filename))) { printf("Failed to mount root :(\n"); return 1;