Add resize option to oxfstool
This commit is contained in:
+35
-21
@@ -41,11 +41,17 @@ class FileStore {
|
||||
void *data();
|
||||
};
|
||||
|
||||
uint32_t m_fsType;
|
||||
uint32_t m_fsType;
|
||||
FsSize_t m_size;
|
||||
FsSize_t m_rootInode;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Compacts and resizes the file store to the minimum possible size for
|
||||
* the contents.
|
||||
*/
|
||||
void resize();
|
||||
|
||||
/**
|
||||
* Writes the given data to a "file" with the given id.
|
||||
* @param id the id of the file
|
||||
@@ -111,9 +117,10 @@ class FileStore {
|
||||
* @param root the root node to start comparing on
|
||||
* @param id id of the "file"
|
||||
* @param pathLen number of characters in pathLen
|
||||
* @param targetAddr the address of the target inode
|
||||
* @return the requested Inode, if available
|
||||
*/
|
||||
Inode *getInodeParent(Inode *root, InodeId_t id);
|
||||
Inode *getInodeParent(Inode *root, InodeId_t id, FsSize_t targetAddr);
|
||||
|
||||
/**
|
||||
* Removes the inode of the given ID.
|
||||
@@ -140,9 +147,9 @@ class FileStore {
|
||||
void *alloc(FsSize_t size);
|
||||
|
||||
/**
|
||||
* Compresses all of the inode into a contiguous space, starting at the first inode.
|
||||
* Compacts all of the inodes into a contiguous space, starting at the first inode.
|
||||
*/
|
||||
void compress(FsSize_t firstInode);
|
||||
void compact();
|
||||
|
||||
/**
|
||||
* Inserts the given insertValue into the tree of the given root.
|
||||
@@ -164,7 +171,7 @@ class FileStore {
|
||||
/**
|
||||
* Updates the address of the inode in the tree.
|
||||
*/
|
||||
void updateInodeAddress(InodeId_t id, FsSize_t addr);
|
||||
void updateInodeAddress(InodeId_t id, FsSize_t oldAddr, FsSize_t newAddr);
|
||||
|
||||
uint8_t *begin() {
|
||||
return (uint8_t*) this;
|
||||
@@ -214,6 +221,13 @@ 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();
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
int FileStore<FsSize_t>::write(void *data, FsSize_t dataLen, uint8_t fileType) {
|
||||
return 1;
|
||||
@@ -314,13 +328,13 @@ void FileStore<FsSize_t>::unlink(Inode *inode) {
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void FileStore<FsSize_t>::updateInodeAddress(InodeId_t id, FsSize_t addr) {
|
||||
auto parent = getInodeParent(ptr<Inode*>(m_rootInode), id);
|
||||
void FileStore<FsSize_t>::updateInodeAddress(InodeId_t id, FsSize_t oldAddr, FsSize_t newAddr) {
|
||||
auto parent = getInodeParent(ptr<Inode*>(m_rootInode), id, oldAddr);
|
||||
if (parent) {
|
||||
if (parent->left && ptr<Inode*>(parent->left)->id == id) {
|
||||
parent->left = addr;
|
||||
} else if (parent->right && ptr<Inode*>(parent->right)->id == id) {
|
||||
parent->right = addr;
|
||||
if (parent->left == oldAddr) {
|
||||
parent->left = newAddr;
|
||||
} else if (parent->right == oldAddr) {
|
||||
parent->right = newAddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,23 +392,23 @@ typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInode(Inode *root,
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInodeParent(Inode *root, InodeId_t id) {
|
||||
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInodeParent(Inode *root, InodeId_t id, FsSize_t targetAddr) {
|
||||
Inode *retval = nullptr;
|
||||
|
||||
if (root->id > id) {
|
||||
if (root->left) {
|
||||
if (ptr<Inode*>(root->left)->id == id) {
|
||||
if (root->left == targetAddr) {
|
||||
retval = root;
|
||||
} else {
|
||||
retval = getInode(ptr<Inode*>(root->left), id);
|
||||
retval = getInodeParent(ptr<Inode*>(root->left), id, targetAddr);
|
||||
}
|
||||
}
|
||||
} else if (root->id < id) {
|
||||
if (root->right) {
|
||||
if (ptr<Inode*>(root->right)->id == id) {
|
||||
if (root->right == targetAddr) {
|
||||
retval = root;
|
||||
} else {
|
||||
retval = getInode(ptr<Inode*>(root->right), id);
|
||||
retval = getInodeParent(ptr<Inode*>(root->right), id, targetAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -412,7 +426,7 @@ template<typename FsSize_t>
|
||||
void *FileStore<FsSize_t>::alloc(FsSize_t size) {
|
||||
FsSize_t next = nextInodeAddr();
|
||||
if ((next + size) > (uint64_t) end()) {
|
||||
compress(firstInode());
|
||||
compact();
|
||||
next = nextInodeAddr();
|
||||
if ((next + size) > (uint64_t) end()) {
|
||||
return nullptr;
|
||||
@@ -429,18 +443,18 @@ void *FileStore<FsSize_t>::alloc(FsSize_t size) {
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void FileStore<FsSize_t>::compress(FsSize_t start) {
|
||||
void FileStore<FsSize_t>::compact() {
|
||||
auto dest = ptr<Inode*>(firstInode());
|
||||
auto current = ptr<Inode*>(start);
|
||||
while (current->next > ptr(begin()) && current->next < ptr(end())) {
|
||||
auto current = ptr<Inode*>(firstInode());
|
||||
while (current->next > firstInode() && current->next < ptr(end())) {
|
||||
ox_memcpy(dest, current, current->size());
|
||||
if (dest->next != firstInode()) {
|
||||
dest->next = ptr(dest) + dest->size();
|
||||
}
|
||||
ptr<Inode*>(dest->next)->prev = ptr(dest);
|
||||
updateInodeAddress(dest->id, ptr(current), ptr(dest));
|
||||
current = ptr<Inode*>(dest->next);
|
||||
dest = ptr<Inode*>(ptr(dest) + dest->size());
|
||||
updateInodeAddress(dest->id, ptr(dest));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,13 @@ class FileSystem {
|
||||
|
||||
virtual int remove(uint64_t inode) = 0;
|
||||
|
||||
virtual void resize() = 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 size() = 0;
|
||||
};
|
||||
|
||||
FileSystem *createFileSystem(void *buff);
|
||||
@@ -95,6 +99,8 @@ class FileSystemTemplate: public FileSystem {
|
||||
|
||||
int read(uint64_t inode, void *buffer, size_t size) override;
|
||||
|
||||
void resize() override;
|
||||
|
||||
int remove(uint64_t inode) override;
|
||||
|
||||
int write(uint64_t inode, void *buffer, uint64_t size, uint8_t fileType) override;
|
||||
@@ -103,6 +109,8 @@ class FileSystemTemplate: public FileSystem {
|
||||
|
||||
FileStat stat(uint64_t inode) override;
|
||||
|
||||
uint64_t size() override;
|
||||
|
||||
static uint8_t *format(void *buffer, typename FileStore::FsSize_t size, bool useDirectories);
|
||||
};
|
||||
|
||||
@@ -199,6 +207,16 @@ int FileSystemTemplate<FileStore, FS_TYPE>::write(uint64_t inode, void *buffer,
|
||||
#pragma warning(default:4244)
|
||||
#endif
|
||||
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
void FileSystemTemplate<FileStore, FS_TYPE>::resize() {
|
||||
return store->resize();
|
||||
}
|
||||
|
||||
template<typename FileStore, FsType FS_TYPE>
|
||||
uint64_t FileSystemTemplate<FileStore, FS_TYPE>::size() {
|
||||
return store->size();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
+51
-3
@@ -20,13 +20,14 @@
|
||||
using namespace ox::fs;
|
||||
using namespace std;
|
||||
|
||||
const static auto oxfstoolVersion = "1.0.0";
|
||||
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 rm <FS file> <inode>\n"
|
||||
"\toxfs version\n"
|
||||
"\toxfs write <FS file> <inode> <insertion file>";
|
||||
"\toxfs version\n";
|
||||
|
||||
char *loadFileBuff(const char *path, ::size_t *sizeOut = nullptr) {
|
||||
auto file = fopen(path, "rb");
|
||||
@@ -129,6 +130,8 @@ int format(int argc, char **args) {
|
||||
if (err == 0) {
|
||||
fprintf(stderr, "Created file system %s\n", path);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Insufficient arguments\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -163,6 +166,8 @@ int read(int argc, char **args) {
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file: %s\n", fsPath);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Insufficient arguments\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -223,6 +228,47 @@ int write(int argc, char **args) {
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file system\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Insufficient arguments\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int resize(int argc, char **args) {
|
||||
auto err = 1;
|
||||
if (argc >= 2) {
|
||||
auto fsPath = args[2];
|
||||
size_t fsSize;
|
||||
|
||||
auto fsBuff = loadFileBuff(fsPath, &fsSize);
|
||||
if (fsBuff) {
|
||||
auto fs = createFileSystem(fsBuff);
|
||||
|
||||
if (fs) {
|
||||
fs->resize();
|
||||
} else {
|
||||
fprintf(stderr, "Invalid file system.\n");
|
||||
}
|
||||
|
||||
// write back to file
|
||||
auto fsFile = fopen(fsPath, "wb");
|
||||
if (fsFile) {
|
||||
err = fwrite(fsBuff, fs->size(), 1, fsFile) != 1;
|
||||
err |= fclose(fsFile);
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system file.\n");
|
||||
}
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
|
||||
delete fs;
|
||||
free(fsBuff);
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file: %s\n", fsPath);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Insufficient arguments\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -280,6 +326,8 @@ int main(int argc, char **args) {
|
||||
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);
|
||||
} else if (ox_strcmp(cmd, "rm") == 0) {
|
||||
err = remove(argc, args);
|
||||
} else if (ox_strcmp(cmd, "help") == 0) {
|
||||
|
||||
Reference in New Issue
Block a user