diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index eee1175c8..bbfb76ab2 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -46,7 +46,6 @@ class FileStore { ox::std::uint32_t m_fsType; FsSize_t m_size; - FsSize_t m_firstInode; FsSize_t m_rootInode; public: @@ -104,6 +103,15 @@ class FileStore { */ Inode *getInode(Inode *root, InodeId_t id); + /** + * 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 *getInodeParent(Inode *root, InodeId_t id); + /** * Removes the inode of the given ID. * @param id the id of the file @@ -116,6 +124,12 @@ class FileStore { */ void unlink(Inode *node); + /** + * Gets the address of the next available inode, assuming there is a next + * available inode. + */ + FsSize_t nextInodeAddr(); + /** * Gets an address for a new Inode. * @param size the size of the Inode @@ -123,9 +137,9 @@ class FileStore { void *alloc(FsSize_t size); /** - * Compresses all of the inode into a contiguous space, starting at m_firstInode. + * Compresses all of the inode into a contiguous space, starting at the first inode. */ - void compress(); + void compress(FsSize_t firstInode); /** * Inserts the given insertValue into the tree of the given root. @@ -140,10 +154,15 @@ class FileStore { */ FsSize_t iterator(); - Inode *firstInode(); + FsSize_t firstInode(); Inode *lastInode(); + /** + * Updates the address of the inode in the tree. + */ + void updateInodeAddress(InodeId_t id, FsSize_t addr); + ox::std::uint8_t *begin() { return (ox::std::uint8_t*) this; } @@ -203,9 +222,10 @@ int FileStore::write(InodeId_t id, void *data, FsSize_t dataLen) { const FsSize_t size = sizeof(Inode) + dataLen; auto inode = (Inode*) alloc(size); if (inode) { - auto root = ptr(m_rootInode); + remove(id); inode->m_id = id; inode->setData(data, dataLen); + auto root = ptr(m_rootInode); if (insert(root, inode) || root == inode) { retval = 0; } @@ -228,7 +248,7 @@ int FileStore::remove(Inode *root, InodeId_t id) { if (node->m_id != id) { err = remove(node, id); } else { - root->left = node->left; + root->left = 0; if (node->right) { insert(root, ptr(node->right)); } @@ -236,6 +256,9 @@ int FileStore::remove(Inode *root, InodeId_t id) { insert(root, ptr(node->left)); } unlink(node); + node->m_id = 0; + node->left = 0; + node->right = 0; err = 0; } } @@ -245,7 +268,7 @@ int FileStore::remove(Inode *root, InodeId_t id) { if (node->m_id != id) { err = remove(node, id); } else { - root->right = node->right; + root->right = 0; if (node->right) { insert(root, ptr(node->right)); } @@ -253,15 +276,21 @@ int FileStore::remove(Inode *root, InodeId_t id) { insert(root, ptr(node->left)); } unlink(node); + node->m_id = 0; + node->left = 0; + node->right = 0; err = 0; } } - } else { + } else if (ptr(m_rootInode)->m_id == id) { m_rootInode = root->right; if (root->left) { insert(ptr(m_rootInode), ptr(root->left)); } unlink(root); + root->m_id = 0; + root->left = 0; + root->right = 0; err = 0; } @@ -269,11 +298,27 @@ int FileStore::remove(Inode *root, InodeId_t id) { } template -void FileStore::unlink(Inode *node) { - auto next = ptr(node->next); - auto prev = ptr(node->prev); +void FileStore::unlink(Inode *inode) { + auto next = ptr(inode->next); + auto prev = ptr(inode->prev); prev->next = ptr(next); next->prev = ptr(prev); + + ox::std::memset(inode, 0, inode->size()); + inode->prev = firstInode(); + inode->next = firstInode(); +} + +template +void FileStore::updateInodeAddress(InodeId_t id, FsSize_t addr) { + auto parent = getInodeParent(ptr(m_rootInode), id); + if (parent) { + if (parent->left && ptr(parent->left)->m_id == id) { + parent->left = addr; + } else if (parent->right && ptr(parent->right)->m_id == id) { + parent->right = addr; + } + } } template @@ -322,36 +367,79 @@ typename FileStore::Inode *FileStore::getInode(Inode *root, return retval; } +template +typename FileStore::Inode *FileStore::getInodeParent(Inode *root, InodeId_t id) { + Inode *retval = nullptr; + + if (root->m_id > id) { + if (root->left) { + if (ptr(root->left)->m_id == id) { + retval = root; + } else { + retval = getInode(ptr(root->left), id); + } + } + } else if (root->m_id < id) { + if (root->right) { + if (ptr(root->right)->m_id == id) { + retval = root; + } else { + retval = getInode(ptr(root->right), id); + } + } + } + + return retval; +} + +template +FsSize_t FileStore::nextInodeAddr() { + FsSize_t next = ptr(lastInode()) + lastInode()->size(); + return next; +} + template void *FileStore::alloc(FsSize_t size) { - if ((lastInode()->next + size) > (ox::std::uint64_t) end()) { - compress(); - if ((lastInode()->next + size) > (ox::std::uint64_t) end()) { + FsSize_t next = nextInodeAddr(); + if ((next + size) > (ox::std::uint64_t) end()) { + compress(firstInode()); + next = nextInodeAddr(); + if ((next + size) > (ox::std::uint64_t) end()) { return nullptr; } } - const auto retval = lastInode()->next; + const auto retval = next; const auto inode = ptr(retval); ox::std::memset(inode, 0, size); + inode->prev = ptr(firstInode())->prev; inode->next = retval + size; - ptr(m_firstInode)->prev = retval; + ptr(firstInode())->prev = retval; return inode; } template -void FileStore::compress() { - auto current = ptr(m_firstInode); - while (current->next) { - auto prevEnd = current + current->size(); - auto prev = ptr(current); - current->next = ptr(current) + current->size(); - current = ptr(current->next); - current->prev = prev; - if (prevEnd != current) { - ox::std::memcpy(prevEnd, current, current->size()); - current = prevEnd; +void FileStore::compress(FsSize_t start) { + auto dest = ptr(firstInode()); + auto current = ptr(start); + while (current->next > ptr(begin()) && current->next < ptr(end())) { + ox::std::memcpy(dest, current, current->size()); + if (dest->next != firstInode()) { + dest->next = ptr(dest) + dest->size(); } + ptr(dest->next)->prev = ptr(dest); + current = ptr(dest->next); + dest = ptr(ptr(dest) + dest->size()); + updateInodeAddress(dest->m_id, ptr(dest)); + //auto prevEnd = current + current->size(); + //auto prev = ptr(current); + //current->next = ptr(current) + current->size(); + //current = ptr(current->next); + //current->prev = prev; + //if (prevEnd != current) { + // ox::std::memcpy(prevEnd, current, current->size()); + // current = prevEnd; + //} } } @@ -373,6 +461,9 @@ bool FileStore::insert(Inode *root, Inode *insertValue) { root->right = ptr(insertValue); retval = true; } + } else if (m_rootInode == 0) { + m_rootInode = ptr(insertValue); + retval = true; } return retval; @@ -389,13 +480,13 @@ FsSize_t FileStore::ptr(void *ptr) { } template -typename FileStore::Inode *FileStore::firstInode() { - return ptr(sizeof(FileStore)); +FsSize_t FileStore::firstInode() { + return sizeof(FileStore); } template typename FileStore::Inode *FileStore::lastInode() { - return ptr(ptr(m_firstInode)->prev); + return ptr(ptr(firstInode())->prev); } template @@ -411,8 +502,7 @@ ox::std::uint8_t *FileStore::format(ox::std::uint8_t *buffer, FsSize_t fs->m_fsType = fsType; fs->m_size = size; fs->m_rootInode = sizeof(FileStore); - fs->m_firstInode = sizeof(FileStore); - fs->firstInode()->prev = fs->m_firstInode; + ((Inode*) (fs + 1))->prev = fs->firstInode(); fs->lastInode()->next = sizeof(FileStore); return (ox::std::uint8_t*) buffer; diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 858a46df3..d502fa37f 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -34,6 +34,8 @@ class FileSystem { virtual ox::std::uint8_t *read(ox::std::uint64_t inode, ox::std::uint64_t *size) = 0; + virtual int remove(ox::std::uint64_t inode) = 0; + virtual int write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) = 0; virtual FileStat stat(ox::std::uint64_t inode) = 0; @@ -85,6 +87,8 @@ class FileSystemTemplate: public FileSystem { int read(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override; + int remove(ox::std::uint64_t inode); + int write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override; FileStat stat(const char *path); @@ -146,6 +150,11 @@ ox::std::uint8_t *FileSystemTemplate::read(ox::std::uint64_t inode, o return buff; } +template +int FileSystemTemplate::remove(ox::std::uint64_t inode) { + return store->remove(inode); +} + template int FileSystemTemplate::write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) { return store->write(inode, buffer, size); diff --git a/src/ox/fs/oxfstool.cpp b/src/ox/fs/oxfstool.cpp index b3c7afc95..c7cfc849b 100644 --- a/src/ox/fs/oxfstool.cpp +++ b/src/ox/fs/oxfstool.cpp @@ -94,15 +94,19 @@ int read(int argc, char **args) { if (fsBuff) { auto fs = createFileSystem(fsBuff); - auto output = fs->read(inode, &fileSize); + if (fs) { + auto output = fs->read(inode, &fileSize); - if (output) { - fwrite(output, fileSize, 1, stdout); - err = 0; + if (output) { + fwrite(output, fileSize, 1, stdout); + err = 0; + } + + delete fs; + free(fsBuff); + } else { + fprintf(stderr, "Invalid file system type: %d.\n", *(ox::std::uint32_t*) fsBuff); } - - delete fs; - delete fsBuff; } else { fprintf(stderr, "Could not open file: %s\n", fsPath); } @@ -133,13 +137,15 @@ int write(int argc, char **args) { auto fs = createFileSystem(fsBuff); if (fs) { err |= fs->write(inode, srcBuff, srcSize); + if (err) { + fprintf(stderr, "Could not write to file system.\n"); + } } else { - fprintf(stderr, "Invalid file system.\n"); + fprintf(stderr, "Invalid file system type: %d.\n", *(ox::std::uint32_t*) fsBuff); + err = 1; } - if (err) { - fprintf(stderr, "Could not write to file system.\n"); - } else { + if (!err) { fsFile = fopen(fsPath, "wb"); if (fsFile) { @@ -166,6 +172,49 @@ int write(int argc, char **args) { return err; } +int remove(int argc, char **args) { + auto err = 1; + if (argc >= 4) { + auto fsPath = args[2]; + auto inode = ox::std::atoi(args[3]); + ::size_t fsSize; + + auto fsBuff = loadFileBuff(fsPath, &fsSize); + if (fsBuff) { + auto fs = createFileSystem(fsBuff); + + if (fs) { + err = fs->remove(inode); + } else { + fprintf(stderr, "Invalid file system.\n"); + } + + if (err) { + fprintf(stderr, "Could not write to file system.\n"); + } else { + auto fsFile = fopen(fsPath, "wb"); + if (fsFile) { + err = fwrite(fsBuff, fsSize, 1, fsFile) != 1; + err |= fclose(fsFile); + if (err) { + fprintf(stderr, "Could not write to file system file.\n"); + } + } else { + err = 1; + } + } + + delete fs; + free(fsBuff); + } else { + fprintf(stderr, "Could not open file: %s\n", fsPath); + } + } else { + fprintf(stderr, "Insufficient arguments\n"); + } + return err; +} + int main(int argc, char **args) { auto err = 0; if (argc > 1) { @@ -176,6 +225,8 @@ int main(int argc, char **args) { err = read(argc, args); } else if (::strcmp(cmd, "write") == 0) { err = write(argc, args); + } else if (::strcmp(cmd, "rm") == 0) { + err = remove(argc, args); } else if (::strcmp(cmd, "help") == 0) { printf("%s\n", usage); } else { diff --git a/src/ox/fs/test/filestoreio.cpp b/src/ox/fs/test/filestoreio.cpp index 80eb114b3..5e7dfa537 100644 --- a/src/ox/fs/test/filestoreio.cpp +++ b/src/ox/fs/test/filestoreio.cpp @@ -5,6 +5,7 @@ * 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 #include #include @@ -23,27 +24,32 @@ int test() { if (fs->write(1, (void*) "Hello", 6) || fs->read(1, (char*) out, &outSize) || strcmp("Hello", out)) { + printf("Failure 1\n"); return 1; } if (fs->write(2, (void*) "World", 6) || fs->read(2, (char*) out, &outSize) || strcmp("World", out)) { + printf("Failure 2\n"); return 2; } // make sure first value was not overwritten if (fs->read(1, (char*) out, &outSize) || strcmp("Hello", out)) { + printf("Failure 3\n"); return 3; } if (fs->remove(1)) { + printf("Failure 4\n"); return 4; } // make sure inode is not found if (fs->read(1, (char*) out, &outSize) == 0) { + printf("Failure 5\n"); return 5; } @@ -51,6 +57,7 @@ int test() { if (fs->write(2, (void*) "World", 6) || fs->read(2, (char*) out, &outSize) || strcmp("World", out)) { + printf("Failure 6\n"); return 6; }