diff --git a/deps/ox/src/ox/fs/CMakeLists.txt b/deps/ox/src/ox/fs/CMakeLists.txt index 3bd52825..9ab6e198 100644 --- a/deps/ox/src/ox/fs/CMakeLists.txt +++ b/deps/ox/src/ox/fs/CMakeLists.txt @@ -1,13 +1,10 @@ -cmake_minimum_required(VERSION 2.8) add_library( OxFS - filestore.cpp filestore/filestoretemplate.cpp - filesystem/filesystem.cpp filesystem/pathiterator.cpp - filesystem2/directory.cpp - filesystem2/filesystem.cpp + filesystem/directory.cpp + filesystem/filesystem.cpp ) set_property( @@ -35,13 +32,14 @@ endif() install( FILES - filestore.hpp + filestore/filestoretemplate.hpp DESTINATION - include/ox/fs + include/ox/fs/filestore ) install( FILES + filestore/filestoretemplate.hpp filesystem/filesystem.hpp filesystem/pathiterator.hpp DESTINATION diff --git a/deps/ox/src/ox/fs/filestore.cpp b/deps/ox/src/ox/fs/filestore.cpp deleted file mode 100644 index 1a943761..00000000 --- a/deps/ox/src/ox/fs/filestore.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include "filestore.hpp" - -namespace ox { - -template class FileStore>; -template class FileStore>; -template class FileStore>; - -} diff --git a/deps/ox/src/ox/fs/filestore.hpp b/deps/ox/src/ox/fs/filestore.hpp deleted file mode 100644 index e843988a..00000000 --- a/deps/ox/src/ox/fs/filestore.hpp +++ /dev/null @@ -1,929 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include - -namespace ox { - -template -struct __attribute__((packed)) FileStoreHeader { - public: - typedef InodeId InodeId_t; - typedef FsT FsSize_t; - const static auto VERSION = 7; - - private: - LittleEndian m_version; - LittleEndian m_fsType; - LittleEndian m_size; - LittleEndian m_memUsed; - LittleEndian m_rootInode; - - public: - void setVersion(uint16_t); - uint16_t getVersion(); - - void setFsType(uint16_t); - uint16_t getFsType(); - - void setSize(FsSize_t); - FsSize_t getSize(); - - void setMemUsed(FsSize_t); - FsSize_t getMemUsed(); - - void setRootInode(FsSize_t); - FsSize_t getRootInode(); -}; - -template -void FileStoreHeader::setVersion(uint16_t version) { - m_version = version; -} - -template -uint16_t FileStoreHeader::getVersion() { - return m_version; -} - -template -void FileStoreHeader::setFsType(uint16_t fsType) { - m_fsType = fsType; -} - -template -uint16_t FileStoreHeader::getFsType() { - return m_fsType; -} - -template -void FileStoreHeader::setSize(FsSize_t size) { - m_size = size; -} - -template -FsSize_t FileStoreHeader::getSize() { - return m_size; -} - -template -void FileStoreHeader::setMemUsed(FsSize_t memUsed) { - m_memUsed = memUsed; -} - -template -FsSize_t FileStoreHeader::getMemUsed() { - return m_memUsed; -} - -template -void FileStoreHeader::setRootInode(FsSize_t rootInode) { - m_rootInode = rootInode; -} - -template -FsSize_t FileStoreHeader::getRootInode() { - return m_rootInode; -} - -template -class FileStore { - - public: - typedef typename Header::InodeId_t InodeId_t; - typedef typename Header::FsSize_t FsSize_t; - const static auto VERSION = Header::VERSION; - - struct StatInfo { - InodeId_t inodeId; - InodeId_t links; - typename Header::FsSize_t size; - uint8_t fileType; - }; - - private: - struct __attribute__((packed)) Inode { - private: - // the next Inode in memory - LittleEndian m_prev; - LittleEndian m_next; - LittleEndian m_dataLen; - - LittleEndian m_id; - LittleEndian m_links; - LittleEndian m_fileType; - LittleEndian m_left; - LittleEndian m_right; - - public: - typename Header::FsSize_t size(); - - void setDataLen(typename Header::FsSize_t); - typename Header::FsSize_t getDataLen(); - - void setPrev(typename Header::FsSize_t); - typename Header::FsSize_t getPrev(); - - void setNext(typename Header::FsSize_t); - typename Header::FsSize_t getNext(); - - void setId(InodeId_t); - InodeId_t getId(); - - void setLinks(InodeId_t); - InodeId_t getLinks(); - - void setFileType(uint8_t); - uint8_t getFileType(); - - void setLeft(typename Header::FsSize_t); - typename Header::FsSize_t getLeft(); - - void setRight(typename Header::FsSize_t); - typename Header::FsSize_t getRight(); - - void setData(void *data, typename Header::FsSize_t size); - uint8_t *getData(); - }; - - Header m_header; - - public: - /** - * Dumps this file store's inodes to the given file store. - */ - int dumpTo(FileStore
*dest); - - /** - * Compacts and resizes the file store to the minimum possible size for - * the contents. - * - * NOTE: This does NOT resize the buffer that this file store refers to! - */ - void resize(typename Header::FsSize_t size = 0); - - /** - * Writes the given data to a "file" with the given id. - * @param id the id of the file - * @param data the contents of the file - * @param dataLen the number of bytes data points to - */ - int write(InodeId_t id, void *data, typename Header::FsSize_t dataLen, uint8_t fileType = 0); - - /** - * Removes the inode of the given ID. - * @param id the id of the file - */ - int remove(InodeId_t id); - - /** - * Increments the links of the inode of the given ID. - * @param id the id of the inode - */ - int incLinks(InodeId_t id); - - /** - * Decrements the links of the inode of the given ID. - * @param id the id of the inode - */ - int decLinks(InodeId_t id); - - /** - * Removes all inodes of the type. - * @param fileType the type of file to remove - */ - int removeAllType(uint8_t fileType); - - /** - * Reads the "file" at the given id. You are responsible for freeing - * the data when done with it. - * @param id id of the "file" - * @param data pointer to the pointer where the data is stored - * @param size pointer to a value that will be assigned the size of data - * @return 0 if read is a success - */ - int read(InodeId_t id, void *data, typename Header::FsSize_t *size); - - /** - * Reads the "file" at the given id. You are responsible for freeing - * the data when done with it. - * @param id id of the "file" - * @param readStart where in the data to start reading - * @param readSize how much data to read - * @param data pointer to the pointer where the data is stored - * @param size pointer to a value that will be assigned the size of data - * @return 0 if read is a success - */ - int read(InodeId_t id, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, void *data, - typename Header::FsSize_t *size); - - /** - * Reads the "file" at the given id. You are responsible for freeing - * the data when done with it. - * @param id id of the "file" - * @param readStart where in the data to start reading - * @param readSize how much data to read - * @param data pointer to the pointer where the data is stored - * @param size pointer to a value that will be assigned the size of data - * @return 0 if read is a success - */ - template - int read(InodeId_t id, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, T *data, - typename Header::FsSize_t *size); - - /** - * Reads the stat information of the inode of the given inode id. - * If the returned inode id is 0, then the requested inode was not found. - * @param id id of the inode to stat - * @return the stat information of the inode of the given inode id - */ - StatInfo stat(InodeId_t id); - - /** - * Returns the space needed for this data at the given inode address. - * @param id the target inode id - * @param size the size of the data to insert - * @return the space currently available in this file store. - */ - typename Header::FsSize_t spaceNeeded(typename Header::FsSize_t size); - - /** - * Returns the size of the file store. - * @return the size of the file store. - */ - typename Header::FsSize_t size(); - - /** - * Returns the space currently available in this file store. - * @return the space currently available in this file store. - */ - typename Header::FsSize_t available(); - - void walk(int(*cb)(const char*, uint64_t start, uint64_t end)); - - uint16_t fsType(); - - uint16_t version(); - - static uint8_t *format(uint8_t *buffer, typename Header::FsSize_t size, uint16_t fsType = 0); - - private: - /** - * Gets the inode at the given id. - * @param root the root node to start comparing on - * @param id id of the "file" - * @param pathLen number of characters in pathLen - * @return the requested Inode, if available - */ - Inode *getInode(Inode *root, InodeId_t id); - - /** - * Gets the parent inode at the given id. - * @param root the root node to start comparing on - * @param id id of the "file" - * @param pathLen number of characters in pathLen - * @param targetAddr the address of the target inode - * @return the requested Inode, if available - */ - Inode *getInodeParent(Inode *root, InodeId_t id, typename Header::FsSize_t targetAddr); - - /** - * Reads the "file" at the given id. You are responsible for freeing - * the data when done with it. - * @param inode inode of the "file" - * @param readStart where in the data to start reading - * @param readSize how much data to read - * @param data pointer to the pointer where the data is stored - * @param size pointer to a value that will be assigned the size of data - * @return 0 if read is a success - */ - template - int read(Inode *inode, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, T *data, - typename Header::FsSize_t *size); - - /** - * Removes the inode of the given ID. - * @param id the id of the file - */ - int remove(Inode *root, InodeId_t id); - - /** - * Removes the given node from the linked list. - * @param node node to remove - */ - void dealloc(Inode *node); - - /** - * Gets the address of the next available inode, assuming there is a next - * available inode. - */ - typename Header::FsSize_t nextInodeAddr(); - - /** - * Gets an address for a new Inode. - * @param size the size of the Inode - */ - void *alloc(typename Header::FsSize_t size); - - /** - * Compacts all of the inodes into a contiguous space, starting at the first inode. - */ - void compact(); - - /** - * Inserts the given insertValue into the tree of the given root. - * If the inode already exists, it replaces the old on deletes it. - * @return true if the inode was inserted - */ - bool insert(Inode *root, Inode *insertValue); - - typename Header::FsSize_t firstInode(); - - typename Header::FsSize_t lastInode(); - - /** - * Updates the address of the inode in the tree. - */ - void updateInodeAddress(InodeId_t id, typename Header::FsSize_t oldAddr, typename Header::FsSize_t newAddr); - - uint8_t *begin() { - return (uint8_t*) this; - } - - uint8_t *end() { - return begin() + this->m_header.getSize(); - } - - /** - * Converts an actual pointer to a FsSize_t. - */ - typename Header::FsSize_t ptr(void *ptr); - - /** - * Converts a FsSize_t to an actual pointer. - */ - template - T ptr(typename Header::FsSize_t ptr) { - return (T) (begin() + ptr); - }; - -}; - -template -typename Header::FsSize_t FileStore
::Inode::size() { - return sizeof(Inode) + getDataLen(); -} - -template -void FileStore
::Inode::setDataLen(typename Header::FsSize_t dataLen) { - this->m_dataLen = dataLen; -} - -template -typename Header::FsSize_t FileStore
::Inode::getDataLen() { - return m_dataLen; -} - -template -void FileStore
::Inode::setPrev(typename Header::FsSize_t prev) { - this->m_prev = prev; -} - -template -typename Header::FsSize_t FileStore
::Inode::getPrev() { - return m_prev; -} - -template -void FileStore
::Inode::setNext(typename Header::FsSize_t next) { - this->m_next = next; -} - -template -typename Header::FsSize_t FileStore
::Inode::getNext() { - return m_next; -} - -template -void FileStore
::Inode::setId(InodeId_t id) { - this->m_id = id; -} - -template -typename Header::InodeId_t FileStore
::Inode::getId() { - return m_id; -} - -template -void FileStore
::Inode::setLinks(InodeId_t links) { - this->m_links = links; -} - -template -typename Header::InodeId_t FileStore
::Inode::getLinks() { - return m_links; -} - -template -void FileStore
::Inode::setFileType(uint8_t fileType) { - this->m_fileType = fileType; -} - -template -uint8_t FileStore
::Inode::getFileType() { - return m_fileType; -} - -template -void FileStore
::Inode::setLeft(typename Header::FsSize_t left) { - this->m_left = left; -} - -template -typename Header::FsSize_t FileStore
::Inode::getLeft() { - return m_left; -} - -template -void FileStore
::Inode::setRight(typename Header::FsSize_t right) { - this->m_right = right; -} - -template -typename Header::FsSize_t FileStore
::Inode::getRight() { - return m_right; -} - -template -void FileStore
::Inode::setData(void *data, typename Header::FsSize_t size) { - ox_memcpy(getData(), data, size); - setDataLen(size); -} - -template -uint8_t *FileStore
::Inode::getData() { - return (uint8_t*) (this + 1); -} - - -// FileStore - -template -int FileStore
::dumpTo(FileStore
*dest) { - if (dest->size() >= size()) { - auto i = ptr(firstInode()); - do { - dest->write(i->getId(), i->getData(), i->getDataLen(), i->getFileType()); - i = ptr(i->getNext()); - } while (ptr(i) != firstInode()); - return 0; - } else { - return -1; - } -} - -template -void FileStore
::resize(typename Header::FsSize_t size) { - if (size < m_header.getSize()) { - // shrink file store - if (m_header.getMemUsed() > size) { - size = m_header.getMemUsed(); - } - compact(); - m_header.setSize(size); - } else if (size > m_header.getSize()) { - // grow file store - m_header.setSize(size); - } -} - -template -int FileStore
::write(InodeId_t id, void *data, typename Header::FsSize_t dataLen, uint8_t fileType) { - auto retval = 1; - const typename Header::FsSize_t size = sizeof(Inode) + dataLen; - if (size <= (m_header.getSize() - m_header.getMemUsed())) { - auto inode = (Inode*) alloc(size); - if (inode) { - remove(id); - inode->setId(id); - inode->setFileType(fileType); - inode->setData(data, dataLen); - auto root = ptr(m_header.getRootInode()); - if (insert(root, inode) || root == inode) { - retval = 0; - } else { - dealloc(inode); - retval = 2; - } - } else { - retval = 3; - } - } else { - retval = 4; - } - return retval; -} - -template -int FileStore
::remove(InodeId_t id) { - return remove(ptr(m_header.getRootInode()), id); -} - -/** - * Increments the links of the inode of the given ID. - * @param id the id of the inode - */ -template -int FileStore
::incLinks(InodeId_t id) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - if (inode) { - inode->setLinks(inode->getLinks() + 1); - return 0; - } else { - return 1; - } -} - -/** - * Decrements the links of the inode of the given ID. - * @param id the id of the inode - */ -template -int FileStore
::decLinks(InodeId_t id) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - if (inode) { - inode->setLinks(inode->getLinks() - 1); - return 0; - } else { - return 1; - } -} - -template -int FileStore
::remove(Inode *root, InodeId_t id) { - auto err = 1; - - if (root->getId() > id) { - if (root->getLeft()) { - auto left = ptr(root->getLeft()); - if (left->getId() != id) { - err = remove(left, id); - } else { - root->setLeft(0); - // pass children to parent - if (left->getRight()) { - insert(root, ptr(left->getRight())); - } - if (left->getLeft()) { - insert(root, ptr(left->getLeft())); - } - dealloc(left); - err = 0; - } - } - } else if (root->getId() < id) { - if (root->getRight()) { - auto right = ptr(root->getRight()); - if (right->getId() != id) { - err = remove(right, id); - } else { - root->setRight(0); - // pass children to parent - if (right->getRight()) { - insert(root, ptr(right->getRight())); - } - if (right->getLeft()) { - insert(root, ptr(right->getLeft())); - } - dealloc(right); - err = 0; - } - } - } else if (ptr(m_header.getRootInode())->getId() == id) { - m_header.setRootInode(root->getRight()); - if (root->getLeft()) { - insert(ptr(m_header.getRootInode()), ptr(root->getLeft())); - } - dealloc(root); - err = 0; - } - - return err; -} - -template -int FileStore
::removeAllType(uint8_t fileType) { - int err = 0; - auto first = ptr(firstInode()); - // skip the first inode for now, because removing the first inode will cause compact to run - auto current = first; - auto next = ptr(current->getNext()); - - while (next != first) { - current = next; - // get next before current is possibly cleared - next = ptr(current->getNext()); - - if (current->getFileType() == fileType) { - err |= remove(current->getId()); - } - } - - if (first->getFileType() == fileType) { - err |= remove(first->getId()); - } - - return err; -} - -template -void FileStore
::dealloc(Inode *inode) { - auto next = ptr(inode->getNext()); - auto prev = ptr(inode->getPrev()); - prev->setNext(ptr(next)); - next->setPrev(ptr(prev)); - - m_header.setMemUsed(m_header.getMemUsed() - inode->size()); - - ox_memset(inode, 0, inode->size()); -} - -template -void FileStore
::updateInodeAddress(InodeId_t id, typename Header::FsSize_t oldAddr, typename Header::FsSize_t newAddr) { - auto parent = getInodeParent(ptr(m_header.getRootInode()), id, oldAddr); - if (parent) { - if (parent->getLeft() == oldAddr) { - parent->setLeft(newAddr); - } else if (parent->getRight() == oldAddr) { - parent->setRight(newAddr); - } - } -} - -template -int FileStore
::read(InodeId_t id, void *data, typename Header::FsSize_t *size) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - return inode ? read(inode, 0, inode->getDataLen(), (uint8_t*) data, size) : 1; -} - -template -int FileStore
::read(InodeId_t id, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, void *data, typename Header::FsSize_t *size) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - return inode ? read(inode, readStart, readSize, (uint8_t*) data, size) : 1; -} - -template -template -int FileStore
::read(InodeId_t id, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, T *data, typename Header::FsSize_t *size) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - return inode ? read(inode, readStart, readSize, data, size) : 1; -} - -template -template -int FileStore
::read(Inode *inode, typename Header::FsSize_t readStart, - typename Header::FsSize_t readSize, T *data, typename Header::FsSize_t *size) { - // be sure read size is not greater than what is available to read - if (inode->getDataLen() - readStart < readSize) { - readSize = inode->getDataLen() - readStart; - } - if (size) { - *size = readSize; - } - - readSize /= sizeof(T); - uint8_t *it = &(inode->getData()[readStart]); - for (typename Header::FsSize_t i = 0; i < readSize; i++) { - // do byte-by-byte copy to ensure alignment is right when copying to - // final destination - T val; - for (std::size_t i = 0; i < sizeof(T); i++) { - ((uint8_t*) (&val))[i] = *(it++); - } - *(data++) = val; - } - return 0; -} - -template -typename FileStore
::StatInfo FileStore
::stat(InodeId_t id) { - auto inode = getInode(ptr(m_header.getRootInode()), id); - StatInfo stat; - if (inode) { - stat.size = inode->getDataLen(); - stat.fileType = inode->getFileType(); - stat.links = inode->getLinks(); - stat.inodeId = id; - } else { - stat.inodeId = 0; - } - return stat; -} - -template -typename Header::FsSize_t FileStore
::spaceNeeded(typename Header::FsSize_t size) { - return sizeof(Inode) + size; -} - -template -typename Header::FsSize_t FileStore
::size() { - return m_header.getSize(); -} - -template -typename Header::FsSize_t FileStore
::available() { - return m_header.getSize() - m_header.getMemUsed(); -} - -template -typename FileStore
::Inode *FileStore
::getInode(Inode *root, InodeId_t id) { - Inode *retval = nullptr; - - if (root->getId() > id) { - if (root->getLeft()) { - retval = getInode(ptr(root->getLeft()), id); - } - } else if (root->getId() < id) { - if (root->getRight()) { - retval = getInode(ptr(root->getRight()), id); - } - } else if (root->getId() == id) { - retval = root; - } - - return retval; -} - -template -typename FileStore
::Inode *FileStore
::getInodeParent(Inode *root, InodeId_t id, typename Header::FsSize_t targetAddr) { - Inode *retval = nullptr; - - if (root->getId() > id) { - if (root->getLeft()) { - if (root->getLeft() == targetAddr) { - retval = root; - } else { - retval = getInodeParent(ptr(root->getLeft()), id, targetAddr); - } - } - } else if (root->getId() < id) { - if (root->getRight()) { - if (root->getRight() == targetAddr) { - retval = root; - } else { - retval = getInodeParent(ptr(root->getRight()), id, targetAddr); - } - } - } - - return retval; -} - -template -typename Header::FsSize_t FileStore
::nextInodeAddr() { - return lastInode() + ptr(lastInode())->size(); -} - -template -void *FileStore
::alloc(typename Header::FsSize_t size) { - auto next = nextInodeAddr(); - if ((next + size) > ptr(end())) { - compact(); - next = nextInodeAddr(); - if ((next + size) > ptr(end())) { - return nullptr; - } - } - - const auto retval = next; - const auto inode = ptr(retval); - ox_memset(inode, 0, size); - inode->setPrev(ptr(firstInode())->getPrev()); - inode->setNext(firstInode()); - m_header.setMemUsed(m_header.getMemUsed() + size); - ptr(lastInode())->setNext(retval); - ptr(firstInode())->setPrev(retval); - return inode; -} - -template -void FileStore
::compact() { - auto dest = ptr(firstInode()); - auto current = ptr(firstInode()); - while (current->getNext() > firstInode() && current->getNext() < ptr(end())) { - ox_memcpy(dest, current, current->size()); - if (dest->getNext() != firstInode()) { - dest->setNext(ptr(dest) + dest->size()); - } - ptr(dest->getNext())->setPrev(ptr(dest)); - updateInodeAddress(dest->getId(), ptr(current), ptr(dest)); - current = ptr(dest->getNext()); - dest = ptr(ptr(dest) + dest->size()); - } -} - -template -bool FileStore
::insert(Inode *root, Inode *insertValue) { - auto retval = false; - - if (root->getId() > insertValue->getId()) { - if (root->getLeft()) { - retval = insert(ptr(root->getLeft()), insertValue); - } else { - root->setLeft(ptr(insertValue)); - retval = true; - } - } else if (root->getId() < insertValue->getId()) { - if (root->getRight()) { - retval = insert(ptr(root->getRight()), insertValue); - } else { - root->setRight(ptr(insertValue)); - retval = true; - } - } else if (m_header.getRootInode() == 0) { - m_header.setRootInode(ptr(insertValue)); - retval = true; - } - - return retval; -} - -template -typename Header::FsSize_t FileStore
::ptr(void *ptr) { -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - return ((uint8_t*) ptr) - begin(); -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif -} - -template -typename Header::FsSize_t FileStore
::firstInode() { - return sizeof(FileStore
); -} - -template -typename Header::FsSize_t FileStore
::lastInode() { - return ptr(firstInode())->getPrev(); -} - -template -uint16_t FileStore
::fsType() { - return m_header.getFsType(); -}; - -template -uint16_t FileStore
::version() { - return m_header.getVersion(); -}; - -template -void FileStore
::walk(int(*cb)(const char*, uint64_t start, uint64_t end)) { - auto err = cb("Header", 0, sizeof(Header)); - auto inode = ptr(firstInode()); - do { - auto start = ptr(inode); - err = cb("Inode", start, start + inode->size()); - inode = ptr(inode->getNext()); - } while (!err && inode != ptr(firstInode())); -} - -template -uint8_t *FileStore
::format(uint8_t *buffer, typename Header::FsSize_t size, uint16_t fsType) { - ox_memset(buffer, 0, size); - - auto *fs = (FileStore*) buffer; - fs->m_header.setFsType(fsType); - fs->m_header.setVersion(Header::VERSION); - fs->m_header.setSize(size); - fs->m_header.setMemUsed(sizeof(FileStore
) + sizeof(Inode)); - fs->m_header.setRootInode(sizeof(FileStore
)); - ((Inode*) (fs + 1))->setPrev(sizeof(FileStore
)); - ((Inode*) (fs + 1))->setNext(sizeof(FileStore
)); - - return (uint8_t*) buffer; -} - -extern template class FileStore>; -extern template class FileStore>; -extern template class FileStore>; - -typedef FileStore> FileStore16; -typedef FileStore> FileStore32; -typedef FileStore> FileStore64; - -} diff --git a/deps/ox/src/ox/fs/filesystem2/directory.cpp b/deps/ox/src/ox/fs/filesystem/directory.cpp similarity index 100% rename from deps/ox/src/ox/fs/filesystem2/directory.cpp rename to deps/ox/src/ox/fs/filesystem/directory.cpp diff --git a/deps/ox/src/ox/fs/filesystem/directory.hpp b/deps/ox/src/ox/fs/filesystem/directory.hpp index de5ed9ee..81bf9b32 100644 --- a/deps/ox/src/ox/fs/filesystem/directory.hpp +++ b/deps/ox/src/ox/fs/filesystem/directory.hpp @@ -8,201 +8,343 @@ #pragma once +#include +#include +#include #include -#include "types.hpp" - -namespace ox { - -template -struct DirectoryListing { - String name; - FileStat stat; - - DirectoryListing() = default; - - DirectoryListing(const char *name) { - this->name = name; - } -}; - -template -bool operator<(const DirectoryListing &a, const DirectoryListing &b) { - return a.name < b.name; -} - +namespace ox::fs { template struct __attribute__((packed)) DirectoryEntry { public: - InodeId_t inode = 0; + struct __attribute__((packed)) DirectoryEntryData { + // DirectoryEntry fields + LittleEndian inode = 0; + char name[MaxFileNameLength]; + + static constexpr std::size_t spaceNeeded(std::size_t chars) { + return offsetof(DirectoryEntryData, name) + chars; + } + + }; + + // NodeBuffer fields + LittleEndian prev = 0; + LittleEndian next = 0; + private: - uint32_t m_nameLen = 0; + LittleEndian m_bufferSize = sizeof(DirectoryEntry); public: - void *end() { - return ((uint8_t*) this) + size(); + DirectoryEntry() = default; + + DirectoryEntry(InodeId_t inode, const char *name, InodeId_t bufferSize) { + init(inode, name, bufferSize); } - char *getName() { - return (char*) (this + 1); + Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) { + m_bufferSize = bufferSize; + auto d = data(); + if (d.valid()) { + d->inode = inode; + ox_strncpy(d->name, name, ox::min(bufferSize, static_cast(MaxFileNameLength))); + return OxError(0); + } + return OxError(1); } - void setName(const char *name) { - auto data = getName(); - m_nameLen = ox_strlen(name); - ox_memcpy(data, name, m_nameLen); - data[m_nameLen] = 0; - } - - static uint64_t spaceNeeded(const char *fileName) { - return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1; + ptrarith::Ptr data() { + oxTrace("ox::fs::DirectoryEntry::data") << this->fullSize() << sizeof(*this) << this->size(); + return ptrarith::Ptr(this, this->fullSize(), sizeof(*this), this->size(), this->size()); } /** - * The size in bytes. + * @return the size of the data + the size of the Item type */ - uint64_t size() { - return sizeof(DirectoryEntry) + m_nameLen + 1; + InodeId_t fullSize() const { + return m_bufferSize; } + + InodeId_t size() const { + return fullSize() - sizeof(*this); + } + + void setSize(InodeId_t) { + // ignore set value + } + + static constexpr std::size_t spaceNeeded(std::size_t chars) { + return sizeof(DirectoryEntry) + offsetof(DirectoryEntryData, name) + chars; + } + }; -template -struct __attribute__((packed)) Directory { - /** - * Number of bytes after this Directory struct. - */ - FsSize_t size = 0; - FsSize_t children = 0; +template +class Directory { - DirectoryEntry *files() { - return size ? (DirectoryEntry*) (this + 1) : nullptr; - } + private: + using Buffer = ptrarith::NodeBuffer>; - void *end(); + InodeId_t m_inodeId = 0; + std::size_t m_size = 0; + FileStore *m_fs = nullptr; - uint64_t getFileInode(const char *name); + public: + Directory() = default; - int getChildrenInodes(InodeId_t *inodes, std::size_t inodesLen); + Directory(FileStore *fs, InodeId_t inode); - int rmFile(const char *name); + /** + * Initializes Directory. + */ + Error init() noexcept; - int copy(Directory *dirOut); + Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr); + + /** + * @param parents indicates the operation should create non-existent directories in the path, like mkdir -p + */ + Error write(PathIterator it, InodeId_t inode, bool parents = false, FileName *nameBuff = nullptr) noexcept; + + Error remove(PathIterator it, FileName *nameBuff = nullptr) noexcept; + + ValErr findEntry(const FileName &name) const noexcept; + + ValErr find(PathIterator name, FileName *nameBuff = nullptr) const noexcept; - template - int ls(List *list); }; -template -void *Directory::end() { - return ((int8_t*) this) + size; +template +Directory::Directory(FileStore *fs, InodeId_t inodeId) { + m_fs = fs; + m_inodeId = inodeId; + auto buff = fs->read(inodeId).template to(); + if (buff.valid()) { + m_size = buff.size(); + } } -template -uint64_t Directory::getFileInode(const char *name) { - uint64_t inode = 0; - auto current = files(); - if (current) { - for (uint64_t i = 0; ox_strcmp(current->getName(), name) != 0;) { - i += current->size(); - if (i < this->size) { - current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); - } else { - current = nullptr; - break; +template +Error Directory::init() noexcept { + constexpr auto Size = sizeof(Buffer); + oxReturnError(m_fs->write(m_inodeId, nullptr, Size)); + auto buff = m_fs->read(m_inodeId); + if (buff.valid()) { + new (buff) Buffer(Size); + m_size = Size; + return OxError(0); + } + m_size = 0; + return OxError(1); +} + +template +Error Directory::mkdir(PathIterator path, bool parents, FileName *nameBuff) { + if (path.valid()) { + oxTrace("ox::fs::Directory::mkdir") << path.fullPath(); + // reuse nameBuff if it has already been allocated, as it is a rather large variable + if (nameBuff == nullptr) { + nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); + } + + // determine if already exists + auto name = nameBuff; + path.get(name); + auto childInode = find(name->c_str()); + if (!childInode.ok()) { + // if this is not the last item in the path and parents is disabled, + // return an error + if (!parents && path.hasNext()) { + return OxError(1); + } + childInode = m_fs->generateInodeId(); + oxLogError(childInode.error); + oxReturnError(childInode.error); + + // initialize the directory + Directory child(m_fs, childInode); + oxReturnError(child.init()); + + auto err = write(name->c_str(), childInode, false); + if (err) { + oxLogError(err); + // could not index the directory, delete it + oxLogError(m_fs->remove(childInode)); + return err; } } - if (current) { - inode = current->inode; + + Directory child(m_fs, childInode); + if (path.hasNext()) { + oxReturnError(child.mkdir(path + 1, parents, nameBuff)); } } - return inode; + return OxError(0); } -template -int Directory::getChildrenInodes(InodeId_t *inodes, std::size_t inodesLen) { - if (inodesLen >= this->children) { - auto current = files(); - if (current) { - for (uint64_t i = 0; i < this->children; i++) { - if (ox_strcmp(current->getName(), ".") and ox_strcmp(current->getName(), "..")) { - inodes[i] = current->inode; - } - current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); - } - return 0; +template +Error Directory::write(PathIterator path, InodeId_t inode, bool parents, FileName *nameBuff) noexcept { + InodeId_t nextChild = 0; + + // reuse nameBuff if it has already been allocated, as it is a rather large variable + if (nameBuff == nullptr) { + nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); + } + auto name = nameBuff; + + if ((path + 1).hasNext()) { + oxTrace("ox::fs::Directory::write") << "Attempting to write to next sub-Directory"; + + oxReturnError(path.get(name)); + nextChild = findEntry(*name); + + if (!nextChild && parents) { + oxReturnError(Directory(m_fs, nextChild).init()); + nextChild = findEntry(*name); } else { - return 1; + return OxError(1); + } + + if (nextChild) { + // reuse name because it is a rather large variable and will not be used again + // be attentive that this remains true + name = nullptr; + return Directory(m_fs, nextChild).write(path + 1, inode, parents, nameBuff); } } else { - return 2; - } -} + // insert the new entry on this directory -template -int Directory::rmFile(const char *name) { - int err = 1; - auto current = files(); - if (current) { - for (uint64_t i = 0; i < this->size;) { - i += current->size(); - if (ox_strcmp(current->getName(), name) == 0) { - auto dest = (uint8_t*) current; - auto src = dest + current->size(); - ox_memcpy(dest, src, this->size - i); - this->size -= current->size(); - this->children--; - err = 0; - break; + // get the name + path.next(name); + + oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; + + // 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 + + cpy->setSize(newSize); + auto val = cpy->malloc(entryDataSize); + if (val.valid()) { + oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; + 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); } - current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); + } else { + oxTrace("ox::fs::Directory::write::fail") << "Could not read existing version of Directory"; + return OxError(1); } } - return err; + return OxError(1); } -template -int Directory::copy(Directory *dirOut) { - auto current = files(); - auto dirOutBuff = (uint8_t*) dirOut; - dirOutBuff += sizeof(Directory); - dirOut->size = this->size; - dirOut->children = this->children; - if (current) { - for (uint64_t i = 0; i < this->children; i++) { - auto entry = (DirectoryEntry*) dirOutBuff; - if (this->end() < current->end()) { - return 1; +template +Error Directory::remove(PathIterator path, FileName *nameBuff) noexcept { + // reuse nameBuff if it has already been allocated, as it is a rather large variable + if (nameBuff == nullptr) { + nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); + } + auto &name = *nameBuff; + oxReturnError(path.get(&name)); + + oxTrace("ox::fs::Directory::remove") << name.c_str(); + auto buff = m_fs->read(m_inodeId).template to(); + if (buff.valid()) { + oxTrace("ox::fs::Directory::remove") << "Found directory buffer."; + for (auto i = buff->iterator(); i.valid(); i.next()) { + auto data = i->data(); + if (data.valid()) { + if (ox_strncmp(data->name, name.c_str(), name.len()) == 0) { + buff->free(i); + } + } else { + oxTrace("ox::fs::Directory::remove") << "INVALID DIRECTORY ENTRY"; } - entry->inode = current->inode; - entry->setName(current->getName()); - - current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); - dirOutBuff += entry->size(); } } else { - return 2; + oxTrace("ox::fs::Directory::remove::fail") << "Could not find directory buffer"; + return OxError(1); } - return 0; + return OxError(0); } -template -template -int Directory::ls(List *list) { - auto current = files(); - if (current) { - for (uint64_t i = 0; i < this->children; i++) { - list->push_back(current->getName()); - (*list)[i].stat.inode = current->inode; - current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); +template +ValErr Directory::findEntry(const FileName &name) const noexcept { + oxTrace("ox::fs::Directory::findEntry") << name.c_str(); + auto buff = m_fs->read(m_inodeId).template to(); + if (buff.valid()) { + oxTrace("ox::fs::Directory::findEntry") << "Found directory buffer."; + for (auto i = buff->iterator(); i.valid(); i.next()) { + 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) { + return static_cast(data->inode); + } + } else { + oxTrace("ox::fs::Directory::findEntry") << "INVALID DIRECTORY ENTRY"; + } } - return 0; + oxTrace("ox::fs::Directory::findEntry::fail"); + return {0, OxError(1)}; } else { - return 1; + oxTrace("ox::fs::Directory::findEntry::fail") << "Could not findEntry directory buffer"; + return {0, OxError(2)}; } } +template +ValErr Directory::find(PathIterator path, FileName *nameBuff) const noexcept { + // reuse nameBuff if it has already been allocated, as it is a rather large variable + if (nameBuff == nullptr) { + nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); + } + + // determine if already exists + auto name = nameBuff; + if (path.get(name)) { + return {0, OxError(1)}; + } + + auto v = findEntry(name->c_str()); + if (!v.error) { + return v; + } + name = nullptr; + v = find(path + 1, nameBuff); + if (!v.error) { + return v; + } + + return {0, OxError(1)}; +} + + +extern template class Directory; +extern template class Directory; + +extern template struct DirectoryEntry; +extern template struct DirectoryEntry; + +using Directory16 = Directory; +using Directory32 = Directory; + } diff --git a/deps/ox/src/ox/fs/filesystem/filesystem.cpp b/deps/ox/src/ox/fs/filesystem/filesystem.cpp index d6f6fed9..a90a6f51 100644 --- a/deps/ox/src/ox/fs/filesystem/filesystem.cpp +++ b/deps/ox/src/ox/fs/filesystem/filesystem.cpp @@ -6,69 +6,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "filesystemtemplate.hpp" +#include "filesystem.hpp" -namespace ox { +namespace ox::fs { -template class FileSystemTemplate; -template class FileSystemTemplate; -template class FileSystemTemplate; - -FileSystem *createFileSystem(uint8_t *buff, std::size_t buffSize, bool ownsBuff) { - auto version = ((FileStore16*) buff)->version(); - auto type = ((FileStore16*) buff)->fsType(); - FileSystem *fs = nullptr; - - switch (version) { - case FileStore16::VERSION: - switch (type) { - case ox::OxFS_16: - fs = new FileSystem16(buff, ownsBuff); - break; - case ox::OxFS_32: - fs = new FileSystem32(buff, ownsBuff); - break; - case ox::OxFS_64: - fs = new FileSystem64(buff, ownsBuff); - break; - } - break; - default: - break; - } - - if (fs && fs->size() > buffSize) { - delete fs; - fs = nullptr; - } - - return fs; -} - -FileSystem *expandCopy(FileSystem *fs, std::size_t size) { - auto fsBuff = fs->buff(); - FileSystem *retval = nullptr; - - if (fs->size() <= size) { - auto cloneBuff = new uint8_t[size]; - ox_memcpy(cloneBuff, fsBuff, fs->size()); - - fsBuff = cloneBuff; - retval = createFileSystem(fsBuff, size); - retval->resize(size); - } - - return retval; -} - -FileSystem *expandCopyCleanup(FileSystem *fs, std::size_t size) { - auto out = expandCopy(fs, size); - - if (!out) { - out = fs; - } - - return out; -} +template class FileSystemTemplate; +template class FileSystemTemplate; } diff --git a/deps/ox/src/ox/fs/filesystem/filesystem.hpp b/deps/ox/src/ox/fs/filesystem/filesystem.hpp index 85d35e6b..ca9a5b60 100644 --- a/deps/ox/src/ox/fs/filesystem/filesystem.hpp +++ b/deps/ox/src/ox/fs/filesystem/filesystem.hpp @@ -8,52 +8,44 @@ #pragma once -#include +#include +#include #include "directory.hpp" -#include "pathiterator.hpp" -namespace ox { +namespace ox::fs { class FileSystem { + public: - virtual ~FileSystem() {}; + virtual Error format() = 0; - virtual int stripDirectories() = 0; - - virtual int mkdir(const char *path, bool recursive = false) = 0; + virtual Error mkdir(const char *path, bool recursive = false) = 0; /** * Moves an entry from one directory to another. * @param src the path to the file * @param dest the path of the destination directory */ - virtual int move(const char *src, const char *dest) = 0; + virtual Error move(const char *src, const char *dest) = 0; - template - int ls(const char *path, List *list); + virtual Error read(const char *path, void *buffer, std::size_t buffSize) = 0; - virtual int read(const char *path, void *buffer, std::size_t buffSize) = 0; + virtual Error read(uint64_t inode, void *buffer, std::size_t size) = 0; - virtual int read(uint64_t inode, void *buffer, std::size_t size) = 0; + virtual Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) = 0; - virtual int read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) = 0; + virtual Error remove(const char *path, bool recursive = false) = 0; - virtual uint8_t *read(uint64_t inode, std::size_t *size) = 0; + virtual void resize(uint64_t size, void *buffer = nullptr) = 0; - virtual int remove(uint64_t inode, bool recursive = false) = 0; + virtual Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - virtual int remove(const char *path, bool recursive = false) = 0; + virtual Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - virtual void resize(uint64_t size = 0) = 0; + virtual ValErr stat(uint64_t inode) = 0; - virtual int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - - virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - - virtual FileStat stat(uint64_t inode) = 0; - - virtual FileStat stat(const char *path) = 0; + virtual ValErr stat(const char *path) = 0; virtual uint64_t spaceNeeded(uint64_t size) = 0; @@ -63,39 +55,283 @@ class FileSystem { virtual uint8_t *buff() = 0; - virtual void walk(int(*cb)(const char*, uint64_t, uint64_t)) = 0; + virtual Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) = 0; + + virtual bool valid() const = 0; - protected: - virtual int readDirectory(const char *path, Directory *dirOut) = 0; }; -template -int FileSystem::ls(const char *path, List *list) { - typedef Directory Dir; - int err = 0; - auto s = stat(path); - if (s.fileType == FileType_Directory) { - uint8_t dirBuff[max(static_cast(s.size), sizeof(Dir)) * 4]; - auto dir = (Directory*) dirBuff; - err |= readDirectory(path, dir); - if (!err) { - err |= dir->ls(list); - } +/** + * FileSystemTemplate used to create file system that wraps around a FileStore, + * taking an inode size and a directory type as parameters. + * + * Note: Directory parameter must have a default constructor. + */ +template +class FileSystemTemplate: public FileSystem { + private: + static constexpr auto InodeFsData = 2; + + struct __attribute__((packed)) FileSystemData { + LittleEndian rootDirInode; + }; + + FileStore *m_fs = nullptr; + + public: + FileSystemTemplate(FileStore *fs); + + ~FileSystemTemplate(); + + Error format() override; + + Error mkdir(const char *path, bool recursive = false) override; + + Error move(const char *src, const char *dest) override; + + Error read(const char *path, void *buffer, std::size_t buffSize) override; + + Error read(uint64_t inode, void *buffer, std::size_t size) override; + + Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) override; + + Error remove(const char *path, bool recursive = false) override; + + void resize(uint64_t size, void *buffer = nullptr) override; + + Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; + + Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; + + ValErr stat(uint64_t inode) override; + + ValErr stat(const char *path) override; + + uint64_t spaceNeeded(uint64_t size) override; + + uint64_t available() override; + + uint64_t size() override; + + uint8_t *buff() override; + + Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) override; + + bool valid() const override; + + private: + ValErr fileSystemData() const noexcept; + + /** + * Finds the inode ID at the given path. + */ + ValErr find(const char *path) const noexcept; + + ValErr rootDir() const noexcept; + +}; + +template +FileSystemTemplate::FileSystemTemplate(FileStore *fs) { + m_fs = fs; +} + +template +FileSystemTemplate::~FileSystemTemplate() { +} + +template +Error FileSystemTemplate::format() { + oxReturnError(m_fs->format()); + + constexpr auto rootDirInode = MaxValue / 2; + Directory rootDir(m_fs, rootDirInode); + oxReturnError(rootDir.init()); + + FileSystemData fd; + fd.rootDirInode = rootDirInode; + oxTrace("ox::fs::FileSystemTemplate::format") << "rootDirInode:" << fd.rootDirInode; + oxReturnError(m_fs->write(InodeFsData, &fd, sizeof(fd))); + + if (m_fs->read(fd.rootDirInode).valid()) { + oxTrace("ox::fs::FileSystemTemplate::format::error") << "FileSystemTemplate::format did not correctly create root directory"; } - return err; + + return OxError(0); } -FileSystem *createFileSystem(uint8_t *buff, std::size_t buffSize, bool ownsBuff = false); +template +Error FileSystemTemplate::mkdir(const char *path, bool recursive) { + oxTrace("ox::fs::FileSystemTemplate::mkdir") << "path:" << path << "recursive:" << recursive; + auto rootDir = this->rootDir(); + oxReturnError(rootDir.error); + return rootDir.value.mkdir(path, recursive); +} -/** - * Creates a larger version of the given FileSystem. - */ -FileSystem *expandCopy(FileSystem *src); +template +Error FileSystemTemplate::move(const char *src, const char *dest) { + auto fd = fileSystemData(); + oxReturnError(fd.error); + Directory rootDir(m_fs, fd.value.rootDirInode); + auto inode = rootDir.find(src); + oxReturnError(inode.error); + oxReturnError(rootDir.write(dest, inode)); + oxReturnError(rootDir.remove(src)); + return OxError(0); +} -/** - * Calls expandCopy and deletes the original FileSystem and buff a resize was - * performed. - */ -FileSystem *expandCopyCleanup(FileSystem *fs, std::size_t size); +template +Error FileSystemTemplate::read(const char *path, void *buffer, std::size_t buffSize) { + auto fd = fileSystemData(); + oxReturnError(fd.error); + Directory rootDir(m_fs, fd.value.rootDirInode); + auto inode = rootDir.find(path); + oxReturnError(inode.error); + return read(inode, buffer, buffSize); +} + +template +Error FileSystemTemplate::read(uint64_t inode, void *buffer, std::size_t buffSize) { + return m_fs->read(inode, buffer, buffSize); +} + +template +Error FileSystemTemplate::read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) { + return m_fs->read(inode, readStart, readSize, buffer, size); +} + +template +Error FileSystemTemplate::remove(const char *path, bool recursive) { + auto fd = fileSystemData(); + oxReturnError(fd.error); + Directory rootDir(m_fs, fd.value.rootDirInode); + auto inode = rootDir.find(path); + oxReturnError(inode.error); + auto st = stat(inode); + oxReturnError(st.error); + if (st.value.fileType == FileType_NormalFile || recursive) { + if (auto err = rootDir.remove(path)) { + // removal failed, try putting the index back + oxLogError(rootDir.write(path, inode)); + return err; + } + } else { + oxTrace("FileSystemTemplate::remove::fail") << "Tried to remove directory without recursive setting."; + return OxError(1); + } + return OxError(0); +} + +template +void FileSystemTemplate::resize(uint64_t size, void *buffer) { + m_fs->resize(size, buffer); +} + +template +Error FileSystemTemplate::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) { + auto inode = find(path); + if (inode.error) { + inode.value = m_fs->generateInodeId(); + } + auto rootDir = this->rootDir(); + oxReturnError(rootDir.error); + oxReturnError(rootDir.value.write(path, inode)); + oxReturnError(write(inode, buffer, size, fileType)); + return 0; +} + +template +Error FileSystemTemplate::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) { + return m_fs->write(inode, buffer, size, fileType); +} + +template +ValErr FileSystemTemplate::stat(uint64_t inode) { + auto s = m_fs->stat(inode); + FileStat out; + out.inode = s.value.inode; + out.links = s.value.links; + out.size = s.value.size; + out.fileType = s.value.fileType; + return {out, s.error}; +} + +template +ValErr FileSystemTemplate::stat(const char *path) { + auto inode = find(path); + if (inode.error) { + return {{}, inode.error}; + } + return stat(inode.value); +} + +template +uint64_t FileSystemTemplate::spaceNeeded(uint64_t size) { + return m_fs->spaceNeeded(size); +} + +template +uint64_t FileSystemTemplate::available() { + return m_fs->available(); +} + +template +uint64_t FileSystemTemplate::size() { + return m_fs->size(); +} + +template +uint8_t *FileSystemTemplate::buff() { + return m_fs->buff(); +} + +template +Error FileSystemTemplate::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { + return m_fs->walk(cb); +} + +template +bool FileSystemTemplate::valid() const { + return m_fs && m_fs->valid(); +} + +template +ValErr::FileSystemData> FileSystemTemplate::fileSystemData() const noexcept { + FileSystemData fd; + auto err = m_fs->read(InodeFsData, &fd, sizeof(fd)); + if (err != 0) { + return {fd, err}; + } + return fd; +} + +template +ValErr FileSystemTemplate::find(const char *path) const noexcept { + auto fd = fileSystemData(); + if (fd.error) { + return {0, fd.error}; + } + Directory rootDir(m_fs, fd.value.rootDirInode); + auto inode = rootDir.find(path); + if (inode.error) { + return {0, inode.error}; + } + return inode.value; +} + +template +ValErr FileSystemTemplate::rootDir() const noexcept { + auto fd = fileSystemData(); + if (fd.error) { + return {{}, fd.error}; + } + return Directory(m_fs, fd.value.rootDirInode); +} + +extern template class FileSystemTemplate; +extern template class FileSystemTemplate; + +using FileSystem16 = FileSystemTemplate; +using FileSystem32 = FileSystemTemplate; } diff --git a/deps/ox/src/ox/fs/filesystem/filesystemtemplate.hpp b/deps/ox/src/ox/fs/filesystem/filesystemtemplate.hpp deleted file mode 100644 index fb6af523..00000000 --- a/deps/ox/src/ox/fs/filesystem/filesystemtemplate.hpp +++ /dev/null @@ -1,631 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include "filesystem.hpp" - -namespace ox { - -template -class FileSystemTemplate: public FileSystem { - - private: - FileStore *m_store = nullptr; - bool m_ownsBuff = false; - - public: - // static members - static typename FileStore::InodeId_t INODE_RANDOM; - static typename FileStore::InodeId_t INODE_ROOT_DIR; - static typename FileStore::InodeId_t INODE_RESERVED_END; - - explicit FileSystemTemplate(uint8_t *buff, bool ownsBuff = false); - - ~FileSystemTemplate(); - - int stripDirectories() override; - - int mkdir(const char *path, bool recursive = false) override; - - int read(const char *path, void *buffer, std::size_t buffSize) override; - - int read(uint64_t inode, void *buffer, std::size_t buffSize) override; - - int read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) override; - - uint8_t *read(uint64_t inode, std::size_t *size) override; - - void resize(uint64_t size = 0) override; - - int remove(uint64_t inode, bool recursive = false) override; - - int remove(const char *path, bool recursive = false) override; - - int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; - - int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; - - FileStat stat(const char *path) override; - - FileStat stat(uint64_t inode) override; - - uint64_t findInodeOf(const char *name); - - uint64_t spaceNeeded(uint64_t size) override; - - uint64_t available() override; - - uint64_t size() override; - - uint8_t *buff() override; - - int move(const char *src, const char *dest) override; - - /** - * Removes an entry from a directory. This does not delete the referred to file. - */ - int rmDirectoryEntry(const char *path); - - void walk(int(*cb)(const char*, uint64_t, uint64_t)) override; - - static uint8_t *format(uint8_t *buffer, typename FileStore::FsSize_t size, bool useDirectories); - - protected: - int readDirectory(const char *path, Directory *dirOut) override; - - private: - uint64_t generateInodeId(); - - int insertDirectoryEntry(const char *dirPath, const char *fileName, uint64_t inode); - - void expand(uint64_t size); -}; - -template -FileSystemTemplate::FileSystemTemplate(uint8_t *buff, bool ownsBuff) { - m_store = (FileStore*) buff; - m_ownsBuff = ownsBuff; -} - -template -FileSystemTemplate::~FileSystemTemplate() { - if (m_ownsBuff) { - delete[] (uint8_t*) m_store; - } -} - -template -typename FileStore::InodeId_t FileSystemTemplate::INODE_RANDOM = 1; - -template -typename FileStore::InodeId_t FileSystemTemplate::INODE_ROOT_DIR = 2; - -template -typename FileStore::InodeId_t FileSystemTemplate::INODE_RESERVED_END = 100; - -template -int FileSystemTemplate::stripDirectories() { - return m_store->removeAllType(FileType::FileType_Directory); -} - -template -int FileSystemTemplate::mkdir(const char *pathIn, bool recursive) { - if (!findInodeOf(pathIn)) { - auto pathLen = ox_strlen(pathIn); - char path[pathLen + 1]; - ox_memcpy(path, pathIn, pathLen + 1); - // make sure last character does not end with / - if (pathLen >= 1 && path[pathLen - 1] == '/') { - path[pathLen - 1] = 0; - pathLen--; - } - - char dirPath[pathLen]; - PathIterator pathReader(path, pathLen); - auto err = pathReader.dirPath(dirPath, pathLen); - - if (err) { - return err; - } - - // make sure parent directory exists if recursive - if (recursive and !findInodeOf(dirPath)) { - err |= mkdir(dirPath, recursive); - if (err) { - return err; - } - } - - Directory dir; - err |= write(path, &dir, sizeof(dir), FileType::FileType_Directory); - if (err) { - return err; - } - - // add . entry for self - auto inode = findInodeOf(path); - err = insertDirectoryEntry(path, ".", inode); - if (err) { - remove(inode); - return err; - } - - // add .. entry for parent - err |= insertDirectoryEntry(path, "..", findInodeOf(dirPath)); - if (err) { - remove(inode); - return err; - } - - return err; - } else { - return 1; - } -} - -template -FileStat FileSystemTemplate::stat(const char *path) { - auto inode = findInodeOf(path); - FileStat stat; - auto s = m_store->stat(inode); - stat.size = s.size; - stat.inode = s.inodeId; - stat.fileType = s.fileType; - return stat; -} - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -FileStat FileSystemTemplate::stat(uint64_t inode) { - FileStat stat; - auto s = m_store->stat(inode); - stat.size = s.size; - stat.inode = s.inodeId; - stat.links = s.links; - stat.fileType = s.fileType; - return stat; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::read(const char *path, void *buffer, std::size_t buffSize) { - int retval = -1; - - // find the inode for the given path - auto inode = findInodeOf(path); - - // if inode exists, read the data into buffer - if (inode) { - retval = read(inode, buffer, buffSize); - } - - return retval; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::read(uint64_t inode, void *buffer, std::size_t buffSize) { - auto stat = m_store->stat(inode); - if (stat.size <= buffSize) { - return m_store->read(inode, buffer, nullptr); - } - return -1; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::read(uint64_t inode, std::size_t readStart, - std::size_t readSize, void *buffer, - std::size_t *size) { - if (size) { - auto stat = m_store->stat(inode); - *size = stat.size; - } - return m_store->read(inode, readStart, readSize, buffer, nullptr); -} -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -uint8_t *FileSystemTemplate::read(uint64_t inode, std::size_t *size) { - auto s = m_store->stat(inode); - auto buff = new uint8_t[s.size]; - if (size) { - *size = s.size; - } - if (m_store->read(inode, buff, nullptr)) { - delete []buff; - buff = nullptr; - } - return buff; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -template -int FileSystemTemplate::remove(const char *path, bool recursive) { - auto inode = findInodeOf(path); - if (inode) { - return rmDirectoryEntry(path) | remove(inode, recursive); - } else { - return 1; - } -} - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::remove(uint64_t inode, bool recursive) { - auto fileType = stat(inode).fileType; - if (fileType != FileType::FileType_Directory) { - return m_store->remove(inode); - } else if (fileType == FileType::FileType_Directory && recursive) { - int err = 0; - auto dirStat = stat(inode); - auto dirBuffLen = dirStat.size; - uint8_t dirBuff[dirBuffLen]; - auto dir = (Directory*) dirBuff; - - err = read(dirStat.inode, dirBuff, dirBuffLen); - if (err) { - return 1; - } - - typename FileStore::InodeId_t inodes[dir->children]; - ox_memset(inodes, 0, sizeof(typename FileStore::InodeId_t) * dir->children); - dir->getChildrenInodes(inodes, dir->children); - - for (auto i : inodes) { - if (i) { - err |= remove(i, true); - } - } - - if (!err) { - err |= m_store->remove(inode); - } - - return err; - } else { - return 1; - } -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) { - int err = 0; - std::size_t pathLen = ox_strlen(path); - char dirPath[pathLen]; - char fileName[pathLen]; - PathIterator pathReader(path, pathLen); - err |= pathReader.fileName(fileName, pathLen); - err |= pathReader.dirPath(dirPath, pathLen); - if (err) { - return err; - } - - uint64_t inode = findInodeOf(path); - // find an inode value for the given path - if (!inode) { - inode = generateInodeId(); - err |= write(inode, buffer, 0, fileType); // ensure file exists before indexing it - err |= insertDirectoryEntry(dirPath, fileName, inode); - } - - if (!err) { - err = write(inode, buffer, size, fileType); - } - - return err; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) { - if (m_ownsBuff) { - while (m_store->spaceNeeded(size) > m_store->available()) { - expand(this->size() * 2); - } - } - return m_store->write(inode, buffer, size, fileType); -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -uint64_t FileSystemTemplate::findInodeOf(const char *path) { - const auto pathLen = ox_strlen(path); - PathIterator it(path, pathLen); - char fileName[pathLen]; - uint64_t inode = INODE_ROOT_DIR; - while (it.hasNext() && it.next(fileName, pathLen) == 0 && ox_strlen(fileName)) { - auto dirStat = stat(inode); - if (dirStat.inode && dirStat.size >= sizeof(Directory)) { - uint8_t dirBuffer[dirStat.size]; - auto dir = (Directory*) dirBuffer; - if (read(inode, dirBuffer, dirStat.size) == 0) { - if (dirStat.fileType == FileType::FileType_Directory) { - inode = dir->getFileInode(fileName); - } else { - inode = 0; // null out inode and break - break; - } - } else { - inode = 0; // null out inode and break - break; - } - } else { - inode = 0; // null out inode and break - break; - } - } - return inode; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -template -void FileSystemTemplate::resize(uint64_t size) { - return m_store->resize(size); -} - -template -uint64_t FileSystemTemplate::spaceNeeded(uint64_t size) { - return m_store->spaceNeeded(size); -} - -template -uint64_t FileSystemTemplate::available() { - return m_store->available(); -} - -template -uint64_t FileSystemTemplate::size() { - return m_store->size(); -} - -template -uint8_t *FileSystemTemplate::buff() { - return (uint8_t*) m_store; -} - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -uint8_t *FileSystemTemplate::format(uint8_t *buffer, typename FileStore::FsSize_t size, bool useDirectories) { - buffer = FileStore::format(buffer, size, (uint16_t) FS_TYPE); - - if (buffer && useDirectories) { - Directory dir; - FileSystemTemplate fs((uint8_t*) buffer); - fs.write(INODE_ROOT_DIR, &dir, sizeof(dir), FileType::FileType_Directory); - } - - return (uint8_t*) buffer; -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -template -uint64_t FileSystemTemplate::generateInodeId() { - Random rand; - read(INODE_RANDOM, &rand, sizeof(rand)); - - uint64_t inode = 0; - // find an inode value for the given path - while (!inode) { - inode = rand.gen(); - inode >>= 64 - 8 * sizeof(typename FileStore::InodeId_t); - - // make sure this does not already exist - if (inode < INODE_RESERVED_END || stat(inode).inode) { - // that result was unusable, try again - inode = 0; - } - } - - write(INODE_RANDOM, &rand, sizeof(rand)); - - return inode; -} - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif -template -int FileSystemTemplate::insertDirectoryEntry(const char *dirPath, const char *fileName, uint64_t inode) { - auto s = stat(dirPath); - if (s.inode) { - auto spaceNeeded = DirectoryEntry::spaceNeeded(fileName); - std::size_t dirBuffSize = s.size + spaceNeeded; - uint8_t dirBuff[dirBuffSize]; - int err = read(s.inode, dirBuff, dirBuffSize); - - if (!err) { - auto dir = (Directory*) dirBuff; - dir->size += spaceNeeded; - dir->children++; - auto entry = (DirectoryEntry*) &dirBuff[s.size]; - entry->inode = inode; - entry->setName(fileName); - err = write(s.inode, dirBuff, dirBuffSize, FileType_Directory); - err |= m_store->incLinks(inode); - return err; - } else { - return 1; - } - } else { - return 2; - } -} -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif - -template -int FileSystemTemplate::move(const char *src, const char *dest) { - auto inode = stat(src).inode; - if (inode && !stat(dest).inode) { - int err = 0; - - std::size_t srcLen = ox_strlen(src); - char srcDirPath[srcLen]; - char srcFileName[srcLen]; - PathIterator srcPathReader(src, srcLen); - err |= srcPathReader.fileName(srcFileName, srcLen); - err |= srcPathReader.dirPath(srcDirPath, srcLen); - if (err) { - return err; - } - - std::size_t destLen = ox_strlen(dest); - char destDirPath[destLen]; - char destFileName[destLen]; - PathIterator destPathReader(dest, destLen); - err |= destPathReader.fileName(destFileName, destLen); - err |= destPathReader.dirPath(destDirPath, destLen); - if (err) { - return err; - } - - err = rmDirectoryEntry(src); - if (err) { - return err; - } - - err = insertDirectoryEntry(destDirPath, destFileName, inode); - if (!err) { - return err; - } - - return 0; - } else { - return 1; - } -} - -template -int FileSystemTemplate::rmDirectoryEntry(const char *path) { - int err = 0; - std::size_t pathLen = ox_strlen(path); - char dirPath[pathLen]; - char fileName[pathLen]; - PathIterator pathReader(path, pathLen); - err |= pathReader.fileName(fileName, pathLen); - err |= pathReader.dirPath(dirPath, pathLen); - if (err) { - return err; - } - - auto dirStat = stat(dirPath); - auto dirBuffLen = dirStat.size; - uint8_t dirBuff[dirBuffLen]; - - err = read(dirStat.inode, dirBuff, dirBuffLen); - if (err) { - return err; - } - - auto dir = (Directory*) dirBuff; - auto inode = dir->getFileInode(fileName); - err |= dir->rmFile(fileName); - err |= m_store->decLinks(inode); - - if (err) { - return err; - } - - err = write(dirStat.inode, dirBuff, dirBuffLen - DirectoryEntry::spaceNeeded(fileName)); - - return err; -} - -template -int FileSystemTemplate::readDirectory(const char *path, Directory *dirOut) { - typedef Directory Dir; - int err = 0; - auto dirStat = stat(path); - auto dirBuffLen = ox::max(static_cast(dirStat.size), sizeof(Dir)); - uint8_t dirBuff[dirBuffLen]; - auto dir = (Dir*) dirBuff; - - err |= read(dirStat.inode, dirBuff, dirBuffLen); - if (!err) { - return dir->copy(dirOut); - } else { - return 1; - } -} - -template -void FileSystemTemplate::expand(uint64_t newSize) { - if (newSize > size()) { - auto newBuff = new uint8_t[newSize]; - ox_memcpy(newBuff, m_store, m_store->size()); - delete[] m_store; - m_store = (FileStore*) newBuff; - resize(newSize); - } -} - -template -void FileSystemTemplate::walk(int(*cb)(const char*, uint64_t, uint64_t)) { - m_store->walk(cb); -} - -extern template class FileSystemTemplate; -extern template class FileSystemTemplate; -extern template class FileSystemTemplate; - -typedef FileSystemTemplate FileSystem16; -typedef FileSystemTemplate FileSystem32; -typedef FileSystemTemplate FileSystem64; - -} diff --git a/deps/ox/src/ox/fs/filesystem2/directory.hpp b/deps/ox/src/ox/fs/filesystem2/directory.hpp deleted file mode 100644 index 81bf9b32..00000000 --- a/deps/ox/src/ox/fs/filesystem2/directory.hpp +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include -#include -#include - -namespace ox::fs { - -template -struct __attribute__((packed)) DirectoryEntry { - - public: - struct __attribute__((packed)) DirectoryEntryData { - // DirectoryEntry fields - LittleEndian inode = 0; - char name[MaxFileNameLength]; - - static constexpr std::size_t spaceNeeded(std::size_t chars) { - return offsetof(DirectoryEntryData, name) + chars; - } - - }; - - // NodeBuffer fields - LittleEndian prev = 0; - LittleEndian next = 0; - - - private: - LittleEndian m_bufferSize = sizeof(DirectoryEntry); - - public: - DirectoryEntry() = default; - - DirectoryEntry(InodeId_t inode, const char *name, InodeId_t bufferSize) { - init(inode, name, bufferSize); - } - - Error init(InodeId_t inode, const char *name, InodeId_t bufferSize) { - m_bufferSize = bufferSize; - auto d = data(); - if (d.valid()) { - d->inode = inode; - ox_strncpy(d->name, name, ox::min(bufferSize, static_cast(MaxFileNameLength))); - return OxError(0); - } - return OxError(1); - } - - ptrarith::Ptr data() { - oxTrace("ox::fs::DirectoryEntry::data") << this->fullSize() << sizeof(*this) << this->size(); - return ptrarith::Ptr(this, this->fullSize(), sizeof(*this), this->size(), this->size()); - } - - /** - * @return the size of the data + the size of the Item type - */ - InodeId_t fullSize() const { - return m_bufferSize; - } - - InodeId_t size() const { - return fullSize() - sizeof(*this); - } - - void setSize(InodeId_t) { - // ignore set value - } - - static constexpr std::size_t spaceNeeded(std::size_t chars) { - return sizeof(DirectoryEntry) + offsetof(DirectoryEntryData, name) + chars; - } - -}; - - -template -class Directory { - - private: - using Buffer = ptrarith::NodeBuffer>; - - InodeId_t m_inodeId = 0; - std::size_t m_size = 0; - FileStore *m_fs = nullptr; - - public: - Directory() = default; - - Directory(FileStore *fs, InodeId_t inode); - - /** - * Initializes Directory. - */ - Error init() noexcept; - - Error mkdir(PathIterator path, bool parents, FileName *nameBuff = nullptr); - - /** - * @param parents indicates the operation should create non-existent directories in the path, like mkdir -p - */ - Error write(PathIterator it, InodeId_t inode, bool parents = false, FileName *nameBuff = nullptr) noexcept; - - Error remove(PathIterator it, FileName *nameBuff = nullptr) noexcept; - - ValErr findEntry(const FileName &name) const noexcept; - - ValErr find(PathIterator name, FileName *nameBuff = nullptr) const noexcept; - -}; - -template -Directory::Directory(FileStore *fs, InodeId_t inodeId) { - m_fs = fs; - m_inodeId = inodeId; - auto buff = fs->read(inodeId).template to(); - if (buff.valid()) { - m_size = buff.size(); - } -} - -template -Error Directory::init() noexcept { - constexpr auto Size = sizeof(Buffer); - oxReturnError(m_fs->write(m_inodeId, nullptr, Size)); - auto buff = m_fs->read(m_inodeId); - if (buff.valid()) { - new (buff) Buffer(Size); - m_size = Size; - return OxError(0); - } - m_size = 0; - return OxError(1); -} - -template -Error Directory::mkdir(PathIterator path, bool parents, FileName *nameBuff) { - if (path.valid()) { - oxTrace("ox::fs::Directory::mkdir") << path.fullPath(); - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); - } - - // determine if already exists - auto name = nameBuff; - path.get(name); - auto childInode = find(name->c_str()); - if (!childInode.ok()) { - // if this is not the last item in the path and parents is disabled, - // return an error - if (!parents && path.hasNext()) { - return OxError(1); - } - childInode = m_fs->generateInodeId(); - oxLogError(childInode.error); - oxReturnError(childInode.error); - - // initialize the directory - Directory child(m_fs, childInode); - oxReturnError(child.init()); - - auto err = write(name->c_str(), childInode, false); - if (err) { - oxLogError(err); - // could not index the directory, delete it - oxLogError(m_fs->remove(childInode)); - return err; - } - } - - Directory child(m_fs, childInode); - if (path.hasNext()) { - oxReturnError(child.mkdir(path + 1, parents, nameBuff)); - } - } - return OxError(0); -} - -template -Error Directory::write(PathIterator path, InodeId_t inode, bool parents, FileName *nameBuff) noexcept { - InodeId_t nextChild = 0; - - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); - } - auto name = nameBuff; - - if ((path + 1).hasNext()) { - oxTrace("ox::fs::Directory::write") << "Attempting to write to next sub-Directory"; - - oxReturnError(path.get(name)); - nextChild = findEntry(*name); - - if (!nextChild && parents) { - oxReturnError(Directory(m_fs, nextChild).init()); - nextChild = findEntry(*name); - } else { - return OxError(1); - } - - if (nextChild) { - // reuse name because it is a rather large variable and will not be used again - // be attentive that this remains true - name = nullptr; - return Directory(m_fs, nextChild).write(path + 1, inode, parents, nameBuff); - } - } else { - // insert the new entry on this directory - - // get the name - path.next(name); - - oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; - - // 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 - - cpy->setSize(newSize); - auto val = cpy->malloc(entryDataSize); - if (val.valid()) { - oxTrace("ox::fs::Directory::write") << "Attempting to write Directory to FileStore"; - 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"; - return OxError(1); - } - } - return OxError(1); -} - -template -Error Directory::remove(PathIterator path, FileName *nameBuff) noexcept { - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); - } - auto &name = *nameBuff; - oxReturnError(path.get(&name)); - - oxTrace("ox::fs::Directory::remove") << name.c_str(); - auto buff = m_fs->read(m_inodeId).template to(); - if (buff.valid()) { - oxTrace("ox::fs::Directory::remove") << "Found directory buffer."; - for (auto i = buff->iterator(); i.valid(); i.next()) { - auto data = i->data(); - if (data.valid()) { - if (ox_strncmp(data->name, name.c_str(), name.len()) == 0) { - buff->free(i); - } - } else { - oxTrace("ox::fs::Directory::remove") << "INVALID DIRECTORY ENTRY"; - } - } - } else { - oxTrace("ox::fs::Directory::remove::fail") << "Could not find directory buffer"; - return OxError(1); - } - return OxError(0); -} - -template -ValErr Directory::findEntry(const FileName &name) const noexcept { - oxTrace("ox::fs::Directory::findEntry") << name.c_str(); - auto buff = m_fs->read(m_inodeId).template to(); - if (buff.valid()) { - oxTrace("ox::fs::Directory::findEntry") << "Found directory buffer."; - for (auto i = buff->iterator(); i.valid(); i.next()) { - 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) { - return static_cast(data->inode); - } - } else { - oxTrace("ox::fs::Directory::findEntry") << "INVALID DIRECTORY ENTRY"; - } - } - oxTrace("ox::fs::Directory::findEntry::fail"); - return {0, OxError(1)}; - } else { - oxTrace("ox::fs::Directory::findEntry::fail") << "Could not findEntry directory buffer"; - return {0, OxError(2)}; - } -} - -template -ValErr Directory::find(PathIterator path, FileName *nameBuff) const noexcept { - // reuse nameBuff if it has already been allocated, as it is a rather large variable - if (nameBuff == nullptr) { - nameBuff = reinterpret_cast(ox_alloca(sizeof(FileName))); - } - - // determine if already exists - auto name = nameBuff; - if (path.get(name)) { - return {0, OxError(1)}; - } - - auto v = findEntry(name->c_str()); - if (!v.error) { - return v; - } - name = nullptr; - v = find(path + 1, nameBuff); - if (!v.error) { - return v; - } - - return {0, OxError(1)}; -} - - -extern template class Directory; -extern template class Directory; - -extern template struct DirectoryEntry; -extern template struct DirectoryEntry; - -using Directory16 = Directory; -using Directory32 = Directory; - -} diff --git a/deps/ox/src/ox/fs/filesystem2/filesystem.cpp b/deps/ox/src/ox/fs/filesystem2/filesystem.cpp deleted file mode 100644 index a90a6f51..00000000 --- a/deps/ox/src/ox/fs/filesystem2/filesystem.cpp +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include "filesystem.hpp" - -namespace ox::fs { - -template class FileSystemTemplate; -template class FileSystemTemplate; - -} diff --git a/deps/ox/src/ox/fs/filesystem2/filesystem.hpp b/deps/ox/src/ox/fs/filesystem2/filesystem.hpp deleted file mode 100644 index 33331271..00000000 --- a/deps/ox/src/ox/fs/filesystem2/filesystem.hpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include -#include - -#include "directory.hpp" - -namespace ox::fs { - -class FileSystem { - - public: - virtual Error format() = 0; - - virtual Error mkdir(const char *path, bool recursive = false) = 0; - - /** - * Moves an entry from one directory to another. - * @param src the path to the file - * @param dest the path of the destination directory - */ - virtual Error move(const char *src, const char *dest) = 0; - - virtual Error read(const char *path, void *buffer, std::size_t buffSize) = 0; - - virtual Error read(uint64_t inode, void *buffer, std::size_t size) = 0; - - virtual Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) = 0; - - virtual Error remove(const char *path, bool recursive = false) = 0; - - virtual void resize(uint64_t size, void *buffer = nullptr) = 0; - - virtual Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - - virtual Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) = 0; - - virtual ValErr stat(uint64_t inode) = 0; - - virtual ValErr stat(const char *path) = 0; - - virtual uint64_t spaceNeeded(uint64_t size) = 0; - - virtual uint64_t available() = 0; - - virtual uint64_t size() = 0; - - virtual uint8_t *buff() = 0; - - virtual Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) = 0; - - virtual bool valid() const = 0; - -}; - -/** - * FileSystemTemplate used to create file system that wraps around a FileStore, - * taking an inode size and a directory type as parameters. - * - * Note: Directory parameter must have a default constructor. - */ -template -class FileSystemTemplate: public FileSystem { - private: - static constexpr auto InodeFsData = 2; - - struct __attribute__((packed)) FileSystemData { - LittleEndian rootDirInode; - }; - - FileStore *m_fs = nullptr; - - public: - FileSystemTemplate(FileStore *fs); - - ~FileSystemTemplate(); - - Error format() override; - - Error mkdir(const char *path, bool recursive = false) override; - - Error move(const char *src, const char *dest) override; - - Error read(const char *path, void *buffer, std::size_t buffSize) override; - - Error read(uint64_t inode, void *buffer, std::size_t size) override; - - Error read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) override; - - Error remove(const char *path, bool recursive = false) override; - - void resize(uint64_t size, void *buffer = nullptr) override; - - Error write(const char *path, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; - - Error write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = FileType_NormalFile) override; - - ValErr stat(uint64_t inode) override; - - ValErr stat(const char *path) override; - - uint64_t spaceNeeded(uint64_t size) override; - - uint64_t available() override; - - uint64_t size() override; - - uint8_t *buff() override; - - Error walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) override; - - bool valid() const override; - - private: - ValErr fileSystemData() const noexcept; - - /** - * Finds the inode ID at the given path. - */ - ValErr find(const char *path) const noexcept; - - ValErr rootDir() const noexcept; - -}; - -template -FileSystemTemplate::FileSystemTemplate(FileStore *fs) { - m_fs = fs; -} - -template -FileSystemTemplate::~FileSystemTemplate() { -} - -template -Error FileSystemTemplate::format() { - oxReturnError(m_fs->format()); - - constexpr auto rootDirInode = MaxValue / 2; - Directory rootDir(m_fs, rootDirInode); - oxReturnError(rootDir.init()); - - FileSystemData fd; - fd.rootDirInode = rootDirInode; - oxTrace("ox::fs::FileSystemTemplate::format") << "rootDirInode:" << fd.rootDirInode; - oxReturnError(m_fs->write(InodeFsData, &fd, sizeof(fd))); - - if (m_fs->read(fd.rootDirInode).valid()) { - oxTrace("ox::fs::FileSystemTemplate::format::error") << "FileSystemTemplate::format did not correctly create root directory"; - } - - return OxError(0); -} - -template -Error FileSystemTemplate::mkdir(const char *path, bool recursive) { - oxTrace("ox::fs::FileSystemTemplate::mkdir") << "path:" << path << "recursive:" << recursive; - auto rootDir = this->rootDir(); - oxReturnError(rootDir.error); - return rootDir.value.mkdir(path, recursive); -} - -template -Error FileSystemTemplate::move(const char *src, const char *dest) { - auto fd = fileSystemData(); - oxReturnError(fd.error); - Directory rootDir(m_fs, fd.value.rootDirInode); - auto inode = rootDir.find(src); - oxReturnError(inode.error); - oxReturnError(rootDir.write(dest, inode)); - oxReturnError(rootDir.remove(src)); - return OxError(0); -} - -template -Error FileSystemTemplate::read(const char *path, void *buffer, std::size_t buffSize) { - auto fd = fileSystemData(); - oxReturnError(fd.error); - Directory rootDir(m_fs, fd.value.rootDirInode); - auto inode = rootDir.find(path); - oxReturnError(inode.error); - return read(inode, buffer, buffSize); -} - -template -Error FileSystemTemplate::read(uint64_t inode, void *buffer, std::size_t buffSize) { - return m_fs->read(inode, buffer, buffSize); -} - -template -Error FileSystemTemplate::read(uint64_t inode, std::size_t readStart, std::size_t readSize, void *buffer, std::size_t *size) { - return m_fs->read(inode, readStart, readSize, buffer, size); -} - -template -Error FileSystemTemplate::remove(const char *path, bool recursive) { - auto fd = fileSystemData(); - oxReturnError(fd.error); - Directory rootDir(m_fs, fd.value.rootDirInode); - auto inode = rootDir.find(path); - oxReturnError(inode.error); - auto st = stat(inode); - oxReturnError(st.error); - if (st.value.fileType == FileType_NormalFile || recursive) { - if (auto err = rootDir.remove(path)) { - // removal failed, try putting the index back - oxLogError(rootDir.write(path, inode)); - return err; - } - } else { - oxTrace("FileSystemTemplate::remove::fail") << "Tried to remove directory without recursive setting."; - return OxError(1); - } - return OxError(0); -} - -template -void FileSystemTemplate::resize(uint64_t size, void *buffer) { - m_fs->resize(size, buffer); -} - -template -Error FileSystemTemplate::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) { - auto inode = find(path); - if (inode.error) { - inode.value = m_fs->generateInodeId(); - } - auto rootDir = this->rootDir(); - oxReturnError(rootDir.error); - oxReturnError(rootDir.value.write(path, inode)); - oxReturnError(write(inode, buffer, size, fileType)); - return 0; -} - -template -Error FileSystemTemplate::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) { - return m_fs->write(inode, buffer, size, fileType); -} - -template -ValErr FileSystemTemplate::stat(uint64_t inode) { - auto s = m_fs->stat(inode); - FileStat out; - out.inode = s.value.inode; - out.links = s.value.links; - out.size = s.value.size; - out.fileType = s.value.fileType; - return {out, s.error}; -} - -template -ValErr FileSystemTemplate::stat(const char *path) { - auto inode = find(path); - if (inode.error) { - return {{}, inode.error}; - } - return stat(inode.value); -} - -template -uint64_t FileSystemTemplate::spaceNeeded(uint64_t size) { - return m_fs->spaceNeeded(size); -} - -template -uint64_t FileSystemTemplate::available() { - return m_fs->available(); -} - -template -uint64_t FileSystemTemplate::size() { - return m_fs->size(); -} - -template -uint8_t *FileSystemTemplate::buff() { - return m_fs->buff(); -} - -template -Error FileSystemTemplate::walk(Error(*cb)(uint8_t, uint64_t, uint64_t)) { - return m_fs->walk(cb); -} - -template -bool FileSystemTemplate::valid() const { - return m_fs && m_fs->valid(); -} - -template -ValErr::FileSystemData> FileSystemTemplate::fileSystemData() const noexcept { - FileSystemData fd; - auto err = m_fs->read(InodeFsData, &fd, sizeof(fd)); - if (err != 0) { - return {fd, err}; - } - return fd; -} - -template -ValErr FileSystemTemplate::find(const char *path) const noexcept { - auto fd = fileSystemData(); - if (fd.error) { - return {0, fd.error}; - } - Directory rootDir(m_fs, fd.value.rootDirInode); - auto inode = rootDir.find(path); - if (inode.error) { - return {0, inode.error}; - } - return inode.value; -} - -template -ValErr FileSystemTemplate::rootDir() const noexcept { - auto fd = fileSystemData(); - if (fd.error) { - return {{}, fd.error}; - } - return Directory(m_fs, fd.value.rootDirInode); -} - -extern template class FileSystemTemplate; -extern template class FileSystemTemplate; - -using FileSystem16 = FileSystemTemplate; -using FileSystem32 = FileSystemTemplate; - -} diff --git a/deps/ox/src/ox/fs/fs.hpp b/deps/ox/src/ox/fs/fs.hpp index 6e4dd813..a8ddabcb 100644 --- a/deps/ox/src/ox/fs/fs.hpp +++ b/deps/ox/src/ox/fs/fs.hpp @@ -8,5 +8,5 @@ #pragma once -#include "filesystem/filesystemtemplate.hpp" -#include "filesystem2/directory.hpp" +//#include "filesystem/filesystemtemplate.hpp" +#include "filesystem/directory.hpp" diff --git a/deps/ox/src/ox/fs/test/CMakeLists.txt b/deps/ox/src/ox/fs/test/CMakeLists.txt index d4d9a6bc..de654453 100644 --- a/deps/ox/src/ox/fs/test/CMakeLists.txt +++ b/deps/ox/src/ox/fs/test/CMakeLists.txt @@ -1,49 +1,10 @@ cmake_minimum_required(VERSION 2.8) -add_executable( - FileStoreFormat - filestore_format.cpp -) - -add_executable( - FileSystemFormat - filesystem_format.cpp -) - -add_executable( - FileStoreIO - filestoreio.cpp -) - add_executable( FSTests tests.cpp ) -target_link_libraries( - FileStoreFormat - OxFS - OxStd - OxTrace - OxMetalClaw -) - -target_link_libraries( - FileSystemFormat - OxFS - OxStd - OxTrace - OxMetalClaw -) - -target_link_libraries( - FileStoreIO - OxFS - OxStd - OxTrace - OxMetalClaw -) - target_link_libraries( FSTests OxFS @@ -52,9 +13,6 @@ target_link_libraries( OxMetalClaw ) -add_test("FileStoreFormat" FileStoreFormat) -add_test("FileSystemFormat" FileSystemFormat) -add_test("FileStoreIO" FileStoreIO) add_test("Test\\ PathIterator::next1" FSTests PathIterator::next1) add_test("Test\\ PathIterator::next2" FSTests PathIterator::next2) add_test("Test\\ PathIterator::next3" FSTests PathIterator::next3) @@ -65,14 +23,6 @@ add_test("Test\\ PathIterator::hasNext" FSTests PathIterator::hasNext) add_test("Test\\ PathIterator::dirPath" FSTests PathIterator::dirPath) add_test("Test\\ PathIterator::fileName" FSTests PathIterator::fileName) -add_test("Test\\ FileSystem32::findInodeOf\\ /" FSTests "FileSystem32::findInodeOf /") -add_test("Test\\ FileSystem32::write\\(string\\)" FSTests "FileSystem32::write(string)") -add_test("Test\\ FileSystem32::rmDirectoryEntry\\(string\\)" FSTests "FileSystem32::rmDirectoryEntry(string)") -add_test("Test\\ FileSystem32::remove\\(string,\\ true\\)" FSTests "FileSystem32::remove(string, true)") -add_test("Test\\ FileSystem32::move" FSTests "FileSystem32::move") -add_test("Test\\ FileSystem32::stripDirectories" FSTests "FileSystem32::stripDirectories") -#add_test("Test\\ FileSystem32::ls" FSTests "FileSystem32::ls") - add_test("Test\\ NodeBuffer::insert" FSTests "NodeBuffer::insert") add_test("Test\\ FileStore::readWrite" FSTests "FileStore::readWrite") diff --git a/deps/ox/src/ox/fs/test/tests.cpp b/deps/ox/src/ox/fs/test/tests.cpp index 247488cc..ddd58f3d 100644 --- a/deps/ox/src/ox/fs/test/tests.cpp +++ b/deps/ox/src/ox/fs/test/tests.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include using namespace std; @@ -120,216 +120,6 @@ map tests = { return retval; } }, - { - "FileSystem32::findInodeOf /", - [](string) { - int retval = 0; - const auto size = 1024; - uint8_t buff[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - retval |= !(fs->findInodeOf("/") == FileSystem32::INODE_ROOT_DIR); - delete fs; - return retval; - } - }, - { - "FileSystem32::write(string)", - [](string) { - int retval = 0; - auto path = "/usr/share/test.txt"; - auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; - auto dataOut = new char[dataOutLen]; - - const auto size = 1024 * 1024; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - retval |= fs->mkdir("/usr/lib"); - - retval |= fs->write(path, (void*) dataIn, ox_strlen(dataIn) + 1); - retval |= fs->read(path, dataOut, dataOutLen); - retval |= ox_strcmp(dataIn, dataOut) != 0; - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, - { - "FileSystem32::rmDirectoryEntry(string)", - [](string) { - int retval = 0; - auto path = "/usr/share/test.txt"; - auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; - auto dataOut = new char[dataOutLen]; - - const auto size = 1024 * 1024 * 10; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - - retval |= fs->write(path, (void*) dataIn, ox_strlen(dataIn) + 1); - retval |= fs->read(path, dataOut, dataOutLen); - retval |= ox_strcmp(dataIn, dataOut) != 0; - - retval |= fs->rmDirectoryEntry(path); - // the lookup should fail - retval |= fs->read(path, dataOut, dataOutLen) == 0; - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, - { - "FileSystem32::remove(string, true)", - [](string) { - int retval = 0; - auto dataIn = "test string"; - auto dataOutLen = 1024 * 64; - auto dataOut = new char[dataOutLen]; - std::vector inodes; - - const auto size = 1024 * 1024; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - - inodes.push_back(fs->stat("/usr").inode); - inodes.push_back(fs->stat("/usr/share").inode); - inodes.push_back(fs->stat("/usr/share/test.txt").inode); - - retval |= fs->remove("/usr", true); - - // the lookup should fail - for (auto inode : inodes) { - retval |= fs->read(inode, dataOut, dataOutLen) == 0; - } - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, - { - "FileSystem32::move", - [](string) { - int retval = 0; - auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; - auto dataOut = new char[dataOutLen]; - std::vector inodes; - - const auto size = 1024 * 1024; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - - retval |= fs->move("/usr/share", "/share"); - retval |= fs->read("/share/test.txt", dataOut, dataOutLen); - retval |= !(ox_strcmp(dataIn, dataOut) == 0); - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, - { - "FileSystem32::stripDirectories", - [](string) { - int retval = 0; - auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; - auto dataOut = new char[dataOutLen]; - std::vector inodes; - - const auto size = 1024 * 1024; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - retval |= fs->write("/usr/share/test.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - - auto inode = fs->stat("/usr/share/test.txt").inode; - - retval |= fs->stripDirectories(); - - // make sure normal file is still there and the directories are gone - retval |= fs->read(inode, dataOut, dataOutLen); - retval |= !(ox_strcmp(dataIn, dataOut) == 0); - retval |= !(fs->stat("/usr").inode == 0); - retval |= !(fs->stat("/usr/share").inode == 0); - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, - { - "FileSystem32::ls", - [](string) { - int retval = 0; - auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; - auto dataOut = new char[dataOutLen]; - std::vector inodes; - std::vector> files; - - const auto size = 1024 * 1024; - auto buff = new uint8_t[size]; - FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); - auto fs = (FileSystem32*) createFileSystem(buff, size); - - retval |= fs->mkdir("/usr"); - retval |= fs->mkdir("/usr/share"); - retval |= fs->write("/usr/share/a.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - retval |= fs->write("/usr/share/b.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - retval |= fs->write("/usr/share/c.txt", (void*) dataIn, ox_strlen(dataIn) + 1); - - fs->ls("/usr/share/", &files); - - retval |= !(files[0].name == "."); - retval |= !(files[1].name == ".."); - retval |= !(files[2].name == "a.txt"); - retval |= !(files[3].name == "b.txt"); - retval |= !(files[4].name == "c.txt"); - - delete fs; - delete []buff; - delete []dataOut; - - return retval; - } - }, { "Ptr::subPtr", [](string) {