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:
typedef uint16_t InodeId_t;
typedef FsT FsSize_t;
const static auto VERSION = 2;
struct StatInfo {
InodeId_t inodeId;
@@ -41,16 +42,25 @@ class FileStore {
void *data();
};
uint32_t m_fsType;
uint16_t m_version;
uint16_t m_fsType;
FsSize_t m_size;
FsSize_t m_memUsed;
FsSize_t m_rootInode;
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
* 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.
@@ -90,9 +100,17 @@ class FileStore {
*/
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:
/**
@@ -124,7 +142,7 @@ class FileStore {
* Removes the given node from the linked list.
* @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
@@ -214,25 +232,49 @@ void *FileStore<FsSize_t>::Inode::data() {
// FileStore
template<typename FsSize_t>
void FileStore<FsSize_t>::resize() {
compact();
auto last = lastInode();
m_size = ptr(last) + last->size();
int FileStore<FsSize_t>::dumpTo(FileStore<FsSize_t> *dest) {
if (dest->size() >= size()) {
auto i = ptr<Inode*>(firstInode());
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>
int FileStore<FsSize_t>::write(InodeId_t id, void *data, FsSize_t dataLen, uint8_t fileType) {
auto retval = 1;
const FsSize_t size = sizeof(Inode) + dataLen;
auto inode = (Inode*) alloc(size);
if (inode) {
remove(id);
inode->id = id;
inode->fileType = fileType;
inode->setData(data, dataLen);
auto root = ptr<Inode*>(m_rootInode);
if (insert(root, inode) || root == inode) {
retval = 0;
if (size <= (m_size - m_memUsed)) {
auto inode = (Inode*) alloc(size);
if (inode) {
remove(id);
inode->id = id;
inode->fileType = fileType;
inode->setData(data, dataLen);
auto root = ptr<Inode*>(m_rootInode);
if (insert(root, inode) || root == inode) {
retval = 0;
}
}
}
return retval;
@@ -260,7 +302,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (node->left) {
insert(root, ptr<Inode*>(node->left));
}
unlink(node);
dealloc(node);
node->id = 0;
node->left = 0;
node->right = 0;
@@ -280,7 +322,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (node->left) {
insert(root, ptr<Inode*>(node->left));
}
unlink(node);
dealloc(node);
node->id = 0;
node->left = 0;
node->right = 0;
@@ -292,7 +334,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
if (root->left) {
insert(ptr<Inode*>(m_rootInode), ptr<Inode*>(root->left));
}
unlink(root);
dealloc(root);
root->id = 0;
root->left = 0;
root->right = 0;
@@ -303,15 +345,15 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
}
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 prev = ptr<Inode*>(inode->prev);
prev->next = ptr(next);
next->prev = ptr(prev);
m_memUsed -= inode->size();
ox_memset(inode, 0, inode->size());
inode->prev = firstInode();
inode->next = firstInode();
}
template<typename FsSize_t>
@@ -359,6 +401,11 @@ FsSize_t FileStore<FsSize_t>::size() {
return m_size;
}
template<typename FsSize_t>
FsSize_t FileStore<FsSize_t>::available() {
return m_size - m_memUsed;
}
template<typename FsSize_t>
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInode(Inode *root, InodeId_t id) {
Inode *retval = nullptr;
@@ -425,6 +472,7 @@ void *FileStore<FsSize_t>::alloc(FsSize_t size) {
ox_memset(inode, 0, size);
inode->prev = ptr<Inode*>(firstInode())->prev;
inode->next = retval + size;
m_memUsed += size;
ptr<Inode*>(firstInode())->prev = retval;
return inode;
}
@@ -498,19 +546,26 @@ typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::lastInode() {
}
template<typename FsSize_t>
uint8_t FileStore<FsSize_t>::version() {
return 1;
uint16_t FileStore<FsSize_t>::fsType() {
return m_fsType;
};
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);
auto *fs = (FileStore*) buffer;
fs->m_fsType = fsType;
fs->m_version = VERSION;
fs->m_size = size;
fs->m_memUsed = sizeof(FileStore<FsSize_t>) + sizeof(Inode);
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>);
return (uint8_t*) buffer;
+1 -1
View File
@@ -11,7 +11,7 @@ namespace ox {
namespace fs {
FileSystem *createFileSystem(void *buff) {
auto type = *((uint32_t*) buff);
auto type = ((FileStore16*) buff)->fsType();
FileSystem *fs = nullptr;
switch (type) {
+14 -7
View File
@@ -13,8 +13,6 @@
namespace ox {
namespace fs {
using namespace std;
enum FsType {
OxFS_16 = 1,
OxFS_32 = 2,
@@ -42,12 +40,14 @@ class FileSystem {
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 FileStat stat(uint64_t inode) = 0;
virtual uint64_t available() = 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;
void resize() override;
void resize(uint64_t size = 0) override;
int remove(uint64_t inode) override;
@@ -109,6 +109,8 @@ class FileSystemTemplate: public FileSystem {
FileStat stat(uint64_t inode) override;
uint64_t available() override;
uint64_t size() override;
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
template<typename FileStore, FsType FS_TYPE>
void FileSystemTemplate<FileStore, FS_TYPE>::resize() {
return store->resize();
void FileSystemTemplate<FileStore, FS_TYPE>::resize(uint64_t size) {
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>
@@ -222,7 +229,7 @@ uint64_t FileSystemTemplate<FileStore, FS_TYPE>::size() {
#endif
template<typename FileStore, FsType FS_TYPE>
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);
if (buffer && useDirectories) {
+29 -11
View File
@@ -24,9 +24,10 @@ const static auto oxfstoolVersion = "1.1.0";
const static auto usage = "usage:\n"
"\toxfs format [16,32,64] <size> <path>\n"
"\toxfs read <FS file> <inode>\n"
"\toxfs write <FS file> <inode> <insertion file>"
"\toxfs compact <FS file>"
"\toxfs write <FS file> <inode> <insertion file>\n"
"\toxfs write-expand <FS file> <inode> <insertion file>\n"
"\toxfs rm <FS file> <inode>\n"
"\toxfs compact <FS file>\n"
"\toxfs version\n";
char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) {
@@ -155,6 +156,7 @@ int read(int argc, char **args) {
if (output) {
fwrite(output, fileSize, 1, stdout);
delete []output;
err = 0;
}
@@ -172,7 +174,7 @@ int read(int argc, char **args) {
return err;
}
int write(int argc, char **args) {
int write(int argc, char **args, bool expand) {
auto err = 0;
if (argc >= 5) {
auto fsPath = args[2];
@@ -184,9 +186,9 @@ int write(int argc, char **args) {
if (fsFile) {
fseek(fsFile, 0, SEEK_END);
const auto fsSize = (size_t) ftell(fsFile);
auto fsSize = (size_t) ftell(fsFile);
rewind(fsFile);
auto fsBuff = (char*) malloc(fsSize);
auto fsBuff = new uint8_t[fsSize];
auto itemsRead = fread(fsBuff, fsSize, 1, fsFile);
fclose(fsFile);
@@ -195,10 +197,24 @@ int write(int argc, char **args) {
if (srcBuff) {
auto fs = createFileSystem(fsBuff);
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);
if (err) {
fprintf(stderr, "Could not write to file system.\n");
}
delete fs;
} else {
fprintf(stderr, "Invalid file system type: %d.\n", *(uint32_t*) fsBuff);
err = 1;
@@ -224,7 +240,7 @@ int write(int argc, char **args) {
}
}
free(fsBuff);
delete []fsBuff;
} else {
fprintf(stderr, "Could not open file system\n");
}
@@ -234,7 +250,7 @@ int write(int argc, char **args) {
return err;
}
int resize(int argc, char **args) {
int compact(int argc, char **args) {
auto err = 1;
if (argc >= 2) {
auto fsPath = args[2];
@@ -325,16 +341,18 @@ int main(int argc, char **args) {
} else if (ox_strcmp(cmd, "read") == 0) {
err = read(argc, args);
} else if (ox_strcmp(cmd, "write") == 0) {
err = write(argc, args);
} else if (ox_strcmp(cmd, "resize") == 0) {
err = resize(argc, args);
err = write(argc, args, false);
} else if (ox_strcmp(cmd, "write-expand") == 0) {
err = write(argc, args, true);
} else if (ox_strcmp(cmd, "compact") == 0) {
err = compact(argc, args);
} else if (ox_strcmp(cmd, "rm") == 0) {
err = remove(argc, args);
} else if (ox_strcmp(cmd, "help") == 0) {
printf("%s\n", usage);
} else if (ox_strcmp(cmd, "version") == 0) {
printf("oxfstool version %s\n", oxfstoolVersion);
printf("oxfs format version %d\n", FileStore16::version());
printf("oxfs format version %d\n", FileStore16::VERSION);
} else {
printf("Command '%s' not recognized.\n", cmd);
err = 1;