Add write-expand command to oxfstool

This commit is contained in:
2017-04-08 03:41:48 -05:00
parent a3f5af23fe
commit b1e1e764a9
4 changed files with 127 additions and 47 deletions
+83 -28
View File
@@ -18,6 +18,7 @@ class FileStore {
public: public:
typedef uint16_t InodeId_t; typedef uint16_t InodeId_t;
typedef FsT FsSize_t; typedef FsT FsSize_t;
const static auto VERSION = 2;
struct StatInfo { struct StatInfo {
InodeId_t inodeId; InodeId_t inodeId;
@@ -41,16 +42,25 @@ class FileStore {
void *data(); void *data();
}; };
uint32_t m_fsType; uint16_t m_version;
uint16_t m_fsType;
FsSize_t m_size; FsSize_t m_size;
FsSize_t m_memUsed;
FsSize_t m_rootInode; FsSize_t m_rootInode;
public: public:
/**
* Dumps this file store's inodes to the given file store.
*/
int dumpTo(FileStore<FsSize_t> *dest);
/** /**
* Compacts and resizes the file store to the minimum possible size for * Compacts and resizes the file store to the minimum possible size for
* the contents. * the contents.
*
* NOTE: This does NOT resize the buffer that this file store refers to!
*/ */
void resize(); void resize(FsSize_t size = 0);
/** /**
* Writes the given data to a "file" with the given id. * Writes the given data to a "file" with the given id.
@@ -90,9 +100,17 @@ class FileStore {
*/ */
FsSize_t size(); FsSize_t size();
static uint8_t version(); /**
* Returns the space currently available in this file store.
* @return the space currently available in this file store.
*/
FsSize_t available();
uint16_t fsType();
uint16_t version();
static uint8_t *format(uint8_t *buffer, FsSize_t size, uint32_t fsType = 0); static uint8_t *format(uint8_t *buffer, FsSize_t size, uint16_t fsType = 0);
private: private:
/** /**
@@ -124,7 +142,7 @@ class FileStore {
* Removes the given node from the linked list. * Removes the given node from the linked list.
* @param node node to remove * @param node node to remove
*/ */
void unlink(Inode *node); void dealloc(Inode *node);
/** /**
* Gets the address of the next available inode, assuming there is a next * Gets the address of the next available inode, assuming there is a next
@@ -214,25 +232,49 @@ void *FileStore<FsSize_t>::Inode::data() {
// FileStore // FileStore
template<typename FsSize_t> template<typename FsSize_t>
void FileStore<FsSize_t>::resize() { int FileStore<FsSize_t>::dumpTo(FileStore<FsSize_t> *dest) {
compact(); if (dest->size() >= size()) {
auto last = lastInode(); auto i = ptr<Inode*>(firstInode());
m_size = ptr(last) + last->size(); do {
dest->write(i->id, i->data(), i->dataLen, i->fileType);
i = ptr<Inode*>(i->next);
} while (ptr(i) != firstInode());
return 0;
} else {
return -1;
}
}
template<typename FsSize_t>
void FileStore<FsSize_t>::resize(FsSize_t size) {
if (size < m_size) {
// shrink file store
if (m_memUsed > size) {
size = m_memUsed;
}
compact();
m_size = size;
} else if (size > m_size) {
// grow file store
m_size = size;
}
} }
template<typename FsSize_t> template<typename FsSize_t>
int FileStore<FsSize_t>::write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType) { int FileStore<FsSize_t>::write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType) {
auto retval = 1; auto retval = 1;
const FsSize_t size = sizeof(Inode) + dataLen; const FsSize_t size = sizeof(Inode) + dataLen;
auto inode = (Inode*) alloc(size); if (size <= (m_size - m_memUsed)) {
if (inode) { auto inode = (Inode*) alloc(size);
remove(id); if (inode) {
inode->id = id; remove(id);
inode->fileType = fileType; inode->id = id;
inode->setData(data, dataLen); inode->fileType = fileType;
auto root = ptr<Inode*>(m_rootInode); inode->setData(data, dataLen);
if (insert(root, inode) || root == inode) { auto root = ptr<Inode*>(m_rootInode);
retval = 0; if (insert(root, inode) || root == inode) {
retval = 0;
}
} }
} }
return retval; return retval;
@@ -260,7 +302,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (node->left) { if (node->left) {
insert(root, ptr<Inode*>(node->left)); insert(root, ptr<Inode*>(node->left));
} }
unlink(node); dealloc(node);
node->id = 0; node->id = 0;
node->left = 0; node->left = 0;
node->right = 0; node->right = 0;
@@ -280,7 +322,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (node->left) { if (node->left) {
insert(root, ptr<Inode*>(node->left)); insert(root, ptr<Inode*>(node->left));
} }
unlink(node); dealloc(node);
node->id = 0; node->id = 0;
node->left = 0; node->left = 0;
node->right = 0; node->right = 0;
@@ -292,7 +334,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (root->left) { if (root->left) {
insert(ptr<Inode*>(m_rootInode), ptr<Inode*>(root->left)); insert(ptr<Inode*>(m_rootInode), ptr<Inode*>(root->left));
} }
unlink(root); dealloc(root);
root->id = 0; root->id = 0;
root->left = 0; root->left = 0;
root->right = 0; root->right = 0;
@@ -303,15 +345,15 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
} }
template<typename FsSize_t> template<typename FsSize_t>
void FileStore<FsSize_t>::unlink(Inode *inode) { void FileStore<FsSize_t>::dealloc(Inode *inode) {
auto next = ptr<Inode*>(inode->next); auto next = ptr<Inode*>(inode->next);
auto prev = ptr<Inode*>(inode->prev); auto prev = ptr<Inode*>(inode->prev);
prev->next = ptr(next); prev->next = ptr(next);
next->prev = ptr(prev); next->prev = ptr(prev);
m_memUsed -= inode->size();
ox_memset(inode, 0, inode->size()); ox_memset(inode, 0, inode->size());
inode->prev = firstInode();
inode->next = firstInode();
} }
template<typename FsSize_t> template<typename FsSize_t>
@@ -359,6 +401,11 @@ FsSize_t FileStore<FsSize_t>::size() {
return m_size; return m_size;
} }
template<typename FsSize_t>
FsSize_t FileStore<FsSize_t>::available() {
return m_size - m_memUsed;
}
template<typename FsSize_t> template<typename FsSize_t>
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInode(Inode *root, InodeId_t id) { typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInode(Inode *root, InodeId_t id) {
Inode *retval = nullptr; Inode *retval = nullptr;
@@ -425,6 +472,7 @@ void *FileStore<FsSize_t>::alloc(FsSize_t size) {
ox_memset(inode, 0, size); ox_memset(inode, 0, size);
inode->prev = ptr<Inode*>(firstInode())->prev; inode->prev = ptr<Inode*>(firstInode())->prev;
inode->next = retval + size; inode->next = retval + size;
m_memUsed += size;
ptr<Inode*>(firstInode())->prev = retval; ptr<Inode*>(firstInode())->prev = retval;
return inode; return inode;
} }
@@ -498,19 +546,26 @@ typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::lastInode() {
} }
template<typename FsSize_t> template<typename FsSize_t>
uint8_t FileStore<FsSize_t>::version() { uint16_t FileStore<FsSize_t>::fsType() {
return 1; return m_fsType;
}; };
template<typename FsSize_t> template<typename FsSize_t>
uint8_t *FileStore<FsSize_t>::format(uint8_t *buffer, FsSize_t size, uint32_t fsType) { uint16_t FileStore<FsSize_t>::version() {
return m_version;
};
template<typename FsSize_t>
uint8_t *FileStore<FsSize_t>::format(uint8_t *buffer, FsSize_t size, uint16_t fsType) {
ox_memset(buffer, 0, size); ox_memset(buffer, 0, size);
auto *fs = (FileStore*) buffer; auto *fs = (FileStore*) buffer;
fs->m_fsType = fsType; fs->m_fsType = fsType;
fs->m_version = VERSION;
fs->m_size = size; fs->m_size = size;
fs->m_memUsed = sizeof(FileStore<FsSize_t>) + sizeof(Inode);
fs->m_rootInode = sizeof(FileStore<FsSize_t>); fs->m_rootInode = sizeof(FileStore<FsSize_t>);
((Inode*) (fs + 1))->prev = fs->firstInode(); ((Inode*) (fs + 1))->prev = sizeof(FileStore<FsSize_t>);
fs->lastInode()->next = sizeof(FileStore<FsSize_t>); fs->lastInode()->next = sizeof(FileStore<FsSize_t>);
return (uint8_t*) buffer; return (uint8_t*) buffer;
+1 -1
View File
@@ -11,7 +11,7 @@ namespace ox {
namespace fs { namespace fs {
FileSystem *createFileSystem(void *buff) { FileSystem *createFileSystem(void *buff) {
auto type = *((uint32_t*) buff); auto type = ((FileStore16*) buff)->fsType();
FileSystem *fs = nullptr; FileSystem *fs = nullptr;
switch (type) { switch (type) {
+14 -7
View File
@@ -13,8 +13,6 @@
namespace ox { namespace ox {
namespace fs { namespace fs {
using namespace std;
enum FsType { enum FsType {
OxFS_16 = 1, OxFS_16 = 1,
OxFS_32 = 2, OxFS_32 = 2,
@@ -42,12 +40,14 @@ class FileSystem {
virtual int remove(uint64_t inode) = 0; virtual int remove(uint64_t inode) = 0;
virtual void resize() = 0; virtual void resize(uint64_t size = 0) = 0;
virtual int write(uint64_t inode, 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; virtual FileStat stat(uint64_t inode) = 0;
virtual uint64_t available() = 0;
virtual uint64_t size() = 0; virtual uint64_t size() = 0;
}; };
@@ -99,7 +99,7 @@ class FileSystemTemplate: public FileSystem {
int read(uint64_t inode, void *buffer, size_t size) override; int read(uint64_t inode, void *buffer, size_t size) override;
void resize() override; void resize(uint64_t size = 0) override;
int remove(uint64_t inode) override; int remove(uint64_t inode) override;
@@ -109,6 +109,8 @@ class FileSystemTemplate: public FileSystem {
FileStat stat(uint64_t inode) override; FileStat stat(uint64_t inode) override;
uint64_t available() override;
uint64_t size() override; uint64_t size() override;
static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories); static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
@@ -208,8 +210,13 @@ int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer,
#endif #endif
template<typename FileStore, FsType FS_TYPE> template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::resize() { void FileSystemTemplate<FileStore, FS_TYPE>::resize(uint64_t size) {
return store->resize(); return store->resize(size);
}
template<typename FileStore, FsType FS_TYPE>
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::available() {
return store->available();
} }
template<typename FileStore, FsType FS_TYPE> template<typename FileStore, FsType FS_TYPE>
@@ -222,7 +229,7 @@ uint64_t FileSystemTemplate<FileStore, FS_TYPE>::size() {
#endif #endif
template<typename FileStore, FsType FS_TYPE> template<typename FileStore, FsType FS_TYPE>
uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) { uint8_t *FileSystemTemplate<FileStore, FS_TYPE>::format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories) {
buffer = FileStore::format((uint8_t*) buffer, size, (uint32_t) FS_TYPE); buffer = FileStore::format((uint8_t*) buffer, size, (uint16_t) FS_TYPE);
FileSystemTemplate<FileStore, FS_TYPE> fs(buffer); FileSystemTemplate<FileStore, FS_TYPE> fs(buffer);
if (buffer && useDirectories) { if (buffer && useDirectories) {
+29 -11
View File
@@ -24,9 +24,10 @@ const static auto oxfstoolVersion = "1.1.0";
const static auto usage = "usage:\n" const static auto usage = "usage:\n"
"\toxfs format [16,32,64] <size> <path>\n" "\toxfs format [16,32,64] <size> <path>\n"
"\toxfs read <FS file> <inode>\n" "\toxfs read <FS file> <inode>\n"
"\toxfs write <FS file> <inode> <insertion file>" "\toxfs write <FS file> <inode> <insertion file>\n"
"\toxfs compact <FS file>" "\toxfs write-expand <FS file> <inode> <insertion file>\n"
"\toxfs rm <FS file> <inode>\n" "\toxfs rm <FS file> <inode>\n"
"\toxfs compact <FS file>\n"
"\toxfs version\n"; "\toxfs version\n";
char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) { char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) {
@@ -155,6 +156,7 @@ int read(int argc, char **args) {
if (output) { if (output) {
fwrite(output, fileSize, 1, stdout); fwrite(output, fileSize, 1, stdout);
delete []output;
err = 0; err = 0;
} }
@@ -172,7 +174,7 @@ int read(int argc, char **args) {
return err; return err;
} }
int write(int argc, char **args) { int write(int argc, char **args, bool expand) {
auto err = 0; auto err = 0;
if (argc >= 5) { if (argc >= 5) {
auto fsPath = args[2]; auto fsPath = args[2];
@@ -184,9 +186,9 @@ int write(int argc, char **args) {
if (fsFile) { if (fsFile) {
fseek(fsFile, 0, SEEK_END); fseek(fsFile, 0, SEEK_END);
const auto fsSize = (size_t) ftell(fsFile); auto fsSize = (size_t) ftell(fsFile);
rewind(fsFile); rewind(fsFile);
auto fsBuff = (char*) malloc(fsSize); auto fsBuff = new uint8_t[fsSize];
auto itemsRead = fread(fsBuff, fsSize, 1, fsFile); auto itemsRead = fread(fsBuff, fsSize, 1, fsFile);
fclose(fsFile); fclose(fsFile);
@@ -195,10 +197,24 @@ int write(int argc, char **args) {
if (srcBuff) { if (srcBuff) {
auto fs = createFileSystem(fsBuff); auto fs = createFileSystem(fsBuff);
if (fs) { if (fs) {
if (expand && fs->available() <= srcSize) {
auto needed = (fs->size() - fs->available()) + fsSize;
auto cloneBuff = new uint8_t[needed];
ox_memcpy(cloneBuff, fsBuff, fsSize);
delete fs;
delete []fsBuff;
fsBuff = cloneBuff;
fs = createFileSystem(fsBuff);
fsSize = needed;
fs->resize(fsSize);
}
err |= fs->write(inode, srcBuff, srcSize); err |= fs->write(inode, srcBuff, srcSize);
if (err) { if (err) {
fprintf(stderr, "Could not write to file system.\n"); fprintf(stderr, "Could not write to file system.\n");
} }
delete fs;
} else { } else {
fprintf(stderr, "Invalid file system type: %d.\n", *(uint32_t*) fsBuff); fprintf(stderr, "Invalid file system type: %d.\n", *(uint32_t*) fsBuff);
err = 1; err = 1;
@@ -224,7 +240,7 @@ int write(int argc, char **args) {
} }
} }
free(fsBuff); delete []fsBuff;
} else { } else {
fprintf(stderr, "Could not open file system\n"); fprintf(stderr, "Could not open file system\n");
} }
@@ -234,7 +250,7 @@ int write(int argc, char **args) {
return err; return err;
} }
int resize(int argc, char **args) { int compact(int argc, char **args) {
auto err = 1; auto err = 1;
if (argc >= 2) { if (argc >= 2) {
auto fsPath = args[2]; auto fsPath = args[2];
@@ -325,16 +341,18 @@ int main(int argc, char **args) {
} else if (ox_strcmp(cmd, "read") == 0) { } else if (ox_strcmp(cmd, "read") == 0) {
err = read(argc, args); err = read(argc, args);
} else if (ox_strcmp(cmd, "write") == 0) { } else if (ox_strcmp(cmd, "write") == 0) {
err = write(argc, args); err = write(argc, args, false);
} else if (ox_strcmp(cmd, "resize") == 0) { } else if (ox_strcmp(cmd, "write-expand") == 0) {
err = resize(argc, args); err = write(argc, args, true);
} else if (ox_strcmp(cmd, "compact") == 0) {
err = compact(argc, args);
} else if (ox_strcmp(cmd, "rm") == 0) { } else if (ox_strcmp(cmd, "rm") == 0) {
err = remove(argc, args); err = remove(argc, args);
} else if (ox_strcmp(cmd, "help") == 0) { } else if (ox_strcmp(cmd, "help") == 0) {
printf("%s\n", usage); printf("%s\n", usage);
} else if (ox_strcmp(cmd, "version") == 0) { } else if (ox_strcmp(cmd, "version") == 0) {
printf("oxfstool version %s\n", oxfstoolVersion); printf("oxfstool version %s\n", oxfstoolVersion);
printf("oxfs format version %d\n", FileStore16::version()); printf("oxfs format version %d\n", FileStore16::VERSION);
} else { } else {
printf("Command '%s' not recognized.\n", cmd); printf("Command '%s' not recognized.\n", cmd);
err = 1; err = 1;