Add move and strip directories functionality to FileSystem
This commit is contained in:
@@ -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<Header>::remove(Inode *root, InodeId_t id) {
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename Header>
|
||||
int FileStore<Header>::removeAllType(uint8_t fileType) {
|
||||
int err = 0;
|
||||
auto first = ptr<Inode*>(firstInode());
|
||||
// skip the first inode for now, because removing the first inode will cause compact to run
|
||||
auto current = first;
|
||||
auto next = ptr<Inode*>(current->getNext());
|
||||
|
||||
while (next != first) {
|
||||
current = next;
|
||||
// get next before current is possibly cleared
|
||||
next = ptr<Inode*>(current->getNext());
|
||||
|
||||
if (current->getFileType() == fileType) {
|
||||
err |= remove(current->getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (first->getFileType() == fileType) {
|
||||
err |= remove(first->getId());
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename Header>
|
||||
void FileStore<Header>::dealloc(Inode *inode) {
|
||||
auto next = ptr<Inode*>(inode->getNext());
|
||||
|
||||
@@ -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<FileStore, FS_TYPE>::INODE_ROOT
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
typename FileStore::InodeId_t FileSystemTemplate<FileStore, FS_TYPE>::INODE_RESERVED_END = 100;
|
||||
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
int FileSystemTemplate<FileStore, FS_TYPE>::stripDirectories() {
|
||||
return m_store->removeAllType(FileType::Directory);
|
||||
}
|
||||
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
int FileSystemTemplate<FileStore, FS_TYPE>::mkdir(const char *path) {
|
||||
Directory dir;
|
||||
@@ -532,6 +548,48 @@ int FileSystemTemplate<FileStore, FS_TYPE>::insertDirectoryEntry(const char *dir
|
||||
#pragma warning(default:4244)
|
||||
#endif
|
||||
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
int FileSystemTemplate<FileStore, FS_TYPE>::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<typename FileStore, FsType FS_TYPE>
|
||||
int FileSystemTemplate<FileStore, FS_TYPE>::rmDirectoryEntry(const char *path) {
|
||||
int err = 0;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -224,6 +224,70 @@ map<string, int(*)(string)> 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<uint64_t> 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<uint64_t> 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;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user