[ox/fs] Fix various file system bugs
This commit is contained in:
parent
fc337922ac
commit
7f5f74e2a6
@ -414,8 +414,9 @@ const ptrarith::Ptr<uint8_t, std::size_t> FileStoreTemplate<size_t>::read(InodeI
|
|||||||
template<typename size_t>
|
template<typename size_t>
|
||||||
ox::Error FileStoreTemplate<size_t>::resize() {
|
ox::Error FileStoreTemplate<size_t>::resize() {
|
||||||
oxReturnError(compact());
|
oxReturnError(compact());
|
||||||
oxReturnError(m_buffer->setSize(size() - available()));
|
const auto newSize = size() - available();
|
||||||
oxTrace("ox::fs::FileStoreTemplate::resize") << "resize to:" << 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();
|
oxTrace("ox::fs::FileStoreTemplate::resize") << "resized to:" << m_buffer->size();
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
56
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
56
deps/ox/src/ox/fs/filesystem/directory.hpp
vendored
@ -25,7 +25,7 @@ struct __attribute__((packed)) DirectoryEntry {
|
|||||||
char name[MaxFileNameLength];
|
char name[MaxFileNameLength];
|
||||||
|
|
||||||
static constexpr std::size_t spaceNeeded(std::size_t chars) {
|
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<FileStore, InodeId_t>::write(PathIterator path, InodeId_t in
|
|||||||
// find existing version of directory
|
// find existing version of directory
|
||||||
oxTrace("ox::fs::Directory::write") << "Searching for inode" << m_inodeId;
|
oxTrace("ox::fs::Directory::write") << "Searching for inode" << m_inodeId;
|
||||||
auto old = m_fs.read(m_inodeId);
|
auto old = m_fs.read(m_inodeId);
|
||||||
if (old.valid()) {
|
if (!old.valid()) {
|
||||||
const auto entrySize = DirectoryEntry<InodeId_t>::spaceNeeded(name->len());
|
|
||||||
const auto entryDataSize =DirectoryEntry<InodeId_t>::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 {
|
|
||||||
oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory";
|
oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory";
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto entrySize = DirectoryEntry<InodeId_t>::spaceNeeded(name->len() + 1); // add 1 for \0
|
||||||
|
const auto entryDataSize = DirectoryEntry<InodeId_t>::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<typename FileStore, typename InodeId_t>
|
template<typename FileStore, typename InodeId_t>
|
||||||
@ -324,7 +322,7 @@ ValErr<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::findEntry
|
|||||||
auto data = i->data();
|
auto data = i->data();
|
||||||
if (data.valid()) {
|
if (data.valid()) {
|
||||||
oxTrace("ox::fs::Directory::findEntry").del("") << "Comparing \"" << name.c_str() << "\" to \"" << data->name << "\"";
|
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.";
|
oxTrace("ox::fs::Directory::findEntry").del("") << "\"" << name.c_str() << "\" match found.";
|
||||||
return static_cast<InodeId_t>(data->inode);
|
return static_cast<InodeId_t>(data->inode);
|
||||||
}
|
}
|
||||||
@ -345,9 +343,7 @@ ValErr<typename FileStore::InodeId_t> Directory<FileStore, InodeId_t>::find(Path
|
|||||||
|
|
||||||
// determine if already exists
|
// determine if already exists
|
||||||
auto name = nameBuff;
|
auto name = nameBuff;
|
||||||
if (path.get(name)) {
|
oxReturnError(path.get(name));
|
||||||
return {0, OxError(1)};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto v = findEntry(name->c_str());
|
auto v = findEntry(name->c_str());
|
||||||
if (!v.error) {
|
if (!v.error) {
|
||||||
|
5
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
5
deps/ox/src/ox/fs/filesystem/filesystem.hpp
vendored
@ -225,6 +225,7 @@ ox::Error FileSystemTemplate<FileStore, Directory>::read(uint64_t inode, std::si
|
|||||||
template<typename FileStore, typename Directory>
|
template<typename FileStore, typename Directory>
|
||||||
template<typename F>
|
template<typename F>
|
||||||
ox::Error FileSystemTemplate<FileStore, Directory>::ls(const char *path, F cb) {
|
ox::Error FileSystemTemplate<FileStore, Directory>::ls(const char *path, F cb) {
|
||||||
|
oxTrace("ox::FileSystemTemplate::ls") << "path:" << path;
|
||||||
auto [s, err] = stat(path);
|
auto [s, err] = stat(path);
|
||||||
oxReturnError(err);
|
oxReturnError(err);
|
||||||
Directory dir(m_fs, s.inode);
|
Directory dir(m_fs, s.inode);
|
||||||
@ -350,6 +351,10 @@ ValErr<uint64_t> FileSystemTemplate<FileStore, Directory>::find(const char *path
|
|||||||
if (fd.error) {
|
if (fd.error) {
|
||||||
return {0, fd.error};
|
return {0, fd.error};
|
||||||
}
|
}
|
||||||
|
// return root as a special case
|
||||||
|
if (ox_strcmp(path, "/") == 0) {
|
||||||
|
return static_cast<uint64_t>(fd.value.rootDirInode);
|
||||||
|
}
|
||||||
Directory rootDir(m_fs, fd.value.rootDirInode);
|
Directory rootDir(m_fs, fd.value.rootDirInode);
|
||||||
auto inode = rootDir.find(path);
|
auto inode = rootDir.find(path);
|
||||||
if (inode.error) {
|
if (inode.error) {
|
||||||
|
@ -75,7 +75,7 @@ Error PathIterator::get(char *pathOut, std::size_t pathOutSize) {
|
|||||||
std::size_t end = substr - m_path;
|
std::size_t end = substr - m_path;
|
||||||
size = end - start;
|
size = end - start;
|
||||||
// cannot fit the output in the output parameter
|
// cannot fit the output in the output parameter
|
||||||
if (size >= pathOutSize) {
|
if (size >= pathOutSize || size == 0) {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
ox_memcpy(pathOut, &m_path[start], size);
|
ox_memcpy(pathOut, &m_path[start], size);
|
||||||
|
41
deps/ox/src/ox/ptrarith/nodebuffer.hpp
vendored
41
deps/ox/src/ox/ptrarith/nodebuffer.hpp
vendored
@ -117,6 +117,12 @@ class __attribute__((packed)) NodeBuffer {
|
|||||||
|
|
||||||
[[nodiscard]] ItemPtr next(Item *item);
|
[[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(size_t offset);
|
||||||
|
|
||||||
[[nodiscard]] ItemPtr ptr(void *item);
|
[[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
|
* @return the actual number a bytes need to store the given number of
|
||||||
* bytes
|
* bytes
|
||||||
*/
|
*/
|
||||||
size_t spaceNeeded(size_t size);
|
static size_t spaceNeeded(size_t size);
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
[[nodiscard]] ox::Error compact(F cb = [](uint64_t, ItemPtr) {});
|
[[nodiscard]] ox::Error compact(F cb = [](uint64_t, ItemPtr) {});
|
||||||
@ -213,6 +219,23 @@ typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::next(Item *
|
|||||||
return ptr(item->next);
|
return ptr(item->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename size_t, typename Item>
|
||||||
|
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::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 size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
|
typename NodeBuffer<size_t, Item>::ItemPtr NodeBuffer<size_t, Item>::ptr(size_t itemOffset) {
|
||||||
// make sure this can be read as an Item, and then use Item::size for the size
|
// make sure this can be read as an Item, and then use Item::size for the size
|
||||||
@ -320,11 +343,12 @@ Error NodeBuffer<size_t, Item>::free(ItemPtr item) {
|
|||||||
|
|
||||||
template<typename size_t, typename Item>
|
template<typename size_t, typename Item>
|
||||||
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
|
Error NodeBuffer<size_t, Item>::setSize(size_t size) {
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::setSize") << size;
|
oxTrace("ox::ptrarith::NodeBuffer::setSize") << m_header.size << "to" << size;
|
||||||
auto last = lastItem();
|
auto last = lastItem();
|
||||||
auto end = last.valid() ? last.end() : sizeof(m_header);
|
auto end = last.valid() ? last.end() : sizeof(m_header);
|
||||||
oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end;
|
oxTrace("ox::ptrarith::NodeBuffer::setSize") << "end:" << end;
|
||||||
if (end > size) {
|
if (end > size) {
|
||||||
|
// resizing to less than buffer size
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
} else {
|
} else {
|
||||||
m_header.size = size;
|
m_header.size = size;
|
||||||
@ -357,9 +381,16 @@ template<typename F>
|
|||||||
ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
|
ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
|
||||||
auto src = firstItem();
|
auto src = firstItem();
|
||||||
auto dest = ptr(sizeof(*this));
|
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
|
// move node
|
||||||
ox_memcpy(dest, src, src.size());
|
ox_memcpy(dest, src, src->fullSize());
|
||||||
oxReturnError(cb(src, dest));
|
oxReturnError(cb(src, dest));
|
||||||
// update surrounding nodes
|
// update surrounding nodes
|
||||||
auto prev = ptr(dest->prev);
|
auto prev = ptr(dest->prev);
|
||||||
@ -372,7 +403,7 @@ ox::Error NodeBuffer<size_t, Item>::compact(F cb) {
|
|||||||
}
|
}
|
||||||
// update iterators
|
// update iterators
|
||||||
src = ptr(dest->next);
|
src = ptr(dest->next);
|
||||||
dest = ptr(dest.offset() + dest.size());
|
dest = uninitializedPtr(dest.offset() + dest->fullSize());
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return OxError(0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user