From bca4b71bfa1e3db74aaa706a9849e36768282a95 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 24 Oct 2018 12:43:52 +0200 Subject: [PATCH] Lots of hacking to make a very simple "ls" utility. I added a dead-simple malloc that only allows allocations < 4096 bytes. It just forwards the request to mmap() every time. I also added simplified versions of opendir() and readdir(). --- AK/BufferStream.h | 54 +++++++++++++++++++ Kernel/ProcFileSystem.cpp | 7 +-- Kernel/Syscall.cpp | 2 + Kernel/Syscall.h | 1 + Kernel/Task.cpp | 16 ++++++ Kernel/Task.h | 3 ++ Kernel/_fs_contents | Bin 1024000 -> 1024000 bytes LibC/Makefile | 2 + LibC/dirent.cpp | 67 ++++++++++++++++++++++++ LibC/dirent.h | 27 ++++++++++ LibC/stdlib.cpp | 24 +++++++++ LibC/stdlib.h | 11 ++++ LibC/types.h | 3 ++ Userland/ls.cpp | 18 +++---- VirtualFileSystem/Ext2FileSystem.cpp | 44 +--------------- VirtualFileSystem/FileHandle.cpp | 29 +++++++++- VirtualFileSystem/FileHandle.h | 2 + VirtualFileSystem/VirtualFileSystem.cpp | 19 +++++-- VirtualFileSystem/VirtualFileSystem.h | 15 ++++-- 19 files changed, 277 insertions(+), 67 deletions(-) create mode 100644 AK/BufferStream.h create mode 100644 LibC/dirent.cpp create mode 100644 LibC/dirent.h create mode 100644 LibC/stdlib.cpp create mode 100644 LibC/stdlib.h diff --git a/AK/BufferStream.h b/AK/BufferStream.h new file mode 100644 index 0000000000..379fcb5792 --- /dev/null +++ b/AK/BufferStream.h @@ -0,0 +1,54 @@ +#pragma once + +#include "ByteBuffer.h" + +namespace AK { + +class BufferStream { +public: + explicit BufferStream(ByteBuffer& buffer) + : m_buffer(buffer) + { + } + + void operator<<(byte value) + { + m_buffer[m_offset++] = value & 0xffu; + } + + void operator<<(word value) + { + m_buffer[m_offset++] = value & 0xffu; + m_buffer[m_offset++] = (byte)(value >> 8) & 0xffu; + } + + void operator<<(dword value) + { + m_buffer[m_offset++] = value & 0xffu; + m_buffer[m_offset++] = (byte)(value >> 8) & 0xffu; + m_buffer[m_offset++] = (byte)(value >> 16) & 0xffu; + m_buffer[m_offset++] = (byte)(value >> 24) & 0xffu; + } + + void operator<<(const String& value) + { + for (unsigned i = 0; i < value.length(); ++i) + m_buffer[m_offset++] = value[i]; + } + + void fillToEnd(byte ch) + { + while (m_offset < m_buffer.size()) + m_buffer[m_offset++] = ch; + } + + Unix::size_t offset() const { return m_offset; } + +private: + ByteBuffer& m_buffer; + Unix::size_t m_offset { 0 }; +}; + +} + +using AK::BufferStream; diff --git a/Kernel/ProcFileSystem.cpp b/Kernel/ProcFileSystem.cpp index 57d7493fd1..039d8c897d 100644 --- a/Kernel/ProcFileSystem.cpp +++ b/Kernel/ProcFileSystem.cpp @@ -21,17 +21,18 @@ bool ProcFileSystem::initialize() InterruptDisabler disabler; auto tasks = Task::allTasks(); char* buffer; - auto stringImpl = StringImpl::createUninitialized(tasks.size() * 128, buffer); + auto stringImpl = StringImpl::createUninitialized(tasks.size() * 256, buffer); memset(buffer, 0, stringImpl->length()); char* ptr = buffer; - ptr += ksprintf(ptr, "PID OWNER STATE NSCHED NAME\n"); + ptr += ksprintf(ptr, "PID OWNER STATE NSCHED FDS NAME\n"); for (auto* task : tasks) { - ptr += ksprintf(ptr, "%w %w:%w %b %w %s\n", + ptr += ksprintf(ptr, "%w %w:%w %b %w %w %s\n", task->pid(), task->uid(), task->gid(), task->state(), task->timesScheduled(), + task->fileHandleCount(), task->name().characters()); } ptr += ksprintf(ptr, "kmalloc: alloc: %u / free: %u\n", sum_alloc, sum_free); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 1e70f9a510..4be04cbfac 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -66,6 +66,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3) break; case Syscall::Spawn: return current->sys$spawn((const char*)arg1); + case Syscall::GetDirEntries: + return current->sys$get_dir_entries((int)arg1, (void*)arg2, (size_t)arg3); case Syscall::PosixOpen: //kprintf("syscall: open('%s', %u)\n", arg1, arg2); return current->sys$open((const char*)arg1, (size_t)arg2); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 22f6fb3812..70b3f12983 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -26,6 +26,7 @@ enum Function { PosixWaitpid = 0x1994, PosixMmap = 0x1995, PosixMunmap = 0x1996, + GetDirEntries = 0x1997, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 331be38ffb..fe185cc154 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -230,6 +230,10 @@ Task::Task(String&& name, uid_t uid, gid_t gid) , m_state(Runnable) , m_ring(Ring3) { + m_fileHandles.append(nullptr); + m_fileHandles.append(nullptr); + m_fileHandles.append(nullptr); + m_nextRegion = LinearAddress(0x600000); memset(&m_tss, 0, sizeof(m_tss)); @@ -280,6 +284,10 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring) , m_state(Runnable) , m_ring(ring) { + m_fileHandles.append(nullptr); + m_fileHandles.append(nullptr); + m_fileHandles.append(nullptr); + m_nextRegion = LinearAddress(0x600000); Region* codeRegion = nullptr; @@ -643,6 +651,14 @@ FileHandle* Task::fileHandleIfExists(int fd) return nullptr; } +ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size) +{ + auto* handle = fileHandleIfExists(fd); + if (!handle) + return -1; + return handle->get_dir_entries((byte*)buffer, size); +} + int Task::sys$seek(int fd, int offset) { auto* handle = fileHandleIfExists(fd); diff --git a/Kernel/Task.h b/Kernel/Task.h index f79ccc267d..8ff28a00ed 100644 --- a/Kernel/Task.h +++ b/Kernel/Task.h @@ -101,6 +101,7 @@ public: pid_t sys$waitpid(pid_t); void* sys$mmap(void*, size_t size); int sys$munmap(void*, size_t size); + int sys$get_dir_entries(int fd, void*, size_t); struct { @@ -122,6 +123,8 @@ public: pid_t waitee() const { return m_waitee; } + size_t fileHandleCount() const { return m_fileHandles.size(); } + private: friend class MemoryManager; diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index 315825570efed2d33dad720c6d561cae18cbe31b..25f45186bf0759cb69e983cecd678b2f6563db67 100644 GIT binary patch delta 5019 zcmZoTVApWKZUYYsT7M7}S^;7}S{<7&Mp|7&Ipv8fZ^`V!FUqM}mRjmJ-B=$aeA}+3C-~z!1Q| zz!1p5z!1d1z!1#9z!1W~z!19mpjrIf?FtDT4}`Z};82iQtnfwz%KgKkAYwE}5Mqi6 zn9^X-V$fs=@2yecXnykHfBB!#&ZptQJ3w+T{`~*{zw>bGf$9D(91@yJoj1TDtp`d( zgMyk5a0g_FGB7ZJ#hQ-@ynbMKpf~kLbbRdg2`(I3Z1us-Z#W>5KmM2KbspZq0#n^7 zalAnQ6ygjF496Qp;4BF!>ot?%f#xF|(T7_P@V6{uU|?vr_|M-mmw|yHEI6?9So03B z=2D#<3<6O5I}diYfdsq7c1)LKVA#zdz);U{wxP2PWO!#E$l&faFgXn*!aNP6*z!Ud zi{XLSuH6EiVJuw%EFEEd$K5zUKJSiT?G5Hk>kQ*DywvT%YI(7YyURy_v%^P>-|6+c zV=jFB4BY{&y)FWronTXY-B_Zc;|?1hIBW}YQW^U(R$jRa><1Wjfw+bTUV=ih^*{+1 zm=ESnGiH>ZKFNqfV)EbHq0?QxIh4fm3sUn^GK&<_5;JpBQxvQ;xENH6xi&j~_GFxX z&xb=`a@9S7>3qH%0@LrAFd9tn%j6K4&S%Q#G<|_Dhrwi@`*MzoAjiWoGlMdm4Pr1e zsDLOqW@b=@vq21I2DRz_ri}WG%G3Y*ayZsIg9M?Nh2i6WKPVeSf%xGd1_J{FF9QRE z5CaQCJd_X08A1$F4CzolC`g4EL>M+g`9GLI>RB1`pnL(aep!Z6C?BF;w4R{`ML?LL z8OoOeYv5(*g7QHI3o&prOoH+u2Ffr@hw|mX>IE6*LHQD3z68T!C_e?vXJS|Z<%2vf z#Nf@zumLKdzzlLRI|DddFfcHH@}UreG{b(VyfoMVF@_^hJ|qMr8BRg@{L?l4IppP2 zGK*64O7xNo3K)t@QgSkrz|7RVlA=lwYx4UC;w-tjiFuRHf0LQs;m;waotTr8pUhB{ znwXN3S;UZ=n^?dQUtE${R00-b$W6@5V}K@`=@YpbrR&p*Qd1ciKslUIlz~Bvfq{X^ zhyfh$AigGuuff1z1)_Bs7(5vm7(n8nm}SynVDJF(#TXb^nHU%tB^VeCpmaEt&VbU} zpfsrLVH9Uzkbv^NLZOT@DBS|3k3nfxkj17@hv_hY6Cjfgl&{ACE>xK`85lrGfXR@7 zfgPmYWb>}?cNl|gNwid2qBUS2|0uSIA9Q5NGMJZ2;#_^?y!)9 zb^3)MjysGg(+6e$a|ho^i(XhgOX0j7z60hH$8Je&A(bFaS#i zhH%I;&YfNu!lACKzy}p&fH)dd)`2{c3kp#N1_m~0O4!TBz~DT2<1b;!Oa=x9P6h@B z2dGQ{9|NecU{Igz_*|Y9Js=M!K2Q=z`)JGzyPypBAQJb*%=t5z$Wyf znUH~G0x0joOjv|w!fAE}27ZtUmY|G-?A8J#6Znzb0LqA1Z=(4d#{(DEWh1I$OalonS;u$7KhoXaF~+aJ6&}2L=XYfV>M)H4oIx=?1rnAWf9! zBLcK)0hxgsR@j6oRji-~~w##Va347zo7_IT732i*-p*5Z~ zsnB>zg*KA#HlEC&jU`=Z<4Ko+!4*_PNir~idZD1k6R2Ke(uX#tv>-(=s1*oqOqtTD zF%>iYA0Hz(S4w7)UU5m0p`PLNixwQsuoe~zAEbq)fvtsQ18qxbOh;~E<-kPAZeh)V zwy-qdEv%EES{S2+wT6#@0n|kRRYUk%SSN9|u#P}m86XqzwXh!JY+;>2G67!;>l5}C z))ge}_*z&3;Pw-wi6sGMV>Gc8z`__!EDfAZtUE|{gOVbw<$&JAa>m)jiUv2P(3@DP zU{UlYRzB7yRxP|Ch2F&Kh0CBfvF74#V(kF8ku=epSWlo$EKoF~G_fW(zEsylZ&A&G zwx~d=L3Ix-Tq-ADd?`HH!^OwQb>O+rrtlg{y4~ciR@8wk^ENw(z|H07-$aX8-^I delta 3179 zcmZoTVApWKZUYYseW?9UC_CMuj4^5Yok9+7cD>?~B11jH z=@%_HTqYm*X)|4+oKb~y4L1XW0|Ntt+~kRm^EuyeGcXu{c+&$zIOHd5Jkj8k;eiP) z1PN6}d1F=nxfdQO$SQsGu#gh%63NxBc-^j-(Y&oBSfq|0&VmK&7LUjXq z!^^-Bu)VRGaX<4k8%9MTQ0y=;Fd*fat;UR-h{!Qk)8(TXC8j?x;y6K3zLAVW$~V*V z;~3i%6&M&~KDm@RJbF{*Hya5FGyfFgeS!6e3f&KQ(@ zF?|j{qXuUWTnv;kroZ85Tp+oJ8xkKFIb(Wa3M0;}afF+=tigsgYX~4^4LPh?;|h|i z@MR5~$&OEjrxyel%! zbjMN-@yQE*3ovqlnbQ}9atJUAO`ix7{_tCXlZPLYwv;Dx{*h0cgPkE5DXacKj;IU&qHNCe)5r62ruMpz2{| zu_4#=dBKcoye6Qw6Eg#Y3IhX!()5eLjMA(oybKJ>AVu;V0S1OSpd$G-^QJ2bB8+z? zE52x9l%Krpg$>Um1_p-aA53)u0Rdr?-@PzkTsB$$rB!`+@6;Fn{{Ii^oO(g1A`bN z0|S#b1A{DxR%c)U*Lp$>3|1h%3Il@+RGlZ39{{427#QL=>wf#p%(!B*;xBE+GEim} zo}BPYfb|3~1H*>NrN5L}uP`z&@Pd>7Wnuh3;tGTTrt`5 zw>slbaAsr#=Rj~~ +#include "stdio.h" + +extern "C" { + +DIR* opendir(const char* name) +{ + // FIXME: Should fail if it's not a directory! + int fd = open(name); + if (fd == -1) + return nullptr; + DIR* dirp = (DIR*)malloc(sizeof(dirp)); + dirp->fd = fd; + dirp->buffer = nullptr; + dirp->buffer_size = 0; + dirp->nextptr = nullptr; + return dirp; +} + +struct sys_dirent { + ino_t ino; + byte file_type; + size_t namelen; + char name[]; + size_t total_size() + { + return sizeof(ino_t) + sizeof(byte) + sizeof(size_t) + sizeof(char) * namelen; + } +} __attribute__ ((packed)); + +dirent* readdir(DIR* dirp) +{ + if (!dirp) + return nullptr; + if (dirp->fd == -1) + return nullptr; + + if (!dirp->buffer) { + // FIXME: Figure out how much to actually allocate. + dirp->buffer = (char*)malloc(4096); + ssize_t nread = Syscall::invoke(Syscall::GetDirEntries, (dword)dirp->fd, (dword)dirp->buffer, 4096); + dirp->buffer_size = nread; + dirp->nextptr = dirp->buffer; + } + + if (dirp->nextptr > (dirp->buffer + dirp->buffer_size)) + return nullptr; + + auto* sys_ent = (sys_dirent*)dirp->nextptr; + dirp->cur_ent.d_ino = sys_ent->ino; + dirp->cur_ent.d_type = sys_ent->file_type; + dirp->cur_ent.d_off = 0; + dirp->cur_ent.d_reclen = sys_ent->total_size(); + for (size_t i = 0; i < sys_ent->namelen; ++i) + dirp->cur_ent.d_name[i] = sys_ent->name[i]; + // FIXME: I think this null termination behavior is not supposed to be here. + dirp->cur_ent.d_name[sys_ent->namelen] = '\0'; + + dirp->nextptr += sys_ent->total_size(); + return &dirp->cur_ent; +} + +} + diff --git a/LibC/dirent.h b/LibC/dirent.h new file mode 100644 index 0000000000..be069d8133 --- /dev/null +++ b/LibC/dirent.h @@ -0,0 +1,27 @@ +#pragma once + +#include "types.h" + +extern "C" { + +struct dirent { + ino_t d_ino; + off_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +struct DIR { + int fd; + dirent cur_ent; + char* buffer; + size_t buffer_size; + char* nextptr; +}; + +DIR* opendir(const char* name); +dirent* readdir(DIR* dirp); + +} + diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp new file mode 100644 index 0000000000..7d0f1b5e8f --- /dev/null +++ b/LibC/stdlib.cpp @@ -0,0 +1,24 @@ +#include "stdlib.h" +#include "mman.h" + +extern "C" { + +void* malloc(size_t size) +{ + if (size > 4096) { + volatile char* crashme = (char*)0xc007d00d; + *crashme = 0; + } + void* ptr = mmap(nullptr, 4096); + return ptr; +} + +void free(void* ptr) +{ + if (!ptr) + return; + munmap(ptr, 4096); +} + +} + diff --git a/LibC/stdlib.h b/LibC/stdlib.h new file mode 100644 index 0000000000..55cd47c9f7 --- /dev/null +++ b/LibC/stdlib.h @@ -0,0 +1,11 @@ +#pragma once + +#include "types.h" + +extern "C" { + +void* malloc(size_t); +void free(void*); + +} + diff --git a/LibC/types.h b/LibC/types.h index fc990e79f7..cedc52280c 100644 --- a/LibC/types.h +++ b/LibC/types.h @@ -17,5 +17,8 @@ typedef dword pid_t; typedef dword size_t; typedef signed_dword ssize_t; +typedef dword ino_t; +typedef signed_dword off_t; + } diff --git a/Userland/ls.cpp b/Userland/ls.cpp index f6a90568b9..dfaa0d4eb2 100644 --- a/Userland/ls.cpp +++ b/Userland/ls.cpp @@ -1,21 +1,17 @@ #include #include -#include +#include int main(int c, char** v) { - int fd = open("/"); - if (fd == -1) { - printf("failed to open / :(\n"); + DIR* dirp = opendir("/"); + if (!dirp) { + printf("opendir failed :(\n"); return 1; } + while (auto* de = readdir(dirp)) { + printf("%s\n", de->d_name); - byte* memory = (byte*)mmap(nullptr, 16384); - printf("%p\n", memory); - memory[0] = 'H'; - memory[1] = 'i'; - memory[2] = '!'; - memory[3] = '\0'; - printf("%p : %s\n", memory, memory); + } return 0; } diff --git a/VirtualFileSystem/Ext2FileSystem.cpp b/VirtualFileSystem/Ext2FileSystem.cpp index 8e0dc9b87b..53fa6a3b66 100644 --- a/VirtualFileSystem/Ext2FileSystem.cpp +++ b/VirtualFileSystem/Ext2FileSystem.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "sys-errno.h" //#define EXT2_DEBUG @@ -431,49 +432,6 @@ bool Ext2FileSystem::addInodeToDirectory(unsigned directoryInode, unsigned inode return writeDirectoryInode(directoryInode, move(entries)); } -class BufferStream { -public: - explicit BufferStream(ByteBuffer& buffer) - : m_buffer(buffer) - { - } - - void operator<<(byte value) - { - m_buffer[m_offset++] = value & 0xffu; - } - - void operator<<(word value) - { - m_buffer[m_offset++] = value & 0xffu; - m_buffer[m_offset++] = (byte)(value >> 8) & 0xffu; - } - - void operator<<(dword value) - { - m_buffer[m_offset++] = value & 0xffu; - m_buffer[m_offset++] = (byte)(value >> 8) & 0xffu; - m_buffer[m_offset++] = (byte)(value >> 16) & 0xffu; - m_buffer[m_offset++] = (byte)(value >> 24) & 0xffu; - } - - void operator<<(const String& value) - { - for (unsigned i = 0; i < value.length(); ++i) - m_buffer[m_offset++] = value[i]; - } - - void fillToEnd(byte ch) - { - while (m_offset < m_buffer.size()) - m_buffer[m_offset++] = ch; - } - -private: - ByteBuffer& m_buffer; - Unix::size_t m_offset { 0 }; -}; - bool Ext2FileSystem::writeDirectoryInode(unsigned directoryInode, Vector&& entries) { kprintf("[ext2fs] New directory inode %u contents to write:\n", directoryInode); diff --git a/VirtualFileSystem/FileHandle.cpp b/VirtualFileSystem/FileHandle.cpp index 113a9a56c1..90c0beade2 100644 --- a/VirtualFileSystem/FileHandle.cpp +++ b/VirtualFileSystem/FileHandle.cpp @@ -3,6 +3,7 @@ #include "CharacterDevice.h" #include "sys-errno.h" #include "UnixTypes.h" +#include FileHandle::FileHandle(RetainPtr&& vnode) : m_vnode(move(vnode)) @@ -29,7 +30,7 @@ int FileHandle::stat(Unix::stat* buffer) if (!m_vnode) return -EBADF; - auto metadata = m_vnode->inode.metadata(); + auto metadata = m_vnode->metadata(); if (!metadata.isValid()) return -EIO; @@ -58,7 +59,7 @@ Unix::off_t FileHandle::seek(Unix::off_t offset, int whence) // FIXME: The file type should be cached on the vnode. // It's silly that we have to do a full metadata lookup here. - auto metadata = m_vnode->inode.metadata(); + auto metadata = m_vnode->metadata(); if (!metadata.isValid()) return -EIO; @@ -120,3 +121,27 @@ ByteBuffer FileHandle::readEntireFile() return m_vnode->fileSystem()->readEntireInode(m_vnode->inode); } +ssize_t FileHandle::get_dir_entries(byte* buffer, size_t size) +{ + Locker locker(VirtualFileSystem::lock()); + + auto metadata = m_vnode->metadata(); + if (!metadata.isValid()) + return -EIO; + if (!metadata.isDirectory()) + return -ENOTDIR; + + // FIXME: Compute the actual size needed. + auto tempBuffer = ByteBuffer::createUninitialized(2048); + BufferStream stream(tempBuffer); + m_vnode->vfs()->enumerateDirectoryInode(m_vnode->inode, [&stream] (const FileSystem::DirectoryEntry& entry) { + stream << (dword)entry.inode.index(); + stream << (byte)entry.fileType; + stream << (dword)entry.name.length(); + stream << entry.name; + return true; + }); + + memcpy(buffer, tempBuffer.pointer(), stream.offset()); + return stream.offset(); +} diff --git a/VirtualFileSystem/FileHandle.h b/VirtualFileSystem/FileHandle.h index 16956eb87c..f75d88895c 100644 --- a/VirtualFileSystem/FileHandle.h +++ b/VirtualFileSystem/FileHandle.h @@ -12,6 +12,8 @@ public: Unix::ssize_t read(byte* buffer, Unix::size_t count); int stat(Unix::stat*); + ssize_t get_dir_entries(byte* buffer, Unix::size_t); + ByteBuffer readEntireFile(); #ifdef SERENITY diff --git a/VirtualFileSystem/VirtualFileSystem.cpp b/VirtualFileSystem/VirtualFileSystem.cpp index c4c831b9c1..d7880a1b02 100644 --- a/VirtualFileSystem/VirtualFileSystem.cpp +++ b/VirtualFileSystem/VirtualFileSystem.cpp @@ -78,6 +78,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr fileSystem->retain(); vnode->inode = inode; + vnode->m_cachedMetadata = { }; #ifdef VFS_DEBUG kprintf("makeNode: inode=%u, size=%u, mode=%o, uid=%u, gid=%u\n", inode.index(), metadata.size, metadata.mode, metadata.uid, metadata.gid); @@ -85,6 +86,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr m_inode2vnode.set(inode, vnode.ptr()); vnode->m_characterDevice = characterDevice; + return vnode; } @@ -151,7 +153,7 @@ auto VirtualFileSystem::allocateNode() -> RetainPtr auto* node = m_nodeFreeList.takeLast(); ASSERT(node->retainCount == 0); node->retainCount = 1; - node->vfs = this; + node->m_vfs = this; return adopt(*node); } @@ -198,8 +200,7 @@ bool VirtualFileSystem::isRoot(InodeIdentifier inode) const return inode == m_rootNode->inode; } -template -void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode, F func) +void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode, Function callback) { if (!directoryInode.isValid()) return; @@ -216,7 +217,7 @@ void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode, ASSERT(mount); resolvedInode = mount->host(); } - func({ entry.name, resolvedInode }); + callback({ entry.name, resolvedInode }); return true; }); } @@ -340,6 +341,7 @@ void VirtualFileSystem::listDirectoryRecursively(const String& path) } else { kprintf("%s/%s\n", path.characters(), entry.name.characters()); } + return true; }); } @@ -467,10 +469,17 @@ void VirtualFileSystem::Node::release() { ASSERT(retainCount); if (--retainCount == 0) { - vfs->freeNode(this); + m_vfs->freeNode(this); } } +const InodeMetadata& VirtualFileSystem::Node::metadata() const +{ + if (!m_cachedMetadata.isValid()) + m_cachedMetadata = inode.metadata(); + return m_cachedMetadata; +} + VirtualFileSystem::Mount::Mount(InodeIdentifier host, RetainPtr&& guestFileSystem) : m_host(host) , m_guest(guestFileSystem->rootInode()) diff --git a/VirtualFileSystem/VirtualFileSystem.h b/VirtualFileSystem/VirtualFileSystem.h index 2fa31b51b9..bafb791d9f 100644 --- a/VirtualFileSystem/VirtualFileSystem.h +++ b/VirtualFileSystem/VirtualFileSystem.h @@ -6,12 +6,14 @@ #include #include #include +#include #include "InodeIdentifier.h" +#include "InodeMetadata.h" #include "Limits.h" +#include "FileSystem.h" class CharacterDevice; class FileHandle; -class FileSystem; class VirtualFileSystem { public: @@ -20,6 +22,7 @@ public: struct Node { InodeIdentifier inode; + const InodeMetadata& metadata() const; bool inUse() const { return inode.isValid(); } @@ -32,11 +35,15 @@ public: FileSystem* fileSystem() { return inode.fileSystem(); } const FileSystem* fileSystem() const { return inode.fileSystem(); } + VirtualFileSystem* vfs() { return m_vfs; } + const VirtualFileSystem* vfs() const { return m_vfs; } + private: friend class VirtualFileSystem; - VirtualFileSystem* vfs { nullptr }; + VirtualFileSystem* m_vfs { nullptr }; unsigned retainCount { 0 }; CharacterDevice* m_characterDevice { nullptr }; + mutable InodeMetadata m_cachedMetadata; }; static VirtualFileSystem& the(); @@ -68,7 +75,9 @@ public: void registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice&); private: - template void enumerateDirectoryInode(InodeIdentifier, F func); + friend class FileHandle; + + void enumerateDirectoryInode(InodeIdentifier, Function); InodeIdentifier resolvePath(const String& path); InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode);