Add initial support for looking up file by path

This commit is contained in:
2017-04-23 04:10:12 -05:00
parent 32d50a42df
commit 7c54d3fb47
6 changed files with 186 additions and 26 deletions
+1
View File
@@ -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 {
+147 -26
View File
@@ -8,6 +8,7 @@
#pragma once
#include <ox/std/std.hpp>
#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<typename FileStore, FsType FS_TYPE>
FileSystemTemplate<FileStore, FS_TYPE>::FileSystemTemplate(void *buff) {
store = (FileStore*) buff;
m_store = (FileStore*) buff;
}
template<typename FileStore, FsType FS_TYPE>
@@ -164,7 +189,7 @@ FileStat FileSystemTemplate<FileStore, FS_TYPE>::stat(const char *path) {
template<typename FileStore, FsType FS_TYPE>
FileStat FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::stat(uint64_t inode) {
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::read(const char *path, void *buffer,
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::read(uint64_t inode, size_t readStar
#endif
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::read(uint64_t inode, size_t *si
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::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<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::remove(uint64_t inode) {
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::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<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer,
template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::resize(uint64_t size) {
return store->resize(size);
return m_store->resize(size);
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::spaceNeeded(uint64_t size) {
return store->spaceNeeded(size);
return m_store->spaceNeeded(size);
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::available() {
return store->available();
return m_store->available();
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::size() {
return store->size();
return m_store->size();
}
template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::buff() {
return (uint8_t*) store;
return (uint8_t*) m_store;
}
#ifdef _MSC_VER
@@ -294,10 +387,8 @@ uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename F
FileSystemTemplate<FileStore, FS_TYPE> 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<FileStore, FS_TYPE>::format(void *buffer, typename F
#pragma warning(default:4244)
#endif
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
template<typename FileStore, FsType FS_TYPE>
int FileSystemTemplate<FileStore, FS_TYPE>::insertDirectoryEntry(uint64_t inode, const char *dirPath, const char *fileName) {
return 0;
}
#ifdef _MSC_VER
#pragma warning(default:4244)
#endif
// Directory
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::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<FileStore16, OxFS_16> FileSystem16;
typedef FileSystemTemplate<FileStore32, OxFS_32> FileSystem32;
typedef FileSystemTemplate<FileStore64, OxFS_64> FileSystem64;
+17
View File
@@ -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;
}
}
}
+5
View File
@@ -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();
};
}
+3
View File
@@ -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)
+13
View File
@@ -90,6 +90,19 @@ map<string, int(*)(string)> 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;
}
},
},
};