mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:57:35 +00:00
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().
This commit is contained in:
parent
0c5bbac86e
commit
bca4b71bfa
19 changed files with 277 additions and 67 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <AK/kmalloc.h>
|
||||
#include <AK/ktime.h>
|
||||
#include <AK/kstdio.h>
|
||||
#include <AK/BufferStream.h>
|
||||
#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<DirectoryEntry>&& entries)
|
||||
{
|
||||
kprintf("[ext2fs] New directory inode %u contents to write:\n", directoryInode);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "CharacterDevice.h"
|
||||
#include "sys-errno.h"
|
||||
#include "UnixTypes.h"
|
||||
#include <AK/BufferStream.h>
|
||||
|
||||
FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& 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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -78,6 +78,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
|
|||
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<Node>
|
|||
|
||||
m_inode2vnode.set(inode, vnode.ptr());
|
||||
vnode->m_characterDevice = characterDevice;
|
||||
|
||||
return vnode;
|
||||
}
|
||||
|
||||
|
@ -151,7 +153,7 @@ auto VirtualFileSystem::allocateNode() -> RetainPtr<Node>
|
|||
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<typename F>
|
||||
void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode, F func)
|
||||
void VirtualFileSystem::enumerateDirectoryInode(InodeIdentifier directoryInode, Function<bool(const FileSystem::DirectoryEntry&)> 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<FileSystem>&& guestFileSystem)
|
||||
: m_host(host)
|
||||
, m_guest(guestFileSystem->rootInode())
|
||||
|
|
|
@ -6,12 +6,14 @@
|
|||
#include <AK/String.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <AK/Lock.h>
|
||||
#include <AK/Function.h>
|
||||
#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<typename F> void enumerateDirectoryInode(InodeIdentifier, F func);
|
||||
friend class FileHandle;
|
||||
|
||||
void enumerateDirectoryInode(InodeIdentifier, Function<bool(const FileSystem::DirectoryEntry&)>);
|
||||
InodeIdentifier resolvePath(const String& path);
|
||||
InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue