diff --git a/lib/glacier/container/vector.h b/lib/glacier/container/vector.h index d212ee6..874e1ab 100644 --- a/lib/glacier/container/vector.h +++ b/lib/glacier/container/vector.h @@ -17,6 +17,21 @@ class Vector { other.size_ = 0; other.capacity_ = 0; } + Vector& operator=(Vector&& other) { + if (data_) { + delete[] data_; + } + + data_ = other.data_; + size_ = other.size_; + capacity_ = other.capacity_; + + other.data_ = nullptr; + other.size_ = 0; + other.capacity_ = 0; + + return *this; + } ~Vector() { if (data_) { diff --git a/sys/victoriafalls/fs/ext2/ext2_driver.cpp b/sys/victoriafalls/fs/ext2/ext2_driver.cpp index 68eeb3a..6c275bc 100644 --- a/sys/victoriafalls/fs/ext2/ext2_driver.cpp +++ b/sys/victoriafalls/fs/ext2/ext2_driver.cpp @@ -44,9 +44,11 @@ glcr::ErrorOr Ext2Driver::GetInode(uint32_t inode_number) { return inode_table_->GetInode(inode_number); } -glcr::ErrorCode Ext2Driver::ProbeDirectory(Inode* inode) { +glcr::ErrorOr> Ext2Driver::ReadDirectory( + uint32_t inode_number) { + ASSIGN_OR_RETURN(Inode * inode, inode_table_->GetInode(inode_number)); if (!(inode->mode & 0x4000)) { - dbgln("Probing non-directory"); + dbgln("Reading non directory."); return glcr::INVALID_ARGUMENT; } @@ -59,6 +61,7 @@ glcr::ErrorCode Ext2Driver::ProbeDirectory(Inode* inode) { return glcr::FAILED_PRECONDITION; } + glcr::Vector directory; for (uint64_t i = 0; i < real_block_cnt; i++) { dbgln("Getting block %lx", inode->block[i]); ASSIGN_OR_RETURN(MappedMemoryRegion block, @@ -66,6 +69,7 @@ glcr::ErrorCode Ext2Driver::ProbeDirectory(Inode* inode) { uint64_t addr = block.vaddr(); while (addr < block.vaddr() + ext2_reader_->BlockSize()) { DirEntry* entry = reinterpret_cast(addr); + directory.PushBack(*entry); glcr::String name(entry->name, entry->name_len); switch (entry->file_type) { case kExt2FtFile: @@ -80,5 +84,25 @@ glcr::ErrorCode Ext2Driver::ProbeDirectory(Inode* inode) { addr += entry->record_length; } } - return glcr::OK; + return directory; +} + +glcr::ErrorOr Ext2Driver::ReadFile(uint64_t inode_number) { + ASSIGN_OR_RETURN(Inode * inode, inode_table_->GetInode(inode_number)); + + if (!(inode->mode & 0x8000)) { + dbgln("Reading non file."); + return glcr::INVALID_ARGUMENT; + } + + // This calculation is cursed. + uint64_t real_block_cnt = + (inode->blocks - 1) / (ext2_reader_->BlockSize() / 512) + 1; + + if (real_block_cnt > 1) { + dbgln("Can't handle scatter-gather yet."); + return glcr::UNIMPLEMENTED; + } + + return ext2_reader_->ReadBlock(inode->block[0]); } diff --git a/sys/victoriafalls/fs/ext2/ext2_driver.h b/sys/victoriafalls/fs/ext2/ext2_driver.h index ee8fe7d..9487c16 100644 --- a/sys/victoriafalls/fs/ext2/ext2_driver.h +++ b/sys/victoriafalls/fs/ext2/ext2_driver.h @@ -15,7 +15,10 @@ class Ext2Driver { glcr::ErrorCode ProbePartition(); glcr::ErrorOr GetInode(uint32_t inode_number); - glcr::ErrorCode ProbeDirectory(Inode* inode); + + glcr::ErrorOr> ReadDirectory(uint32_t inode_number); + + glcr::ErrorOr ReadFile(uint64_t inode_number); private: glcr::SharedPtr ext2_reader_; diff --git a/sys/victoriafalls/victoriafalls.cpp b/sys/victoriafalls/victoriafalls.cpp index 9a28bc3..25919ba 100644 --- a/sys/victoriafalls/victoriafalls.cpp +++ b/sys/victoriafalls/victoriafalls.cpp @@ -20,9 +20,7 @@ uint64_t main(uint64_t init_cap) { denali_info.device_id(), denali_info.lba_offset()); ASSIGN_OR_RETURN(Ext2Driver ext2, Ext2Driver::Init(glcr::Move(denali))); - ASSIGN_OR_RETURN(Inode * root, ext2.GetInode(2)); - - ASSIGN_OR_RETURN(auto server, VFSServer::Create()); + ASSIGN_OR_RETURN(auto server, VFSServer::Create(ext2)); Thread server_thread = server->RunServer(); @@ -31,7 +29,6 @@ uint64_t main(uint64_t init_cap) { ASSIGN_OR_RETURN(auto client, server->CreateClient()); req.set_endpoint_capability(client.Capability()); check(yellowstone.RegisterEndpoint(req, empty)); - check(ext2.ProbeDirectory(root)); RET_ERR(server_thread.Join()); diff --git a/sys/victoriafalls/victoriafalls_server.cpp b/sys/victoriafalls/victoriafalls_server.cpp index 0867b19..d6ab24e 100644 --- a/sys/victoriafalls/victoriafalls_server.cpp +++ b/sys/victoriafalls/victoriafalls_server.cpp @@ -4,22 +4,47 @@ #include #include -glcr::ErrorOr> VFSServer::Create() { +glcr::ErrorOr> VFSServer::Create( + Ext2Driver& driver) { z_cap_t endpoint_cap; RET_ERR(ZEndpointCreate(&endpoint_cap)); - return glcr::UniquePtr(new VFSServer(endpoint_cap)); + return glcr::UniquePtr(new VFSServer(endpoint_cap, driver)); } glcr::ErrorCode VFSServer::HandleOpenFile(const OpenFileRequest& request, - OpenFileResponse&) { + OpenFileResponse& response) { auto path_tokens = glcr::StrSplit(request.path(), '/'); - for (uint64_t i = 0; i < path_tokens.size(); i++) { - dbgln("Token %u: '%s'", i, glcr::String(path_tokens.at(i)).cstr()); - } // Require all paths to be absolute rather than relative. // If the path starts with '/' then the first token will be empty. if (path_tokens.at(0) != "") { return glcr::INVALID_ARGUMENT; } - return glcr::UNIMPLEMENTED; + + ASSIGN_OR_RETURN(auto files, driver_.ReadDirectory(2)); + for (uint64_t i = 1; i < path_tokens.size() - 1; i++) { + for (uint64_t j = 0; j < files.size(); j++) { + if (path_tokens.at(i) == + glcr::StringView(files.at(j).name, files.at(j).name_len)) { + ASSIGN_OR_RETURN(files, driver_.ReadDirectory(files.at(j).inode)); + } + } + dbgln("Directory '%s' not found.", glcr::String(path_tokens.at(i)).cstr()); + return glcr::NOT_FOUND; + } + + MappedMemoryRegion region; + for (uint64_t j = 0; j < files.size(); j++) { + if (path_tokens.at(path_tokens.size() - 1) == + glcr::StringView(files.at(j).name, files.at(j).name_len)) { + ASSIGN_OR_RETURN(region, driver_.ReadFile(files.at(j).inode)); + } + } + if (!region) { + dbgln("File '%s' not found.", + glcr::String(path_tokens.at(path_tokens.size() - 1)).cstr()); + } + + response.set_path(request.path()); + response.set_memory(region.cap()); + return glcr::OK; } diff --git a/sys/victoriafalls/victoriafalls_server.h b/sys/victoriafalls/victoriafalls_server.h index 64dd89a..4b8b0e3 100644 --- a/sys/victoriafalls/victoriafalls_server.h +++ b/sys/victoriafalls/victoriafalls_server.h @@ -2,15 +2,20 @@ #include +#include "fs/ext2/ext2_driver.h" #include "victoriafalls/victoriafalls.yunq.server.h" class VFSServer : public VFSServerBase { public: - static glcr::ErrorOr> Create(); + static glcr::ErrorOr> Create(Ext2Driver& driver); glcr::ErrorCode HandleOpenFile(const OpenFileRequest&, OpenFileResponse&) override; private: - VFSServer(z_cap_t endpoint_cap) : VFSServerBase(endpoint_cap) {} + // FIXME: Don't store this as a reference. + Ext2Driver& driver_; + + VFSServer(z_cap_t endpoint_cap, Ext2Driver& driver) + : VFSServerBase(endpoint_cap), driver_(driver) {} }; diff --git a/sys/yellowstone/yellowstone.cpp b/sys/yellowstone/yellowstone.cpp index 32d4685..ec951b1 100644 --- a/sys/yellowstone/yellowstone.cpp +++ b/sys/yellowstone/yellowstone.cpp @@ -44,6 +44,7 @@ uint64_t main(uint64_t port_cap) { MappedMemoryRegion::FromCapability(response.memory()); dbgln("addr: %lu, size: %lu", file.vaddr(), file.size()); + dbgln("Test: '%s'", file.vaddr()); check(server_thread.Join()); dbgln("Yellowstone Finished Successfully.");