From 89ff3844fd3c5383982125d6e473302e5f29c0e8 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 26 Apr 2017 19:43:24 -0500 Subject: [PATCH] Add move and strip directories functionality to FileSystem --- src/ox/fs/filestore.hpp | 31 +++++++++++++++++ src/ox/fs/filesystem.hpp | 60 +++++++++++++++++++++++++++++++- src/ox/fs/test/CMakeLists.txt | 2 ++ src/ox/fs/test/tests.cpp | 64 +++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 1 deletion(-) diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index 847bb2ee2..f7193609e 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -179,6 +179,12 @@ class FileStore { */ int remove(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. @@ -558,6 +564,31 @@ int FileStore
::remove(Inode *root, InodeId_t id) { 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()); diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 78bc314a5..fd3e4619a 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -35,6 +35,8 @@ class FileSystem { public: virtual ~FileSystem() {}; + virtual int stripDirectories() = 0; + virtual int mkdir(const char *path) = 0; virtual int read(const char *path, void *buffer, size_t buffSize) = 0; @@ -137,6 +139,8 @@ class FileSystemTemplate: public FileSystem { explicit FileSystemTemplate(void *buff); + int stripDirectories() override; + int mkdir(const char *path) override; int read(const char *path, void *buffer, size_t buffSize) override; @@ -171,10 +175,17 @@ class FileSystemTemplate: public FileSystem { uint8_t *buff() override; + /** + * Moves an entry from one directory to another. + * @param src the path to the file + * @param dest the path of the destination directory + */ + int move(const char *src, const char *dest); + /** * Removes an entry from a directory. This does not delete the referred to file. */ - int rmDirectoryEntry(const char *dirPath); + int rmDirectoryEntry(const char *path); static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories); @@ -198,6 +209,11 @@ typename FileStore::InodeId_t FileSystemTemplate::INODE_ROOT template typename FileStore::InodeId_t FileSystemTemplate::INODE_RESERVED_END = 100; +template +int FileSystemTemplate::stripDirectories() { + return m_store->removeAllType(FileType::Directory); +} + template int FileSystemTemplate::mkdir(const char *path) { Directory dir; @@ -532,6 +548,48 @@ int FileSystemTemplate::insertDirectoryEntry(const char *dir #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; + + 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; + } + + 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; diff --git a/src/ox/fs/test/CMakeLists.txt b/src/ox/fs/test/CMakeLists.txt index 82ba376bd..8ca81bcf6 100644 --- a/src/ox/fs/test/CMakeLists.txt +++ b/src/ox/fs/test/CMakeLists.txt @@ -41,3 +41,5 @@ add_test("Test\\ FileSystem32::findInodeOf\\ /" FSTests "FileSystem32::findInode 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") diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp index 3f52d3866..45810d2c2 100644 --- a/src/ox/fs/test/tests.cpp +++ b/src/ox/fs/test/tests.cpp @@ -224,6 +224,70 @@ map tests = { 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]; + 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]; + 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; } },