From fdd9dead43359032753fe78e787ceaa716ee4671 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 26 Apr 2017 06:43:30 -0500 Subject: [PATCH] Add recursive remove option to FileSystem --- src/ox/fs/filesystem.hpp | 76 ++++++++++++++++++++++++++++------- src/ox/fs/test/CMakeLists.txt | 2 +- src/ox/fs/test/tests.cpp | 25 +++++++----- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 1fffc6187..78bc314a5 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -45,9 +45,9 @@ class FileSystem { virtual uint8_t *read(uint64_t inode, size_t *size) = 0; - virtual int remove(uint64_t inode) = 0; + virtual int remove(uint64_t inode, bool recursive = false) = 0; - virtual int remove(const char *path) = 0; + virtual int remove(const char *path, bool recursive = false) = 0; virtual void resize(uint64_t size = 0) = 0; @@ -114,6 +114,7 @@ class FileSystemTemplate: public FileSystem { * Number of bytes after this Directory struct. */ typename FileStore::FsSize_t size = 0; + typename FileStore::FsSize_t children = 0; DirectoryEntry *files() { return size ? (DirectoryEntry*) (this + 1) : nullptr; @@ -121,6 +122,8 @@ class FileSystemTemplate: public FileSystem { uint64_t getFileInode(const char *name, uint64_t buffSize); + int getChildrenInodes(typename FileStore::InodeId_t *inodes, size_t inodesLen); + int rmFile(const char *name); }; @@ -146,9 +149,9 @@ class FileSystemTemplate: public FileSystem { void resize(uint64_t size = 0) override; - int remove(uint64_t inode) override; + int remove(uint64_t inode, bool recursive = false) override; - int remove(const char *path) override; + int remove(const char *path, bool recursive = false) override; int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = NormalFile) override; @@ -301,28 +304,51 @@ uint8_t *FileSystemTemplate::read(uint64_t inode, size_t *si #pragma warning(default:4244) #endif -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif template -int FileSystemTemplate::remove(const char *path) { +int FileSystemTemplate::remove(const char *path, bool recursive) { auto inode = findInodeOf(path); if (inode) { - return remove(inode) | rmDirectoryEntry(path); + return remove(inode, recursive) | rmDirectoryEntry(path); } else { return 1; } } -#ifdef _MSC_VER -#pragma warning(default:4244) -#endif #ifdef _MSC_VER #pragma warning(disable:4244) #endif template -int FileSystemTemplate::remove(uint64_t inode) { - return m_store->remove(inode); +int FileSystemTemplate::remove(uint64_t inode, bool recursive) { + auto fileType = stat(inode).fileType; + if (fileType != FileType::Directory) { + return m_store->remove(inode); + } else if (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]; + dir->getChildrenInodes(inodes, dir->children); + + for (auto i : inodes) { + err |= remove(i, true); + } + + if (!err) { + err |= m_store->remove(inode); + } + + return err; + } else { + return 1; + } } #ifdef _MSC_VER #pragma warning(default:4244) @@ -490,6 +516,7 @@ int FileSystemTemplate::insertDirectoryEntry(const char *dir if (!err) { auto dir = (Directory*) dirBuff; dir->size += spaceNeeded; + dir->children++; auto entry = (DirectoryEntry*) &dirBuff[s.size]; entry->inode = inode; entry->setName(fileName); @@ -563,6 +590,24 @@ uint64_t FileSystemTemplate::Directory::getFileInode(const c return inode; } +template +int FileSystemTemplate::Directory::getChildrenInodes(typename FileStore::InodeId_t *inodes, size_t inodesLen) { + if (inodesLen >= this->children) { + auto current = files(); + if (current) { + for (uint64_t i = 0; i < this->children; i++) { + inodes[i] = current->inode; + current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); + } + return 0; + } else { + return 1; + } + } else { + return 2; + } +} + template int FileSystemTemplate::Directory::rmFile(const char *name) { int err = 1; @@ -574,7 +619,8 @@ int FileSystemTemplate::Directory::rmFile(const char *name) auto dest = (uint8_t*) current; auto src = dest + current->size(); ox_memcpy(dest, src, this->size - i); - this->size -= i; + this->size -= current->size(); + this->children--; err = 0; break; } diff --git a/src/ox/fs/test/CMakeLists.txt b/src/ox/fs/test/CMakeLists.txt index 91084b46a..82ba376bd 100644 --- a/src/ox/fs/test/CMakeLists.txt +++ b/src/ox/fs/test/CMakeLists.txt @@ -40,4 +40,4 @@ 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\\)" FSTests "FileSystem32::remove(string)") +add_test("Test\\ FileSystem32::remove\\(string,\\ true\\)" FSTests "FileSystem32::remove(string, true)") diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp index e26fa0776..3f52d3866 100644 --- a/src/ox/fs/test/tests.cpp +++ b/src/ox/fs/test/tests.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -138,7 +139,7 @@ map tests = { auto dataOutLen = ox_strlen(dataIn) + 1; auto dataOut = new char[dataOutLen]; - const auto size = 1024 * 1024 * 10; + 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); @@ -191,29 +192,33 @@ map tests = { } }, { - "FileSystem32::remove(string)", + "FileSystem32::remove(string, true)", [](string) { int retval = 0; - auto path = "/usr/share/test.txt"; auto dataIn = "test string"; - auto dataOutLen = ox_strlen(dataIn) + 1; + auto dataOutLen = 1024 * 64; auto dataOut = new char[dataOutLen]; + vector inodes; - const auto size = 1024 * 1024 * 10; + 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->write(path, (void*) dataIn, ox_strlen(dataIn) + 1); - retval |= fs->read(path, dataOut, dataOutLen); - retval |= ox_strcmp(dataIn, dataOut) != 0; + 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); - retval |= fs->rmDirectoryEntry(path); // the lookup should fail - retval |= fs->read(path, dataOut, dataOutLen) == 0; + for (auto inode : inodes) { + retval |= fs->read(inode, dataOut, dataOutLen) == 0; + } delete fs; delete []buff;