Add recursive remove option to FileSystem
This commit is contained in:
+61
-15
@@ -45,9 +45,9 @@ class FileSystem {
|
|||||||
|
|
||||||
virtual uint8_t *read(uint64_t inode, size_t *size) = 0;
|
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;
|
virtual void resize(uint64_t size = 0) = 0;
|
||||||
|
|
||||||
@@ -114,6 +114,7 @@ class FileSystemTemplate: public FileSystem {
|
|||||||
* Number of bytes after this Directory struct.
|
* Number of bytes after this Directory struct.
|
||||||
*/
|
*/
|
||||||
typename FileStore::FsSize_t size = 0;
|
typename FileStore::FsSize_t size = 0;
|
||||||
|
typename FileStore::FsSize_t children = 0;
|
||||||
|
|
||||||
DirectoryEntry *files() {
|
DirectoryEntry *files() {
|
||||||
return size ? (DirectoryEntry*) (this + 1) : nullptr;
|
return size ? (DirectoryEntry*) (this + 1) : nullptr;
|
||||||
@@ -121,6 +122,8 @@ class FileSystemTemplate: public FileSystem {
|
|||||||
|
|
||||||
uint64_t getFileInode(const char *name, uint64_t buffSize);
|
uint64_t getFileInode(const char *name, uint64_t buffSize);
|
||||||
|
|
||||||
|
int getChildrenInodes(typename FileStore::InodeId_t *inodes, size_t inodesLen);
|
||||||
|
|
||||||
int rmFile(const char *name);
|
int rmFile(const char *name);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,9 +149,9 @@ class FileSystemTemplate: public FileSystem {
|
|||||||
|
|
||||||
void resize(uint64_t size = 0) override;
|
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;
|
int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = NormalFile) override;
|
||||||
|
|
||||||
@@ -301,28 +304,51 @@ uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::read(uint64_t inode, size_t *si
|
|||||||
#pragma warning(default:4244)
|
#pragma warning(default:4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable:4244)
|
|
||||||
#endif
|
|
||||||
template<typename FileStore, FsType FS_TYPE>
|
template<typename FileStore, FsType FS_TYPE>
|
||||||
int FileSystemTemplate<FileStore, FS_TYPE>::remove(const char *path) {
|
int FileSystemTemplate<FileStore, FS_TYPE>::remove(const char *path, bool recursive) {
|
||||||
auto inode = findInodeOf(path);
|
auto inode = findInodeOf(path);
|
||||||
if (inode) {
|
if (inode) {
|
||||||
return remove(inode) | rmDirectoryEntry(path);
|
return remove(inode, recursive) | rmDirectoryEntry(path);
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(default:4244)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable:4244)
|
#pragma warning(disable:4244)
|
||||||
#endif
|
#endif
|
||||||
template<typename FileStore, FsType FS_TYPE>
|
template<typename FileStore, FsType FS_TYPE>
|
||||||
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode) {
|
int FileSystemTemplate<FileStore, FS_TYPE>::remove(uint64_t inode, bool recursive) {
|
||||||
return m_store->remove(inode);
|
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
|
#ifdef _MSC_VER
|
||||||
#pragma warning(default:4244)
|
#pragma warning(default:4244)
|
||||||
@@ -490,6 +516,7 @@ int FileSystemTemplate<FileStore, FS_TYPE>::insertDirectoryEntry(const char *dir
|
|||||||
if (!err) {
|
if (!err) {
|
||||||
auto dir = (Directory*) dirBuff;
|
auto dir = (Directory*) dirBuff;
|
||||||
dir->size += spaceNeeded;
|
dir->size += spaceNeeded;
|
||||||
|
dir->children++;
|
||||||
auto entry = (DirectoryEntry*) &dirBuff[s.size];
|
auto entry = (DirectoryEntry*) &dirBuff[s.size];
|
||||||
entry->inode = inode;
|
entry->inode = inode;
|
||||||
entry->setName(fileName);
|
entry->setName(fileName);
|
||||||
@@ -563,6 +590,24 @@ uint64_t FileSystemTemplate<FileStore, FS_TYPE>::Directory::getFileInode(const c
|
|||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename FileStore, FsType FS_TYPE>
|
||||||
|
int FileSystemTemplate<FileStore, FS_TYPE>::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<typename FileStore, FsType FS_TYPE>
|
template<typename FileStore, FsType FS_TYPE>
|
||||||
int FileSystemTemplate<FileStore, FS_TYPE>::Directory::rmFile(const char *name) {
|
int FileSystemTemplate<FileStore, FS_TYPE>::Directory::rmFile(const char *name) {
|
||||||
int err = 1;
|
int err = 1;
|
||||||
@@ -574,7 +619,8 @@ int FileSystemTemplate<FileStore, FS_TYPE>::Directory::rmFile(const char *name)
|
|||||||
auto dest = (uint8_t*) current;
|
auto dest = (uint8_t*) current;
|
||||||
auto src = dest + current->size();
|
auto src = dest + current->size();
|
||||||
ox_memcpy(dest, src, this->size - i);
|
ox_memcpy(dest, src, this->size - i);
|
||||||
this->size -= i;
|
this->size -= current->size();
|
||||||
|
this->children--;
|
||||||
err = 0;
|
err = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,4 @@ add_test("Test\\ PathIterator::fileName" FSTests PathIterator::fileName)
|
|||||||
add_test("Test\\ FileSystem32::findInodeOf\\ /" FSTests "FileSystem32::findInodeOf /")
|
add_test("Test\\ FileSystem32::findInodeOf\\ /" FSTests "FileSystem32::findInodeOf /")
|
||||||
add_test("Test\\ FileSystem32::write\\(string\\)" FSTests "FileSystem32::write(string)")
|
add_test("Test\\ FileSystem32::write\\(string\\)" FSTests "FileSystem32::write(string)")
|
||||||
add_test("Test\\ FileSystem32::rmDirectoryEntry\\(string\\)" FSTests "FileSystem32::rmDirectoryEntry(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)")
|
||||||
|
|||||||
+15
-10
@@ -9,6 +9,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <ox/fs/filesystem.hpp>
|
#include <ox/fs/filesystem.hpp>
|
||||||
#include <ox/fs/pathiterator.hpp>
|
#include <ox/fs/pathiterator.hpp>
|
||||||
@@ -138,7 +139,7 @@ map<string, int(*)(string)> tests = {
|
|||||||
auto dataOutLen = ox_strlen(dataIn) + 1;
|
auto dataOutLen = ox_strlen(dataIn) + 1;
|
||||||
auto dataOut = new char[dataOutLen];
|
auto dataOut = new char[dataOutLen];
|
||||||
|
|
||||||
const auto size = 1024 * 1024 * 10;
|
const auto size = 1024 * 1024;
|
||||||
auto buff = new uint8_t[size];
|
auto buff = new uint8_t[size];
|
||||||
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
|
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
|
||||||
auto fs = (FileSystem32*) createFileSystem(buff, size);
|
auto fs = (FileSystem32*) createFileSystem(buff, size);
|
||||||
@@ -191,29 +192,33 @@ map<string, int(*)(string)> tests = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"FileSystem32::remove(string)",
|
"FileSystem32::remove(string, true)",
|
||||||
[](string) {
|
[](string) {
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
auto path = "/usr/share/test.txt";
|
|
||||||
auto dataIn = "test string";
|
auto dataIn = "test string";
|
||||||
auto dataOutLen = ox_strlen(dataIn) + 1;
|
auto dataOutLen = 1024 * 64;
|
||||||
auto dataOut = new char[dataOutLen];
|
auto dataOut = new char[dataOutLen];
|
||||||
|
vector<uint64_t> inodes;
|
||||||
|
|
||||||
const auto size = 1024 * 1024 * 10;
|
const auto size = 1024 * 1024;
|
||||||
auto buff = new uint8_t[size];
|
auto buff = new uint8_t[size];
|
||||||
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
|
FileSystem32::format(buff, (FileStore32::FsSize_t) size, true);
|
||||||
auto fs = (FileSystem32*) createFileSystem(buff, size);
|
auto fs = (FileSystem32*) createFileSystem(buff, size);
|
||||||
|
|
||||||
retval |= fs->mkdir("/usr");
|
retval |= fs->mkdir("/usr");
|
||||||
retval |= fs->mkdir("/usr/share");
|
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);
|
inodes.push_back(fs->stat("/usr").inode);
|
||||||
retval |= fs->read(path, dataOut, dataOutLen);
|
inodes.push_back(fs->stat("/usr/share").inode);
|
||||||
retval |= ox_strcmp(dataIn, dataOut) != 0;
|
inodes.push_back(fs->stat("/usr/share/test.txt").inode);
|
||||||
|
|
||||||
|
retval |= fs->remove("/usr", true);
|
||||||
|
|
||||||
retval |= fs->rmDirectoryEntry(path);
|
|
||||||
// the lookup should fail
|
// 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 fs;
|
||||||
delete []buff;
|
delete []buff;
|
||||||
|
|||||||
Reference in New Issue
Block a user