From 544eb94f3442c8366264c0ae00ae04235b01a3ac Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 26 Apr 2017 04:01:19 -0500 Subject: [PATCH] Add support for removing directory entries --- src/ox/fs/filestore.hpp | 1 + src/ox/fs/filesystem.hpp | 80 +++++++++++++++++++++++++++++++---- src/ox/fs/test/CMakeLists.txt | 1 + src/ox/fs/test/tests.cpp | 32 ++++++++++++++ 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index 8acd7b025..847bb2ee2 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + #pragma once #include diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 52945a467..12350e009 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -95,15 +95,15 @@ class FileSystemTemplate: public FileSystem { data[nameLen] = 0; } + static uint64_t spaceNeeded(const char *fileName) { + return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1; + } + /** * The size in bytes. */ uint64_t size() { - return sizeof(DirectoryEntry) + ox_strlen(getName()); - } - - static uint64_t spaceNeeded(const char *fileName) { - return sizeof(DirectoryEntry) + ox_strlen(fileName) + 1; + return spaceNeeded(getName()); } }; @@ -118,6 +118,8 @@ class FileSystemTemplate: public FileSystem { } uint64_t getFileInode(const char *name, uint64_t buffSize); + + int rmFile(const char *name); }; FileStore *m_store = nullptr; @@ -162,6 +164,11 @@ class FileSystemTemplate: public FileSystem { uint8_t *buff() override; + /** + * Removes an entry from a directory. This does not delete the referred to file. + */ + int rmDirectoryEntry(const char *dirPath); + static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories); private: @@ -455,13 +462,14 @@ template int FileSystemTemplate::insertDirectoryEntry(const char *dirPath, const char *fileName, uint64_t inode) { auto s = stat(dirPath); if (s.inode) { - size_t dirBuffSize = s.size + DirectoryEntry::spaceNeeded(fileName); + auto spaceNeeded = DirectoryEntry::spaceNeeded(fileName); + size_t dirBuffSize = s.size + spaceNeeded; uint8_t dirBuff[dirBuffSize]; int err = read(s.inode, dirBuff, dirBuffSize); if (!err) { auto dir = (Directory*) dirBuff; - dir->size++; + dir->size += spaceNeeded; auto entry = (DirectoryEntry*) &dirBuff[s.size]; entry->inode = inode; entry->setName(fileName); @@ -477,6 +485,40 @@ int FileSystemTemplate::insertDirectoryEntry(const char *dir #pragma warning(default:4244) #endif +template +int FileSystemTemplate::rmDirectoryEntry(const char *path) { + int err = 0; + size_t pathLen = ox_strlen(path); + char dirPath[pathLen]; + char fileName[pathLen]; + PathIterator pathReader(path, pathLen); + err |= pathReader.fileName(fileName, pathLen); + err |= pathReader.dirPath(dirPath, pathLen); + if (err) { + return err; + } + + auto dirStat = stat(dirPath); + auto dirBuffLen = dirStat.size; + uint8_t dirBuff[dirBuffLen]; + + err = read(dirStat.inode, dirBuff, dirBuffLen); + if (err) { + return err; + } + + auto dir = (Directory*) dirBuff; + err = dir->rmFile(fileName); + + if (err) { + return err; + } + + err = write(dirStat.inode, dirBuff, dirBuffLen - DirectoryEntry::spaceNeeded(fileName)); + + return err; +} + // Directory @@ -485,7 +527,8 @@ uint64_t FileSystemTemplate::Directory::getFileInode(const c uint64_t inode = 0; auto current = files(); if (current) { - for (uint64_t i = 1; ox_strcmp(current->getName(), name) != 0; i++) { + for (uint64_t i = 0; ox_strcmp(current->getName(), name) != 0;) { + i += current->size(); if (i < this->size) { current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); } else { @@ -500,6 +543,27 @@ uint64_t FileSystemTemplate::Directory::getFileInode(const c return inode; } +template +int FileSystemTemplate::Directory::rmFile(const char *name) { + int err = 1; + auto current = files(); + if (current) { + for (uint64_t i = 0; i < this->size;) { + i += current->size(); + if (ox_strcmp(current->getName(), name) == 0) { + auto dest = (uint8_t*) current; + auto src = dest + current->size(); + ox_memcpy(dest, src, this->size - i); + this->size -= i; + err = 0; + break; + } + current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); + } + } + return err; +} + typedef FileSystemTemplate FileSystem16; typedef FileSystemTemplate FileSystem32; typedef FileSystemTemplate FileSystem64; diff --git a/src/ox/fs/test/CMakeLists.txt b/src/ox/fs/test/CMakeLists.txt index 90a8016f3..224efc9e6 100644 --- a/src/ox/fs/test/CMakeLists.txt +++ b/src/ox/fs/test/CMakeLists.txt @@ -39,3 +39,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)") diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp index 10e4d3466..321ad44ca 100644 --- a/src/ox/fs/test/tests.cpp +++ b/src/ox/fs/test/tests.cpp @@ -155,6 +155,38 @@ map tests = { delete []buff; delete []dataOut; + return retval; + } + }, + { + "FileSystem32::rmDirectoryEntry(string)", + [](string) { + int retval = 0; + auto path = "/usr/share/test.txt"; + auto dataIn = "test string"; + auto dataOutLen = ox_strlen(dataIn) + 1; + auto dataOut = new char[dataOutLen]; + + const auto size = 1024 * 1024 * 10; + 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(path, (void*) dataIn, ox_strlen(dataIn) + 1); + retval |= fs->read(path, dataOut, dataOutLen); + retval |= ox_strcmp(dataIn, dataOut) != 0; + + retval |= fs->rmDirectoryEntry(path); + // the lookup should fail + retval |= fs->read(path, dataOut, dataOutLen) == 0; + + delete fs; + delete []buff; + delete []dataOut; + return retval; } },