2023-02-03 21:18:52 +00:00
|
|
|
#include "fs/tmpfs/FileSystem.h"
|
2023-03-18 08:10:33 +00:00
|
|
|
#include "fs/devices/DeviceRegistry.h"
|
2023-02-03 21:18:52 +00:00
|
|
|
#include <luna/Alloc.h>
|
2023-02-27 14:04:29 +00:00
|
|
|
#include <luna/CString.h>
|
2023-02-25 18:06:50 +00:00
|
|
|
#include <luna/Ignore.h>
|
2023-02-03 21:18:52 +00:00
|
|
|
|
|
|
|
namespace TmpFS
|
|
|
|
{
|
|
|
|
Result<SharedPtr<VFS::FileSystem>> FileSystem::create()
|
|
|
|
{
|
2023-03-07 21:16:52 +00:00
|
|
|
SharedPtr<FileSystem> fs = TRY(adopt_shared_if_nonnull(new (std::nothrow) FileSystem()));
|
2023-02-27 14:04:29 +00:00
|
|
|
SharedPtr<VFS::Inode> root = TRY(fs->create_dir_inode({}));
|
2023-03-28 23:06:26 +00:00
|
|
|
root->chmod(0755);
|
2023-02-25 17:03:11 +00:00
|
|
|
fs->set_root(root);
|
2023-02-03 21:18:52 +00:00
|
|
|
return (SharedPtr<VFS::FileSystem>)fs;
|
|
|
|
}
|
|
|
|
|
2023-02-25 17:03:11 +00:00
|
|
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_file_inode()
|
2023-02-03 21:18:52 +00:00
|
|
|
{
|
2023-02-25 17:11:39 +00:00
|
|
|
SharedPtr<FileInode> inode = TRY(make_shared<FileInode>());
|
2023-02-25 17:03:11 +00:00
|
|
|
inode->set_fs(*this, {});
|
2023-03-18 08:10:33 +00:00
|
|
|
inode->set_inode_number(m_next_inode_number++, {});
|
2023-02-25 17:03:11 +00:00
|
|
|
return (SharedPtr<VFS::Inode>)inode;
|
2023-02-03 21:18:52 +00:00
|
|
|
}
|
|
|
|
|
2023-02-27 14:04:29 +00:00
|
|
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_dir_inode(SharedPtr<VFS::Inode> parent)
|
2023-02-25 18:08:55 +00:00
|
|
|
{
|
|
|
|
SharedPtr<DirInode> inode = TRY(make_shared<DirInode>());
|
2023-03-10 20:09:08 +00:00
|
|
|
|
2023-02-25 18:22:05 +00:00
|
|
|
TRY(inode->add_entry(inode, "."));
|
2023-02-27 14:04:29 +00:00
|
|
|
TRY(inode->add_entry(parent ? parent : (SharedPtr<VFS::Inode>)inode, ".."));
|
2023-02-25 18:22:05 +00:00
|
|
|
|
2023-03-10 20:09:08 +00:00
|
|
|
inode->set_self(inode, {});
|
2023-02-25 18:08:55 +00:00
|
|
|
inode->set_fs(*this, {});
|
2023-03-18 08:10:33 +00:00
|
|
|
inode->set_inode_number(m_next_inode_number++, {});
|
2023-03-10 20:09:08 +00:00
|
|
|
|
2023-03-18 08:10:33 +00:00
|
|
|
return (SharedPtr<VFS::Inode>)inode;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<SharedPtr<VFS::Inode>> FileSystem::create_device_inode(u32 major, u32 minor)
|
|
|
|
{
|
|
|
|
SharedPtr<Device> device = TRY(DeviceRegistry::create_special_device(major, minor));
|
|
|
|
|
|
|
|
SharedPtr<DeviceInode> inode = TRY(make_shared<DeviceInode>());
|
|
|
|
inode->set_fs(*this, {});
|
|
|
|
inode->set_inode_number(m_next_inode_number++, {});
|
|
|
|
inode->set_device(device, {});
|
2023-03-10 20:09:08 +00:00
|
|
|
|
2023-02-25 18:08:55 +00:00
|
|
|
return (SharedPtr<VFS::Inode>)inode;
|
|
|
|
}
|
|
|
|
|
2023-02-25 17:03:11 +00:00
|
|
|
void FileSystem::set_root(SharedPtr<VFS::Inode> root)
|
2023-02-03 21:18:52 +00:00
|
|
|
{
|
|
|
|
m_root_inode = root;
|
|
|
|
}
|
2023-02-25 18:06:50 +00:00
|
|
|
|
|
|
|
Result<SharedPtr<VFS::Inode>> DirInode::find(const char* name) const
|
|
|
|
{
|
2023-02-25 18:22:05 +00:00
|
|
|
for (const auto& entry : m_entries)
|
|
|
|
{
|
2023-02-27 14:14:07 +00:00
|
|
|
if (!strcmp(name, entry.name.chars())) return entry.inode;
|
2023-02-25 18:22:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err(ENOENT);
|
|
|
|
}
|
|
|
|
|
2023-03-28 19:15:26 +00:00
|
|
|
Option<VFS::DirectoryEntry> DirInode::get(usize index) const
|
|
|
|
{
|
|
|
|
if (index >= m_entries.size()) return {};
|
|
|
|
|
|
|
|
return m_entries[index];
|
|
|
|
}
|
|
|
|
|
2023-02-25 18:22:05 +00:00
|
|
|
Result<void> DirInode::add_entry(SharedPtr<VFS::Inode> inode, const char* name)
|
|
|
|
{
|
2023-03-28 19:15:26 +00:00
|
|
|
if (find(name).has_value()) return err(EEXIST);
|
|
|
|
|
|
|
|
VFS::DirectoryEntry entry { inode, name };
|
2023-02-25 18:22:05 +00:00
|
|
|
|
|
|
|
TRY(m_entries.try_append(move(entry)));
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<SharedPtr<VFS::Inode>> DirInode::create_file(const char* name)
|
|
|
|
{
|
|
|
|
auto inode = TRY(m_fs->create_file_inode());
|
|
|
|
|
|
|
|
TRY(add_entry(inode, name));
|
|
|
|
|
|
|
|
return inode;
|
2023-02-25 18:06:50 +00:00
|
|
|
}
|
2023-03-10 20:09:08 +00:00
|
|
|
|
|
|
|
Result<SharedPtr<VFS::Inode>> DirInode::create_subdirectory(const char* name)
|
|
|
|
{
|
|
|
|
auto inode = TRY(m_fs->create_dir_inode(m_self));
|
|
|
|
|
|
|
|
TRY(add_entry(inode, name));
|
|
|
|
|
|
|
|
return inode;
|
|
|
|
}
|
2023-03-10 23:52:39 +00:00
|
|
|
|
|
|
|
Result<usize> FileInode::read(u8* buf, usize offset, usize length) const
|
|
|
|
{
|
|
|
|
if (length == 0) return 0;
|
|
|
|
|
|
|
|
if (offset > m_data_buffer.size()) return 0;
|
|
|
|
if (offset + length > m_data_buffer.size()) length = m_data_buffer.size() - offset;
|
|
|
|
|
|
|
|
memcpy(buf, m_data_buffer.data() + offset, length);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<usize> FileInode::write(const u8* buf, usize offset, usize length)
|
|
|
|
{
|
|
|
|
if (length == 0) return 0;
|
|
|
|
|
|
|
|
if (offset > m_data_buffer.size())
|
|
|
|
{
|
|
|
|
// Fill the in-between space with zeroes.
|
|
|
|
usize old_size = m_data_buffer.size();
|
|
|
|
usize zeroes = offset - old_size;
|
|
|
|
|
|
|
|
TRY(m_data_buffer.try_resize(offset));
|
|
|
|
|
|
|
|
memset(m_data_buffer.data() + old_size, 0, zeroes);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8* slice = TRY(m_data_buffer.slice(offset, length));
|
|
|
|
memcpy(slice, buf, length);
|
|
|
|
|
|
|
|
return length;
|
|
|
|
}
|
2023-03-12 13:43:58 +00:00
|
|
|
|
|
|
|
Result<void> FileInode::truncate(usize size)
|
|
|
|
{
|
|
|
|
usize old_size = m_data_buffer.size();
|
|
|
|
|
|
|
|
TRY(m_data_buffer.try_resize(size));
|
|
|
|
|
|
|
|
if (size > old_size) memset(m_data_buffer.data() + old_size, 0, size - old_size);
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
2023-03-12 13:49:21 +00:00
|
|
|
|
|
|
|
usize FileInode::size()
|
|
|
|
{
|
|
|
|
return m_data_buffer.size();
|
|
|
|
}
|
2023-02-03 21:18:52 +00:00
|
|
|
}
|