diff --git a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp index 0d406aa4..accd02a0 100644 --- a/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp +++ b/deps/ox/src/ox/fs/filestore/filestoretemplate.hpp @@ -414,8 +414,9 @@ const ptrarith::Ptr FileStoreTemplate::read(InodeI template ox::Error FileStoreTemplate::resize() { oxReturnError(compact()); - oxReturnError(m_buffer->setSize(size() - available())); - oxTrace("ox::fs::FileStoreTemplate::resize") << "resize to:" << size() - available(); + const auto newSize = size() - available(); + oxTrace("ox::fs::FileStoreTemplate::resize") << "resize to:" << newSize; + oxReturnError(m_buffer->setSize(newSize)); oxTrace("ox::fs::FileStoreTemplate::resize") << "resized to:" << m_buffer->size(); return OxError(0); } diff --git a/deps/ox/src/ox/fs/filesystem/directory.hpp b/deps/ox/src/ox/fs/filesystem/directory.hpp index 43677b8f..1332ff83 100644 --- a/deps/ox/src/ox/fs/filesystem/directory.hpp +++ b/deps/ox/src/ox/fs/filesystem/directory.hpp @@ -25,7 +25,7 @@ struct __attribute__((packed)) DirectoryEntry { char name[MaxFileNameLength]; static constexpr std::size_t spaceNeeded(std::size_t chars) { - return offsetof(DirectoryEntryData, name) + chars; + return offsetof(DirectoryEntryData, name) + chars + 1; } }; @@ -227,35 +227,33 @@ ox::Error Directory::write(PathIterator path, InodeId_t in // find existing version of directory oxTrace("ox::fs::Directory::write") << "Searching for inode" << m_inodeId; auto old = m_fs.read(m_inodeId); - if (old.valid()) { - const auto entrySize = DirectoryEntry::spaceNeeded(name->len()); - const auto entryDataSize =DirectoryEntry::DirectoryEntryData::spaceNeeded(name->len()); - const auto newSize = m_size + entrySize; - auto cpy = ox_malloca(newSize, Buffer, old); - if (cpy != nullptr) { - // TODO: look for old version of this entry and delete it - - oxReturnError(cpy->setSize(newSize)); - auto val = cpy->malloc(entryDataSize); - if (val.valid()) { - oxTrace("ox::fs::Directory::write") << "Attempting to write Directory entry:" << name->data(); - oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; - oxReturnError(val->init(inode, name->data(), entrySize)); - return m_fs.write(m_inodeId, cpy, cpy->size()); - } else { - oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for new directory entry"; - return OxError(1); - } - } else { - oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for copy of Directory"; - return OxError(1); - } - } else { + if (!old.valid()) { oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory"; return OxError(1); } + + const auto entrySize = DirectoryEntry::spaceNeeded(name->len() + 1); // add 1 for \0 + const auto entryDataSize = DirectoryEntry::DirectoryEntryData::spaceNeeded(name->len()); + const auto newSize = Buffer::spaceNeeded(m_size + entrySize); + auto cpy = ox_malloca(newSize, Buffer, old); + if (cpy == nullptr) { + oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for copy of Directory"; + return OxError(1); + } + + // TODO: look for old version of this entry and delete it + oxReturnError(cpy->setSize(newSize)); + auto val = cpy->malloc(entryDataSize); + if (!val.valid()) { + oxTrace("ox::fs::Directory::write::fail") << "Could not allocate memory for new directory entry"; + return OxError(1); + } + + oxTrace("ox::fs::Directory::write") << "Attempting to write Directory entry:" << name->data(); + oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; + oxReturnError(val->init(inode, name->data(), entrySize)); + return m_fs.write(m_inodeId, cpy, cpy->size()); } - return OxError(1); } template @@ -324,7 +322,7 @@ ValErr Directory::findEntry auto data = i->data(); if (data.valid()) { oxTrace("ox::fs::Directory::findEntry").del("") << "Comparing \"" << name.c_str() << "\" to \"" << data->name << "\""; - if (ox_strncmp(data->name, name.c_str(), name.len()) == 0) { + if (ox_strncmp(data->name, name.c_str(), MaxFileNameLength) == 0) { // <-- TODO: bad compare oxTrace("ox::fs::Directory::findEntry").del("") << "\"" << name.c_str() << "\" match found."; return static_cast(data->inode); } @@ -345,9 +343,7 @@ ValErr Directory::find(Path // determine if already exists auto name = nameBuff; - if (path.get(name)) { - return {0, OxError(1)}; - } + oxReturnError(path.get(name)); auto v = findEntry(name->c_str()); if (!v.error) { diff --git a/deps/ox/src/ox/fs/filesystem/filesystem.hpp b/deps/ox/src/ox/fs/filesystem/filesystem.hpp index 529b9a7f..a511f4c6 100644 --- a/deps/ox/src/ox/fs/filesystem/filesystem.hpp +++ b/deps/ox/src/ox/fs/filesystem/filesystem.hpp @@ -225,6 +225,7 @@ ox::Error FileSystemTemplate::read(uint64_t inode, std::si template template ox::Error FileSystemTemplate::ls(const char *path, F cb) { + oxTrace("ox::FileSystemTemplate::ls") << "path:" << path; auto [s, err] = stat(path); oxReturnError(err); Directory dir(m_fs, s.inode); @@ -350,6 +351,10 @@ ValErr FileSystemTemplate::find(const char *path if (fd.error) { return {0, fd.error}; } + // return root as a special case + if (ox_strcmp(path, "/") == 0) { + return static_cast(fd.value.rootDirInode); + } Directory rootDir(m_fs, fd.value.rootDirInode); auto inode = rootDir.find(path); if (inode.error) { diff --git a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp index 0527c1d1..42186b9c 100644 --- a/deps/ox/src/ox/fs/filesystem/pathiterator.cpp +++ b/deps/ox/src/ox/fs/filesystem/pathiterator.cpp @@ -75,7 +75,7 @@ Error PathIterator::get(char *pathOut, std::size_t pathOutSize) { std::size_t end = substr - m_path; size = end - start; // cannot fit the output in the output parameter - if (size >= pathOutSize) { + if (size >= pathOutSize || size == 0) { return OxError(1); } ox_memcpy(pathOut, &m_path[start], size); diff --git a/deps/ox/src/ox/ptrarith/nodebuffer.hpp b/deps/ox/src/ox/ptrarith/nodebuffer.hpp index ff80fc35..ca3b7938 100644 --- a/deps/ox/src/ox/ptrarith/nodebuffer.hpp +++ b/deps/ox/src/ox/ptrarith/nodebuffer.hpp @@ -117,6 +117,12 @@ class __attribute__((packed)) NodeBuffer { [[nodiscard]] ItemPtr next(Item *item); + /** + * Like pointer but omits checks that assume the memory at the offset has + * already been initialed as an Item. + */ + [[nodiscard]] ItemPtr uninitializedPtr(size_t offset); + [[nodiscard]] ItemPtr ptr(size_t offset); [[nodiscard]] ItemPtr ptr(void *item); @@ -147,7 +153,7 @@ class __attribute__((packed)) NodeBuffer { * @return the actual number a bytes need to store the given number of * bytes */ - size_t spaceNeeded(size_t size); + static size_t spaceNeeded(size_t size); template [[nodiscard]] ox::Error compact(F cb = [](uint64_t, ItemPtr) {}); @@ -213,6 +219,23 @@ typename NodeBuffer::ItemPtr NodeBuffer::next(Item * return ptr(item->next); } +template +typename NodeBuffer::ItemPtr NodeBuffer::uninitializedPtr(size_t itemOffset) { + // make sure this can be read as an Item, and then use Item::size for the size + std::size_t itemSpace = m_header.size - itemOffset; + if (itemOffset >= sizeof(Header) && + itemOffset + itemSpace <= size() && + itemSpace >= sizeof(Item)) { + return ItemPtr(this, m_header.size, itemOffset, itemSpace); + } else { + //oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset:" << itemOffset; + //oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemOffset >= sizeof(Header):" << (itemOffset >= sizeof(Header)); + //oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= sizeof(Item):" << (itemSpace >= sizeof(Item)); + //oxTrace("ox::ptrarith::NodeBuffer::ptr::null") << "itemSpace >= item->fullSize():" << (itemSpace >= item->fullSize()); + return ItemPtr(this, m_header.size, 0, 0); + } +} + template typename NodeBuffer::ItemPtr NodeBuffer::ptr(size_t itemOffset) { // make sure this can be read as an Item, and then use Item::size for the size @@ -320,11 +343,12 @@ Error NodeBuffer::free(ItemPtr item) { template Error NodeBuffer::setSize(size_t size) { - oxTrace("ox::ptrarith::NodeBuffer::setSize") << size; + oxTrace("ox::ptrarith::NodeBuffer::setSize") << m_header.size << "to" << size; auto last = lastItem(); auto end = last.valid() ? last.end() : sizeof(m_header); oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end; if (end > size) { + // resizing to less than buffer size return OxError(1); } else { m_header.size = size; @@ -357,9 +381,16 @@ template ox::Error NodeBuffer::compact(F cb) { auto src = firstItem(); auto dest = ptr(sizeof(*this)); - while (src.valid() && dest.valid() && dest.offset() <= src.offset()) { + while (dest.offset() <= src.offset()) { + if (!src.valid()) { + return OxError(1); + } + if (!dest.valid()) { + dest.valid(); + return OxError(2); + } // move node - ox_memcpy(dest, src, src.size()); + ox_memcpy(dest, src, src->fullSize()); oxReturnError(cb(src, dest)); // update surrounding nodes auto prev = ptr(dest->prev); @@ -372,7 +403,7 @@ ox::Error NodeBuffer::compact(F cb) { } // update iterators src = ptr(dest->next); - dest = ptr(dest.offset() + dest.size()); + dest = uninitializedPtr(dest.offset() + dest->fullSize()); } return OxError(0); }