Add oxfstool read and FileSystem base class
This commit is contained in:
@@ -6,3 +6,28 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#include "filesystem.hpp"
|
||||
|
||||
namespace ox {
|
||||
namespace fs {
|
||||
|
||||
FileSystem *createFileSystem(void *buff) {
|
||||
auto type = *((ox::std::uint32_t*) buff);
|
||||
FileSystem *fs = nullptr;
|
||||
|
||||
switch (type) {
|
||||
case ox::fs::OxFS16:
|
||||
fs = new FileSystem16(buff);
|
||||
break;
|
||||
case ox::fs::OxFS32:
|
||||
fs = new FileSystem32(buff);
|
||||
break;
|
||||
case ox::fs::OxFS64:
|
||||
fs = new FileSystem64(buff);
|
||||
break;
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+73
-16
@@ -26,8 +26,21 @@ struct FileStat {
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
template<typename FileStore>
|
||||
class FileSystem {
|
||||
public:
|
||||
virtual ~FileSystem() {};
|
||||
|
||||
virtual int read(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) = 0;
|
||||
|
||||
virtual ox::std::uint8_t *read(ox::std::uint64_t inode, ox::std::uint64_t *size) = 0;
|
||||
|
||||
virtual int write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) = 0;
|
||||
|
||||
virtual FileStat stat(ox::std::uint64_t inode) = 0;
|
||||
};
|
||||
|
||||
template<typename FileStore>
|
||||
class FileSystemTemplate: public FileSystem {
|
||||
|
||||
private:
|
||||
struct DirectoryEntry {
|
||||
@@ -62,33 +75,46 @@ class FileSystem {
|
||||
FileStore *store = nullptr;
|
||||
|
||||
public:
|
||||
FileSystemTemplate(void *buff);
|
||||
|
||||
int mkdir(const char *path);
|
||||
|
||||
int read(const char *path, void *buffer);
|
||||
|
||||
ox::std::uint8_t *read(ox::std::uint64_t inode, ox::std::uint64_t *size) override;
|
||||
|
||||
int read(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override;
|
||||
|
||||
int write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override;
|
||||
|
||||
FileStat stat(const char *path);
|
||||
|
||||
FileStat stat(typename FileStore::InodeId_t inode);
|
||||
FileStat stat(ox::std::uint64_t inode) override;
|
||||
|
||||
static uint8_t *format(uint8_t *buffer, typename FileStore::FsSize_t size);
|
||||
static ox::std::uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
|
||||
};
|
||||
|
||||
template<typename FileStore>
|
||||
typename FileStore::InodeId_t FileSystem<FileStore>::INODE_ROOT_DIR = 2;
|
||||
FileSystemTemplate<FileStore>::FileSystemTemplate(void *buff) {
|
||||
store = (FileStore*) buff;
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
int FileSystem<FileStore>::mkdir(const char *path) {
|
||||
typename FileStore::InodeId_t FileSystemTemplate<FileStore>::INODE_ROOT_DIR = 2;
|
||||
|
||||
template<typename FileStore>
|
||||
int FileSystemTemplate<FileStore>::mkdir(const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
FileStat FileSystem<FileStore>::stat(const char *path) {
|
||||
FileStat FileSystemTemplate<FileStore>::stat(const char *path) {
|
||||
FileStat stat;
|
||||
return stat;
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
FileStat FileSystem<FileStore>::stat(typename FileStore::InodeId_t inode) {
|
||||
FileStat FileSystemTemplate<FileStore>::stat(ox::std::uint64_t inode) {
|
||||
FileStat stat;
|
||||
auto s = store->stat(inode);
|
||||
stat.size = s.size;
|
||||
@@ -97,21 +123,52 @@ FileStat FileSystem<FileStore>::stat(typename FileStore::InodeId_t inode) {
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
uint8_t *FileSystem<FileStore>::format(uint8_t *buffer, typename FileStore::FsSize_t size) {
|
||||
buffer = FileStore::format(buffer, size);
|
||||
char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2];
|
||||
auto *dir = (Directory*) dirBuff;
|
||||
int FileSystemTemplate<FileStore>::read(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) {
|
||||
auto err = 1;
|
||||
auto s = store->stat(inode);
|
||||
if (size == s.size) {
|
||||
err = store->read(inode, buffer, nullptr);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
template<typename FileStore>
|
||||
ox::std::uint8_t *FileSystemTemplate<FileStore>::read(ox::std::uint64_t inode, ox::std::uint64_t *size) {
|
||||
auto s = store->stat(inode);
|
||||
auto buff = new ox::std::uint8_t[s.size];
|
||||
if (size) {
|
||||
*size = s.size;
|
||||
}
|
||||
if (store->read(inode, buff, nullptr)) {
|
||||
delete []buff;
|
||||
buff = nullptr;
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
int FileSystemTemplate<FileStore>::write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) {
|
||||
return store->write(inode, buffer, size);
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
ox::std::uint8_t *FileSystemTemplate<FileStore>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
|
||||
buffer = FileStore::format((ox::std::uint8_t*) buffer, size);
|
||||
|
||||
if (buffer && useDirectories) {
|
||||
char dirBuff[sizeof(Directory) + sizeof(DirectoryEntry) + 2];
|
||||
auto *dir = (Directory*) dirBuff;
|
||||
dir->files();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
return (ox::std::uint8_t*) buffer;
|
||||
}
|
||||
|
||||
typedef FileSystem<FileStore16> FileSystem16;
|
||||
typedef FileSystem<FileStore32> FileSystem32;
|
||||
typedef FileSystem<FileStore64> FileSystem64;
|
||||
typedef FileSystemTemplate<FileStore16> FileSystem16;
|
||||
typedef FileSystemTemplate<FileStore32> FileSystem32;
|
||||
typedef FileSystemTemplate<FileStore64> FileSystem64;
|
||||
|
||||
FileSystem *createFileSystem(void *buff);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+57
-34
@@ -14,13 +14,15 @@ using namespace ox::fs;
|
||||
|
||||
const char *usage = "usage:\n"
|
||||
"\toxfs format [16,32,64] <size> <path>\n"
|
||||
"\toxfs read <FS file> <inode>\n"
|
||||
"\toxfs write <FS file> <inode> <insertion file>";
|
||||
|
||||
char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) {
|
||||
FILE *file = fopen(path, "rw");
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (file) {
|
||||
fseek(file, 0, SEEK_END);
|
||||
const auto size = ftell(file);
|
||||
rewind(file);
|
||||
auto buff = (char*) malloc(size);
|
||||
fread(buff, size, 1, file);
|
||||
fclose(file);
|
||||
@@ -57,8 +59,9 @@ int format(int argc, char **args) {
|
||||
FileStore64::format(buff, size, ox::fs::OxFS64);
|
||||
break;
|
||||
}
|
||||
createFileSystem(buff);
|
||||
|
||||
FILE *file = fopen(path, "w");
|
||||
auto file = fopen(path, "wb");
|
||||
if (file) {
|
||||
fwrite(buff, size, 1, file);
|
||||
err = fclose(file);
|
||||
@@ -77,6 +80,28 @@ int format(int argc, char **args) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int read(int argc, char **args) {
|
||||
auto err = 1;
|
||||
if (argc >= 4) {
|
||||
auto fsPath = args[2];
|
||||
auto inode = ox::std::atoi(args[3]);
|
||||
::size_t fsSize;
|
||||
ox::std::uint64_t fileSize;
|
||||
|
||||
auto fs = createFileSystem(loadFileBuff(fsPath, &fsSize));
|
||||
|
||||
auto output = fs->read(inode, &fileSize);
|
||||
|
||||
if (output) {
|
||||
fwrite(output, fileSize, 1, stdout);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
delete fs;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int write(int argc, char **args) {
|
||||
auto err = 0;
|
||||
if (argc >= 5) {
|
||||
@@ -85,50 +110,46 @@ int write(int argc, char **args) {
|
||||
auto srcPath = args[4];
|
||||
::size_t srcSize;
|
||||
|
||||
FILE *fsFile = fopen(fsPath, "rw");
|
||||
auto fsFile = fopen(fsPath, "rwb");
|
||||
if (fsFile) {
|
||||
fseek(fsFile, 0, SEEK_END);
|
||||
|
||||
const auto fsSize = ftell(fsFile);
|
||||
auto fs = (char*) malloc(fsSize);
|
||||
fread(fs, fsSize, 1, fsFile);
|
||||
const auto fsSize = (::size_t) ftell(fsFile);
|
||||
rewind(fsFile);
|
||||
auto fsBuff = (char*) malloc(fsSize);
|
||||
fread(fsBuff, fsSize, 1, fsFile);
|
||||
fclose(fsFile);
|
||||
|
||||
auto srcBuff = loadFileBuff(srcPath, &srcSize);
|
||||
if (srcBuff) {
|
||||
auto type = *((ox::std::uint32_t*) fs);
|
||||
switch (type) {
|
||||
case ox::fs::OxFS16:
|
||||
err |= ((FileStore16*) fs)->write(inode, srcBuff, srcSize);
|
||||
break;
|
||||
case ox::fs::OxFS32:
|
||||
err |= ((FileStore32*) fs)->write(inode, srcBuff, srcSize);
|
||||
break;
|
||||
case ox::fs::OxFS64:
|
||||
err |= ((FileStore64*) fs)->write(inode, srcBuff, srcSize);
|
||||
break;
|
||||
auto fs = createFileSystem(fsBuff);
|
||||
if (fs) {
|
||||
err |= fs->write(inode, srcBuff, srcSize);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid file system.\n");
|
||||
}
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
} else {
|
||||
fsFile = fopen(fsPath, "wb");
|
||||
|
||||
if (fsFile) {
|
||||
err = fwrite(fsBuff, fsSize, 1, fsFile) != 1;
|
||||
err |= fclose(fsFile);
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system file.\n");
|
||||
}
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = 1;
|
||||
fprintf(stderr, "Could not load source file.\n");
|
||||
}
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
err = 0;
|
||||
} else {
|
||||
err = fwrite(fs, fsSize, 1, fsFile);
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
}
|
||||
}
|
||||
|
||||
err = fclose(fsFile);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system file.\n");
|
||||
}
|
||||
|
||||
free(fs);
|
||||
free(fsBuff);
|
||||
free(srcBuff);
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file system\n");
|
||||
@@ -143,6 +164,8 @@ int main(int argc, char **args) {
|
||||
auto cmd = args[1];
|
||||
if (::strcmp(cmd, "format") == 0) {
|
||||
err = format(argc, args);
|
||||
} else if (::strcmp(cmd, "read") == 0) {
|
||||
err = read(argc, args);
|
||||
} else if (::strcmp(cmd, "write") == 0) {
|
||||
err = write(argc, args);
|
||||
} else if (::strcmp(cmd, "help") == 0) {
|
||||
|
||||
@@ -15,7 +15,7 @@ template<typename FileSystem>
|
||||
int test() {
|
||||
const ox::std::uint16_t size = ~0;
|
||||
ox::std::uint8_t volume[size];
|
||||
FileSystem::format(volume, size);
|
||||
FileSystem::format(volume, size, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user