Add write-expand command to oxfstool
This commit is contained in:
+83
-28
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user