diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index b21d0bb03..acf28cafe 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -41,11 +41,17 @@ class FileStore { void *data(); }; - uint32_t m_fsType; + uint32_t m_fsType; FsSize_t m_size; FsSize_t m_rootInode; public: + /** + * Compacts and resizes the file store to the minimum possible size for + * the contents. + */ + void resize(); + /** * Writes the given data to a "file" with the given id. * @param id the id of the file @@ -111,9 +117,10 @@ class FileStore { * @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); + Inode *getInodeParent(Inode *root, InodeId_t id, FsSize_t targetAddr); /** * Removes the inode of the given ID. @@ -140,9 +147,9 @@ class FileStore { void *alloc(FsSize_t size); /** - * Compresses all of the inode into a contiguous space, starting at the first inode. + * Compacts all of the inodes into a contiguous space, starting at the first inode. */ - void compress(FsSize_t firstInode); + void compact(); /** * Inserts the given insertValue into the tree of the given root. @@ -164,7 +171,7 @@ class FileStore { /** * Updates the address of the inode in the tree. */ - void updateInodeAddress(InodeId_t id, FsSize_t addr); + void updateInodeAddress(InodeId_t id, FsSize_t oldAddr, FsSize_t newAddr); uint8_t *begin() { return (uint8_t*) this; @@ -214,6 +221,13 @@ void *FileStore::Inode::data() { // FileStore +template +void FileStore::resize() { + compact(); + auto last = lastInode(); + m_size = ptr(last) + last->size(); +} + template int FileStore::write(void *data, FsSize_t dataLen, uint8_t fileType) { return 1; @@ -314,13 +328,13 @@ void FileStore::unlink(Inode *inode) { } template -void FileStore::updateInodeAddress(InodeId_t id, FsSize_t addr) { - auto parent = getInodeParent(ptr(m_rootInode), id); +void FileStore::updateInodeAddress(InodeId_t id, FsSize_t oldAddr, FsSize_t newAddr) { + auto parent = getInodeParent(ptr(m_rootInode), id, oldAddr); if (parent) { - if (parent->left && ptr(parent->left)->id == id) { - parent->left = addr; - } else if (parent->right && ptr(parent->right)->id == id) { - parent->right = addr; + if (parent->left == oldAddr) { + parent->left = newAddr; + } else if (parent->right == oldAddr) { + parent->right = newAddr; } } } @@ -378,23 +392,23 @@ typename FileStore::Inode *FileStore::getInode(Inode *root, } template -typename FileStore::Inode *FileStore::getInodeParent(Inode *root, InodeId_t id) { +typename FileStore::Inode *FileStore::getInodeParent(Inode *root, InodeId_t id, FsSize_t targetAddr) { Inode *retval = nullptr; if (root->id > id) { if (root->left) { - if (ptr(root->left)->id == id) { + if (root->left == targetAddr) { retval = root; } else { - retval = getInode(ptr(root->left), id); + retval = getInodeParent(ptr(root->left), id, targetAddr); } } } else if (root->id < id) { if (root->right) { - if (ptr(root->right)->id == id) { + if (root->right == targetAddr) { retval = root; } else { - retval = getInode(ptr(root->right), id); + retval = getInodeParent(ptr(root->right), id, targetAddr); } } } @@ -412,7 +426,7 @@ template void *FileStore::alloc(FsSize_t size) { FsSize_t next = nextInodeAddr(); if ((next + size) > (uint64_t) end()) { - compress(firstInode()); + compact(); next = nextInodeAddr(); if ((next + size) > (uint64_t) end()) { return nullptr; @@ -429,18 +443,18 @@ void *FileStore::alloc(FsSize_t size) { } template -void FileStore::compress(FsSize_t start) { +void FileStore::compact() { auto dest = ptr(firstInode()); - auto current = ptr(start); - while (current->next > ptr(begin()) && current->next < ptr(end())) { + auto current = ptr(firstInode()); + while (current->next > firstInode() && current->next < ptr(end())) { ox_memcpy(dest, current, current->size()); if (dest->next != firstInode()) { dest->next = ptr(dest) + dest->size(); } ptr(dest->next)->prev = ptr(dest); + updateInodeAddress(dest->id, ptr(current), ptr(dest)); current = ptr(dest->next); dest = ptr(ptr(dest) + dest->size()); - updateInodeAddress(dest->id, ptr(dest)); } } diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 1579022a4..eb3511b7a 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -42,9 +42,13 @@ class FileSystem { virtual int remove(uint64_t inode) = 0; + virtual void resize() = 0; + virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0; virtual FileStat stat(uint64_t inode) = 0; + + virtual uint64_t size() = 0; }; FileSystem *createFileSystem(void *buff); @@ -95,6 +99,8 @@ class FileSystemTemplate: public FileSystem { int read(uint64_t inode, void *buffer, size_t size) override; + void resize() override; + int remove(uint64_t inode) override; int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override; @@ -103,6 +109,8 @@ class FileSystemTemplate: public FileSystem { FileStat stat(uint64_t inode) override; + uint64_t size() override; + static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories); }; @@ -199,6 +207,16 @@ int FileSystemTemplate::write(uint64_t inode, void *buffer, #pragma warning(default:4244) #endif +template +void FileSystemTemplate::resize() { + return store->resize(); +} + +template +uint64_t FileSystemTemplate::size() { + return store->size(); +} + #ifdef _MSC_VER #pragma warning(disable:4244) #endif diff --git a/src/ox/fs/oxfstool.cpp b/src/ox/fs/oxfstool.cpp index ab6f7ba3a..3b08c728f 100644 --- a/src/ox/fs/oxfstool.cpp +++ b/src/ox/fs/oxfstool.cpp @@ -20,13 +20,14 @@ using namespace ox::fs; using namespace std; -const static auto oxfstoolVersion = "1.0.0"; +const static auto oxfstoolVersion = "1.1.0"; const static auto usage = "usage:\n" "\toxfs format [16,32,64] \n" "\toxfs read \n" +"\toxfs write " +"\toxfs compact " "\toxfs rm \n" -"\toxfs version\n" -"\toxfs write "; +"\toxfs version\n"; char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) { auto file = fopen(path, "rb"); @@ -129,6 +130,8 @@ int format(int argc, char **args) { if (err == 0) { fprintf(stderr, "Created file system %s\n", path); } + } else { + fprintf(stderr, "Insufficient arguments\n"); } return err; @@ -163,6 +166,8 @@ int read(int argc, char **args) { } else { fprintf(stderr, "Could not open file: %s\n", fsPath); } + } else { + fprintf(stderr, "Insufficient arguments\n"); } return err; } @@ -223,6 +228,47 @@ int write(int argc, char **args) { } else { fprintf(stderr, "Could not open file system\n"); } + } else { + fprintf(stderr, "Insufficient arguments\n"); + } + return err; +} + +int resize(int argc, char **args) { + auto err = 1; + if (argc >= 2) { + auto fsPath = args[2]; + size_t fsSize; + + auto fsBuff = loadFileBuff(fsPath, &fsSize); + if (fsBuff) { + auto fs = createFileSystem(fsBuff); + + if (fs) { + fs->resize(); + } else { + fprintf(stderr, "Invalid file system.\n"); + } + + // write back to file + auto fsFile = fopen(fsPath, "wb"); + if (fsFile) { + err = fwrite(fsBuff, fs->size(), 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; } @@ -280,6 +326,8 @@ int main(int argc, char **args) { err = read(argc, args); } else if (ox_strcmp(cmd, "write") == 0) { err = write(argc, args); + } else if (ox_strcmp(cmd, "resize") == 0) { + err = resize(argc, args); } else if (ox_strcmp(cmd, "rm") == 0) { err = remove(argc, args); } else if (ox_strcmp(cmd, "help") == 0) {