diff --git a/src/ox/fs/filesystem.cpp b/src/ox/fs/filesystem.cpp index ccc57173a..2fef1603a 100644 --- a/src/ox/fs/filesystem.cpp +++ b/src/ox/fs/filesystem.cpp @@ -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/. */ + #include "filesystem.hpp" namespace ox { diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index fd4f83fd8..cbd00ff94 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include "pathiterator.hpp" #include "filestore.hpp" namespace ox { @@ -34,6 +35,8 @@ class FileSystem { public: virtual ~FileSystem() {}; + virtual int read(const char *path, void *buffer, size_t buffSize) = 0; + virtual int read(uint64_t inode, void *buffer, size_t size) = 0; virtual int read(uint64_t inode, size_t readStart, size_t readSize, void *buffer, size_t *size) = 0; @@ -44,6 +47,8 @@ class FileSystem { virtual void resize(uint64_t size = 0) = 0; + virtual int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0; + virtual int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType = NormalFile) = 0; virtual FileStat stat(uint64_t inode) = 0; @@ -87,6 +92,17 @@ class FileSystemTemplate: public FileSystem { ox_memcpy(data, &name, nameLen); data[nameLen] = 0; } + + /** + * 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); + } }; struct __attribute__((packed)) Directory { @@ -96,21 +112,23 @@ class FileSystemTemplate: public FileSystem { typename FileStore::InodeId_t size = 0; DirectoryEntry *files() { - return (DirectoryEntry*) (this + 1); + return size ? (DirectoryEntry*) (this + 1) : nullptr; } + + uint64_t getFileInode(const char *name, uint64_t buffSize); }; + FileStore *m_store = nullptr; + + public: // static members static typename FileStore::InodeId_t INODE_ROOT_DIR; - FileStore *store = nullptr; - - public: explicit FileSystemTemplate(void *buff); int mkdir(const char *path); - int read(const char *path, void *buffer, size_t buffSize); + int read(const char *path, void *buffer, size_t buffSize) override; int read(uint64_t inode, void *buffer, size_t buffSize) override; @@ -122,12 +140,16 @@ class FileSystemTemplate: public FileSystem { int remove(uint64_t inode) override; + int write(const char *path, void *buffer, uint64_t size, uint8_t fileType = NormalFile) override; + int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override; FileStat stat(const char *path); FileStat stat(uint64_t inode) override; + uint64_t findInodeOf(const char *name); + uint64_t spaceNeeded(uint64_t size) override; uint64_t available() override; @@ -137,11 +159,14 @@ class FileSystemTemplate: public FileSystem { uint8_t *buff() override; static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories); + + private: + int insertDirectoryEntry(uint64_t inode, const char *dirPath, const char *fileName); }; template FileSystemTemplate::FileSystemTemplate(void *buff) { - store = (FileStore*) buff; + m_store = (FileStore*) buff; } template @@ -164,7 +189,7 @@ FileStat FileSystemTemplate::stat(const char *path) { template FileStat FileSystemTemplate::stat(uint64_t inode) { FileStat stat; - auto s = store->stat(inode); + auto s = m_store->stat(inode); stat.size = s.size; stat.inode = s.inodeId; stat.fileType = s.fileType; @@ -179,7 +204,17 @@ FileStat FileSystemTemplate::stat(uint64_t inode) { #endif template int FileSystemTemplate::read(const char *path, void *buffer, size_t buffSize) { - return 0; + int retval = -1; + + // find the inode for the given path + auto inode = findInodeOf(path); + + // if inode exists, read the data into buffer + if (inode) { + read(inode, buffer, buffSize); + } + + return retval; } #ifdef _MSC_VER #pragma warning(default:4244) @@ -190,11 +225,11 @@ int FileSystemTemplate::read(const char *path, void *buffer, #endif template int FileSystemTemplate::read(uint64_t inode, void *buffer, size_t buffSize) { - auto stat = store->stat(inode); + auto stat = m_store->stat(inode); if (stat.size <= buffSize) { - return store->read(inode, buffer, nullptr); + return m_store->read(inode, buffer, nullptr); } - return 0; + return -1; ; } #ifdef _MSC_VER @@ -209,10 +244,10 @@ int FileSystemTemplate::read(uint64_t inode, size_t readStar size_t readSize, void *buffer, size_t *size) { if (size) { - auto stat = store->stat(inode); + auto stat = m_store->stat(inode); *size = stat.size; } - return store->read(inode, readStart, readSize, buffer, nullptr); + return m_store->read(inode, readStart, readSize, buffer, nullptr); } #ifdef _MSC_VER #pragma warning(disable:4244) @@ -223,12 +258,12 @@ int FileSystemTemplate::read(uint64_t inode, size_t readStar #endif template uint8_t *FileSystemTemplate::read(uint64_t inode, size_t *size) { - auto s = store->stat(inode); + auto s = m_store->stat(inode); auto buff = new uint8_t[s.size]; if (size) { *size = s.size; } - if (store->read(inode, buff, nullptr)) { + if (m_store->read(inode, buff, nullptr)) { delete []buff; buff = nullptr; } @@ -243,7 +278,28 @@ uint8_t *FileSystemTemplate::read(uint64_t inode, size_t *si #endif template int FileSystemTemplate::remove(uint64_t inode) { - return store->remove(inode); + return m_store->remove(inode); +} +#ifdef _MSC_VER +#pragma warning(default:4244) +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif +template +int FileSystemTemplate::write(const char *path, void *buffer, uint64_t size, uint8_t fileType) { + int retval = -1; + + // find the inode for the given path + auto inode = findInodeOf(path); + + // if inode exists, read the data into buffer + if (inode) { + retval = write(inode, buffer, size, fileType); + } + + return retval; } #ifdef _MSC_VER #pragma warning(default:4244) @@ -254,7 +310,44 @@ int FileSystemTemplate::remove(uint64_t inode) { #endif template int FileSystemTemplate::write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) { - return store->write(inode, buffer, size, fileType); + return m_store->write(inode, buffer, size, fileType); +} +#ifdef _MSC_VER +#pragma warning(default:4244) +#endif + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif +template +uint64_t FileSystemTemplate::findInodeOf(const char *path) { + const auto pathLen = ox_strlen(path); + PathIterator it(path, pathLen); + char fileName[pathLen]; + uint64_t inode = INODE_ROOT_DIR; + while (inode) { + auto dirStat = m_store->stat(inode); + if (dirStat.size >= sizeof(Directory)) { + uint8_t dirBuffer[dirStat.size]; + auto dir = (Directory*) dirBuffer; + if (read(inode, dirBuffer, dirStat.size) == 0) { + if (dirStat.fileType == FileType::Directory && it.next(fileName, pathLen) == 0) { + if (!it.hasNext()) { + // no further name components, inode points to the correct file + break; + } + inode = dir->getFileInode(fileName, dirStat.size); + } else { + inode = 0; // null out inode and break + } + } else { + inode = 0; // null out inode and break + } + } else { + inode = 0; // null out inode and break + } + } + return inode; } #ifdef _MSC_VER #pragma warning(default:4244) @@ -262,27 +355,27 @@ int FileSystemTemplate::write(uint64_t inode, void *buffer, template void FileSystemTemplate::resize(uint64_t size) { - return store->resize(size); + return m_store->resize(size); } template uint64_t FileSystemTemplate::spaceNeeded(uint64_t size) { - return store->spaceNeeded(size); + return m_store->spaceNeeded(size); } template uint64_t FileSystemTemplate::available() { - return store->available(); + return m_store->available(); } template uint64_t FileSystemTemplate::size() { - return store->size(); + return m_store->size(); } template uint8_t *FileSystemTemplate::buff() { - return (uint8_t*) store; + return (uint8_t*) m_store; } #ifdef _MSC_VER @@ -294,10 +387,8 @@ uint8_t *FileSystemTemplate::format(void *buffer, typename F FileSystemTemplate fs(buffer); if (buffer && useDirectories) { - char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2]; - auto *dir = (Directory*) dirBuff; - dir->files(); - fs.write(INODE_ROOT_DIR, dirBuff, useDirectories, FileType::Directory); + Directory dir; + fs.write(INODE_ROOT_DIR, &dir, sizeof(dir), FileType::Directory); } return (uint8_t*) buffer; @@ -306,6 +397,36 @@ uint8_t *FileSystemTemplate::format(void *buffer, typename F #pragma warning(default:4244) #endif +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif +template +int FileSystemTemplate::insertDirectoryEntry(uint64_t inode, const char *dirPath, const char *fileName) { + return 0; +} +#ifdef _MSC_VER +#pragma warning(default:4244) +#endif + +// Directory + +template +uint64_t FileSystemTemplate::Directory::getFileInode(const char *name, uint64_t buffSize) { + uint64_t retval = 0; + auto current = files(); + if (current) { + auto end = (DirectoryEntry*) ((uint8_t*) files()) + buffSize; + while (current && ox_strcmp(current->getName(), name) != 0) { + current = (DirectoryEntry*) ((uint8_t*) current) + current->size(); + if (current < end) { + current = nullptr; + } + } + retval = current->inode; + } + return retval; +} + typedef FileSystemTemplate FileSystem16; typedef FileSystemTemplate FileSystem32; typedef FileSystemTemplate FileSystem64; diff --git a/src/ox/fs/pathiterator.cpp b/src/ox/fs/pathiterator.cpp index 596116959..c53fd8fb1 100644 --- a/src/ox/fs/pathiterator.cpp +++ b/src/ox/fs/pathiterator.cpp @@ -42,5 +42,22 @@ int PathIterator::next(char *pathOut, size_t pathOutSize) { return retval; } +bool PathIterator::hasNext() { + size_t size = 0; + if (m_iterator < m_maxSize && ox_strlen(&m_path[m_iterator])) { + size_t start = m_iterator; + // end is at the next / + const char *substr = ox_strchr(&m_path[start], '/', m_maxSize - start); + // correct end if it is invalid, which happens if there is no next / + if (!substr) { + substr = ox_strchr(&m_path[start], 0, m_maxSize - start); + } + size_t end = substr - m_path; + size = end - start; + } + m_iterator += size; + return size > 0; +} + } } diff --git a/src/ox/fs/pathiterator.hpp b/src/ox/fs/pathiterator.hpp index 85de80c89..4c4921c99 100644 --- a/src/ox/fs/pathiterator.hpp +++ b/src/ox/fs/pathiterator.hpp @@ -22,7 +22,12 @@ class PathIterator { public: PathIterator(const char *path, size_t maxSize); + /** + * @return 0 if no error + */ int next(char *pathOut, size_t pathOutSize); + + bool hasNext(); }; } diff --git a/src/ox/fs/test/CMakeLists.txt b/src/ox/fs/test/CMakeLists.txt index 2ee7a32a5..d95fc0051 100644 --- a/src/ox/fs/test/CMakeLists.txt +++ b/src/ox/fs/test/CMakeLists.txt @@ -32,3 +32,6 @@ add_test("Test\\ PathIterator1" FSTests PathIterator1) add_test("Test\\ PathIterator2" FSTests PathIterator2) add_test("Test\\ PathIterator3" FSTests PathIterator3) add_test("Test\\ PathIterator4" FSTests PathIterator4) +add_test("Test\\ PathIterator5" FSTests PathIterator5) + +add_test("Test\\ FileSystem32::findInodeOf" FSTests FileSystem32::findInodeOf) diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp index 8e6607b88..9c6072f74 100644 --- a/src/ox/fs/test/tests.cpp +++ b/src/ox/fs/test/tests.cpp @@ -90,6 +90,19 @@ map tests = { return retval; } }, + { + "FileSystem32::findInodeOf", + [](string) { + int retval = 0; + const auto size = 1024; + uint8_t buff[size]; + FileSystem32::format(buff, (FileStore32::FsSize_t) size, true); + auto fs = (FileSystem32*) createFileSystem(buff, size); + retval |= !(fs->findInodeOf("/") == FileSystem32::INODE_ROOT_DIR); + delete fs; + return retval; + } + }, }, };