Compare commits
No commits in common. "ff468db6754acbc455bcc14fe991716655433863" and "89bea931cd01fdfec098068d05640a71c267e72a" have entirely different histories.
ff468db675
...
89bea931cd
@ -26,14 +26,13 @@ static bool can_write_segment(u32 flags)
|
||||
namespace ELFLoader
|
||||
{
|
||||
// FIXME: Check that all calls to read_contents() read the proper amount of bytes.
|
||||
Result<ELFData> load(SharedPtr<VFS::Inode> inode)
|
||||
Result<ELFData> load(const TarStream::Entry& elf_entry, const TarStream& stream)
|
||||
{
|
||||
Elf64_Ehdr elf_header;
|
||||
usize nread = TRY(inode->read((u8*)&elf_header, 0, sizeof elf_header));
|
||||
|
||||
usize nread = stream.read_contents(elf_entry, &elf_header, 0, sizeof elf_header);
|
||||
if (nread < sizeof elf_header)
|
||||
{
|
||||
kdbgln("Error while loading ELF: ELF header does not fit in file");
|
||||
kdbgln("Error while loading ELF: ELF header does not fit in entry");
|
||||
return err(ENOEXEC);
|
||||
}
|
||||
|
||||
@ -79,10 +78,10 @@ namespace ELFLoader
|
||||
usize i;
|
||||
Elf64_Phdr program_header;
|
||||
|
||||
for (TRY(inode->read((u8*)&program_header, elf_header.e_phoff, sizeof program_header)), i = 0;
|
||||
for (stream.read_contents(elf_entry, &program_header, elf_header.e_phoff, sizeof program_header), i = 0;
|
||||
i < elf_header.e_phnum;
|
||||
i++, TRY(inode->read((u8*)&program_header, elf_header.e_phoff + (i * elf_header.e_phentsize),
|
||||
sizeof program_header)))
|
||||
i++, stream.read_contents(elf_entry, &program_header, elf_header.e_phoff + (i * elf_header.e_phentsize),
|
||||
sizeof program_header))
|
||||
{
|
||||
if (program_header.p_type == PT_LOAD)
|
||||
{
|
||||
@ -104,7 +103,8 @@ namespace ELFLoader
|
||||
base_vaddr, get_blocks_from_size(program_header.p_memsz + vaddr_diff, ARCH_PAGE_SIZE), flags));
|
||||
|
||||
// Load the file section of the segment
|
||||
inode->read((u8*)program_header.p_vaddr, program_header.p_offset, program_header.p_filesz);
|
||||
stream.read_contents(elf_entry, (void*)program_header.p_vaddr, program_header.p_offset,
|
||||
program_header.p_filesz);
|
||||
|
||||
// Fill out the rest of the segment with 0s
|
||||
memset((void*)(program_header.p_vaddr + program_header.p_filesz), 0,
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "fs/VFS.h"
|
||||
#include <luna/LinkedList.h>
|
||||
#include <luna/TarStream.h>
|
||||
#include <luna/Types.h>
|
||||
|
||||
#define ELFMAG "\177ELF"
|
||||
@ -54,5 +54,5 @@ struct ELFData
|
||||
|
||||
namespace ELFLoader
|
||||
{
|
||||
Result<ELFData> load(SharedPtr<VFS::Inode> inode);
|
||||
Result<ELFData> load(const TarStream::Entry& elf_entry, const TarStream& stream);
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include "InitRD.h"
|
||||
#include "arch/MMU.h"
|
||||
#include "boot/bootboot.h"
|
||||
#include "fs/VFS.h"
|
||||
|
||||
TarStream g_initrd;
|
||||
extern const BOOTBOOT bootboot;
|
||||
@ -12,29 +11,3 @@ void InitRD::initialize()
|
||||
|
||||
g_initrd.initialize((void*)virtual_initrd_address, bootboot.initrd_size);
|
||||
}
|
||||
|
||||
static Result<void> vfs_create_dir_if_not_exists(const char* path)
|
||||
{
|
||||
auto rc = VFS::create_directory(path);
|
||||
if (rc.has_error())
|
||||
{
|
||||
if (rc.error() == EEXIST) return {};
|
||||
return rc.release_error();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> InitRD::populate_vfs()
|
||||
{
|
||||
TarStream::Entry entry;
|
||||
while (TRY(g_initrd.read_next_entry(entry)))
|
||||
{
|
||||
if (entry.type == TarStream::EntryType::RegularFile)
|
||||
{
|
||||
auto file = TRY(VFS::create_file(entry.name));
|
||||
file->write(entry.data(), 0, entry.size);
|
||||
}
|
||||
else if (entry.type == TarStream::EntryType::Directory) { TRY(vfs_create_dir_if_not_exists(entry.name)); }
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
@ -6,5 +6,4 @@ extern TarStream g_initrd;
|
||||
namespace InitRD
|
||||
{
|
||||
void initialize();
|
||||
Result<void> populate_vfs();
|
||||
}
|
||||
|
@ -15,41 +15,24 @@ namespace VFS
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
|
||||
SharedPtr<Inode> current_inode = root_fs->root_inode();
|
||||
kdbgln("vfs: trying to resolve path %s", path);
|
||||
|
||||
// FIXME: Properly handle relative paths.
|
||||
SharedPtr<Inode> current_inode;
|
||||
|
||||
if (parser.is_absolute()) { current_inode = root_fs->root_inode(); }
|
||||
else
|
||||
{
|
||||
kwarnln("vfs: cannot resolve path '%s', as relative paths are not supported yet", path);
|
||||
return err(ENOTSUP);
|
||||
}
|
||||
|
||||
const char* section;
|
||||
while (parser.next().try_set_value(section)) { current_inode = TRY(current_inode->find(section)); }
|
||||
while (parser.next().try_set_value(section))
|
||||
{
|
||||
kdbgln("vfs: searching for entry '%s' in inode %zu", section, current_inode->inode_number());
|
||||
current_inode = TRY(current_inode->find(section));
|
||||
}
|
||||
|
||||
return current_inode;
|
||||
}
|
||||
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path)
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
auto parent_path = TRY(parser.dirname());
|
||||
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars()));
|
||||
|
||||
auto child_name = TRY(parser.basename());
|
||||
|
||||
// kdbgln("vfs: creating directory '%s' in parent '%s'", child_name.chars(), parent_path.chars());
|
||||
|
||||
return parent_inode->create_subdirectory(child_name.chars());
|
||||
}
|
||||
|
||||
Result<SharedPtr<Inode>> create_file(const char* path)
|
||||
{
|
||||
auto parser = TRY(PathParser::create(path));
|
||||
auto parent_path = TRY(parser.dirname());
|
||||
|
||||
auto parent_inode = TRY(resolve_path(parent_path.chars()));
|
||||
|
||||
auto child_name = TRY(parser.basename());
|
||||
|
||||
// kdbgln("vfs: creating file '%s' in parent '%s'", child_name.chars(), parent_path.chars());
|
||||
|
||||
return parent_inode->create_file(child_name.chars());
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,6 @@ namespace VFS
|
||||
|
||||
virtual Result<SharedPtr<Inode>> create_subdirectory(const char* name) = 0;
|
||||
|
||||
// File-specific methods
|
||||
virtual Result<usize> read(u8* buf, usize offset, usize length) const = 0;
|
||||
|
||||
virtual Result<usize> write(const u8* buf, usize offset, usize length) = 0;
|
||||
|
||||
// Generic methods
|
||||
virtual FileSystem& fs() const = 0;
|
||||
|
||||
@ -78,8 +73,5 @@ namespace VFS
|
||||
|
||||
Result<SharedPtr<Inode>> resolve_path(const char* path);
|
||||
|
||||
Result<SharedPtr<Inode>> create_directory(const char* path);
|
||||
Result<SharedPtr<Inode>> create_file(const char* path);
|
||||
|
||||
Inode& root_inode();
|
||||
}
|
||||
|
@ -66,8 +66,6 @@ namespace TmpFS
|
||||
|
||||
Result<SharedPtr<VFS::Inode>> DirInode::create_file(const char* name)
|
||||
{
|
||||
if (find(name).has_value()) return err(EEXIST);
|
||||
|
||||
auto inode = TRY(m_fs->create_file_inode());
|
||||
|
||||
TRY(add_entry(inode, name));
|
||||
@ -77,45 +75,10 @@ namespace TmpFS
|
||||
|
||||
Result<SharedPtr<VFS::Inode>> DirInode::create_subdirectory(const char* name)
|
||||
{
|
||||
if (find(name).has_value()) return err(EEXIST);
|
||||
|
||||
auto inode = TRY(m_fs->create_dir_inode(m_self));
|
||||
|
||||
TRY(add_entry(inode, name));
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "fs/VFS.h"
|
||||
#include <luna/Atomic.h>
|
||||
#include <luna/Badge.h>
|
||||
#include <luna/Buffer.h>
|
||||
#include <luna/StaticString.h>
|
||||
#include <luna/Vector.h>
|
||||
|
||||
@ -59,15 +58,10 @@ namespace TmpFS
|
||||
return m_inode_number;
|
||||
}
|
||||
|
||||
Result<usize> read(u8*, usize, usize) const override;
|
||||
|
||||
Result<usize> write(const u8*, usize, usize) override;
|
||||
|
||||
virtual ~FileInode() = default;
|
||||
|
||||
private:
|
||||
VFS::FileSystem* m_fs;
|
||||
Buffer m_data_buffer;
|
||||
usize m_inode_number;
|
||||
};
|
||||
|
||||
@ -93,16 +87,6 @@ namespace TmpFS
|
||||
|
||||
Result<SharedPtr<VFS::Inode>> find(const char* name) const override;
|
||||
|
||||
Result<usize> read(u8*, usize, usize) const override
|
||||
{
|
||||
return err(EISDIR);
|
||||
}
|
||||
|
||||
Result<usize> write(const u8*, usize, usize) override
|
||||
{
|
||||
return err(EISDIR);
|
||||
}
|
||||
|
||||
VFS::FileSystem& fs() const override
|
||||
{
|
||||
return *m_fs;
|
||||
|
@ -51,7 +51,29 @@ static Result<void> try_init_vfs()
|
||||
{
|
||||
VFS::root_fs = TRY(TmpFS::FileSystem::create());
|
||||
|
||||
InitRD::populate_vfs();
|
||||
VFS::Inode& root_inode = VFS::root_inode();
|
||||
|
||||
kinfoln("root inode number: %zu", root_inode.inode_number());
|
||||
|
||||
kinfoln("root inode's '.' entry inode number: %zu", TRY(root_inode.find("."))->inode_number());
|
||||
kinfoln("root inode's '..' entry inode number: %zu", TRY(root_inode.find(".."))->inode_number());
|
||||
|
||||
TRY(root_inode.create_subdirectory("etc"));
|
||||
|
||||
kinfoln("root inode's 'etc' entry inode number: %zu", TRY(root_inode.find("etc"))->inode_number());
|
||||
|
||||
auto& etc = *TRY(root_inode.find("etc"));
|
||||
|
||||
kinfoln("etc inode's '.' entry inode number: %zu", TRY(etc.find("."))->inode_number());
|
||||
kinfoln("etc inode's '..' entry inode number: %zu", TRY(etc.find(".."))->inode_number());
|
||||
|
||||
TRY(etc.create_file("passwd"));
|
||||
|
||||
kinfoln("etc inode's 'passwd' entry inode number: %zu", TRY(etc.find("passwd"))->inode_number());
|
||||
|
||||
auto& passwd = *TRY(VFS::resolve_path("/etc/passwd"));
|
||||
|
||||
kinfoln("/etc/passwd's inode number: %zu", passwd.inode_number());
|
||||
|
||||
return {};
|
||||
}
|
||||
@ -63,9 +85,17 @@ static void init_vfs()
|
||||
|
||||
static Result<void> try_init_userspace()
|
||||
{
|
||||
auto app = TRY(VFS::resolve_path("/bin/app"));
|
||||
TarStream::Entry entry;
|
||||
while (TRY(g_initrd.read_next_entry(entry)))
|
||||
{
|
||||
if (entry.type == TarStream::EntryType::RegularFile)
|
||||
{
|
||||
kinfoln("Found file %s in initial ramdisk, of size %s and mode %#ho", entry.name,
|
||||
to_dynamic_unit(entry.size).release_value().chars(), entry.mode);
|
||||
|
||||
TRY(Scheduler::new_userspace_thread(app));
|
||||
if (!strcmp(entry.name, "bin/app")) { TRY(Scheduler::new_userspace_thread(entry, g_initrd)); }
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ namespace Scheduler
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> new_userspace_thread(SharedPtr<VFS::Inode> inode)
|
||||
Result<void> new_userspace_thread(const TarStream::Entry& entry, const TarStream& stream)
|
||||
{
|
||||
Thread* const thread = TRY(new_thread());
|
||||
|
||||
@ -139,7 +139,7 @@ namespace Scheduler
|
||||
|
||||
thread->init_regs_user();
|
||||
|
||||
const ELFData data = TRY(ELFLoader::load(inode));
|
||||
const ELFData data = TRY(ELFLoader::load(entry, stream));
|
||||
|
||||
thread->set_ip(data.entry);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "fs/VFS.h"
|
||||
#include "thread/Thread.h"
|
||||
#include <luna/TarStream.h>
|
||||
|
||||
namespace Scheduler
|
||||
{
|
||||
@ -13,7 +13,7 @@ namespace Scheduler
|
||||
Result<void> new_kernel_thread(void (*func)(void));
|
||||
Result<void> new_kernel_thread(void (*func)(void*), void* arg);
|
||||
|
||||
Result<void> new_userspace_thread(SharedPtr<VFS::Inode> inode);
|
||||
Result<void> new_userspace_thread(const TarStream::Entry& entry, const TarStream& stream);
|
||||
|
||||
Thread* pick_task();
|
||||
|
||||
|
@ -7,7 +7,6 @@ set(FREESTANDING_SOURCES
|
||||
src/Format.cpp
|
||||
src/NumberParsing.cpp
|
||||
src/CString.cpp
|
||||
src/CPath.cpp
|
||||
src/Units.cpp
|
||||
src/SystemError.cpp
|
||||
src/Bitmap.cpp
|
||||
|
@ -15,9 +15,7 @@ class Buffer
|
||||
|
||||
Result<void> try_resize(usize new_size);
|
||||
|
||||
Result<u8*> slice_at_end(usize size);
|
||||
|
||||
Result<u8*> slice(usize offset, usize size);
|
||||
Result<u8*> create_slice_at_end(usize size);
|
||||
|
||||
u8* data()
|
||||
{
|
||||
@ -29,16 +27,6 @@ class Buffer
|
||||
return m_data;
|
||||
}
|
||||
|
||||
u8* end()
|
||||
{
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
const u8* end() const
|
||||
{
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
usize size() const
|
||||
{
|
||||
return m_size;
|
||||
|
@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
char* basename(char*);
|
||||
char* dirname(char*);
|
@ -33,5 +33,4 @@ extern "C"
|
||||
[[deprecated]] char* strcat(char* dst, const char* src);
|
||||
|
||||
char* strchr(const char* str, int c);
|
||||
char* strrchr(const char* str, int c);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include <luna/CString.h>
|
||||
#include <luna/Heap.h>
|
||||
#include <luna/OwnedStringView.h>
|
||||
|
||||
class PathParser
|
||||
{
|
||||
@ -18,9 +17,6 @@ class PathParser
|
||||
return *m_original == '/';
|
||||
}
|
||||
|
||||
Result<OwnedStringView> basename();
|
||||
Result<OwnedStringView> dirname();
|
||||
|
||||
Option<const char*> next();
|
||||
|
||||
private:
|
||||
|
@ -20,14 +20,8 @@ class TarStream
|
||||
mode_t mode;
|
||||
EntryType type;
|
||||
|
||||
const u8* data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
private:
|
||||
usize m_pos;
|
||||
u8* m_data;
|
||||
usize pos;
|
||||
|
||||
friend class TarStream;
|
||||
};
|
||||
|
@ -32,15 +32,9 @@ Result<void> Buffer::try_resize(usize new_size)
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<u8*> Buffer::slice_at_end(usize size)
|
||||
Result<u8*> Buffer::create_slice_at_end(usize size)
|
||||
{
|
||||
usize old_size = m_size;
|
||||
TRY(try_resize(m_size + size));
|
||||
return m_data + old_size;
|
||||
}
|
||||
|
||||
Result<u8*> Buffer::slice(usize offset, usize size)
|
||||
{
|
||||
if (offset + size > m_size) { TRY(try_resize(offset + size)); }
|
||||
return m_data + offset;
|
||||
}
|
||||
|
@ -1,47 +0,0 @@
|
||||
#include <luna/CPath.h>
|
||||
#include <luna/CString.h>
|
||||
|
||||
static char dot[] = ".";
|
||||
|
||||
char* basename(char* path)
|
||||
{
|
||||
// If path is NULL, or the string's length is 0, return .
|
||||
if (!path) return dot;
|
||||
size_t len = strlen(path);
|
||||
if (!len) return dot;
|
||||
|
||||
// Strip trailing slashes.
|
||||
char* it = path + len - 1;
|
||||
while (*it == '/' && it != path) { it--; }
|
||||
*(it + 1) = 0;
|
||||
if (it == path) return path;
|
||||
|
||||
// Return path from the first character if there are no more slashes, or from the first character after the last
|
||||
// slash.
|
||||
char* beg = strrchr(path, '/');
|
||||
if (!beg) return path;
|
||||
return beg + 1;
|
||||
}
|
||||
|
||||
char* dirname(char* path)
|
||||
{
|
||||
// If path is NULL, or the string's length is 0, return .
|
||||
if (!path) return dot;
|
||||
size_t len = strlen(path);
|
||||
if (!len) return dot;
|
||||
|
||||
// Strip trailing slashes.
|
||||
char* it = path + len - 1;
|
||||
while (*it == '/' && it != path) { it--; }
|
||||
*(char*)(it + 1) = 0;
|
||||
if (it == path) return path;
|
||||
|
||||
// Search for the last slash. If there is none, return .
|
||||
// Otherwise, we end the string there and return.
|
||||
char* end = strrchr(path, '/');
|
||||
if (!end) return dot;
|
||||
if (end != path) *end = 0;
|
||||
else
|
||||
*(end + 1) = 0;
|
||||
return path;
|
||||
}
|
@ -126,15 +126,6 @@ extern "C"
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* strrchr(const char* str, int c)
|
||||
{
|
||||
const char* s = str + strlen(str);
|
||||
while (s != str && *s != (char)c) s--;
|
||||
if (s != str) return const_cast<char*>(s);
|
||||
if (*s == (char)c) return const_cast<char*>(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usize strlcpy(char* dest, const char* src, usize len)
|
||||
{
|
||||
usize src_len = strlen(src);
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <luna/CPath.h>
|
||||
#include <luna/PathParser.h>
|
||||
#include <luna/ScopeGuard.h>
|
||||
|
||||
Result<PathParser> PathParser::create(const char* path)
|
||||
{
|
||||
@ -33,29 +31,3 @@ Option<const char*> PathParser::next()
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<OwnedStringView> PathParser::basename()
|
||||
{
|
||||
char* copy = strdup(m_original);
|
||||
if (!copy) return err(ENOMEM);
|
||||
|
||||
auto guard = make_scope_guard([copy] { free_impl(copy); });
|
||||
|
||||
char* result = ::basename(copy);
|
||||
|
||||
// We must copy this as we cannot rely on the original string.
|
||||
return OwnedStringView::from_string_literal(result);
|
||||
}
|
||||
|
||||
Result<OwnedStringView> PathParser::dirname()
|
||||
{
|
||||
char* copy = strdup(m_original);
|
||||
if (!copy) return err(ENOMEM);
|
||||
|
||||
auto guard = make_scope_guard([copy] { free_impl(copy); });
|
||||
|
||||
char* result = ::dirname(copy);
|
||||
|
||||
// We must copy this as we cannot rely on the original string.
|
||||
return OwnedStringView::from_string_literal(result);
|
||||
}
|
||||
|
@ -45,8 +45,7 @@ Result<TarStream::Entry> TarStream::parse_header(const TarStream::TarHeader* hdr
|
||||
|
||||
entry.mode = (mode_t)parse_unsigned_integer(hdr->mode, nullptr, 8);
|
||||
|
||||
entry.m_pos = m_offset;
|
||||
entry.m_data = (u8*)m_base + m_offset;
|
||||
entry.pos = m_offset;
|
||||
|
||||
switch (hdr->typeflag)
|
||||
{
|
||||
@ -100,7 +99,7 @@ usize TarStream::read_contents(const Entry& entry, void* buf, usize offset, usiz
|
||||
if (offset >= entry.size) return 0;
|
||||
if ((length + offset) > entry.size) length = entry.size - offset;
|
||||
|
||||
memcpy(buf, offset_ptr(m_base, entry.m_pos + offset), length);
|
||||
memcpy(buf, offset_ptr(m_base, entry.pos + offset), length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user