Fix to allow overwriting existing inodes and add remove to oxfstool
This commit is contained in:
+122
-32
@@ -46,7 +46,6 @@ class FileStore {
|
||||
|
||||
ox::std::uint32_t m_fsType;
|
||||
FsSize_t m_size;
|
||||
FsSize_t m_firstInode;
|
||||
FsSize_t m_rootInode;
|
||||
|
||||
public:
|
||||
@@ -104,6 +103,15 @@ class FileStore {
|
||||
*/
|
||||
Inode *getInode(Inode *root, InodeId_t id);
|
||||
|
||||
/**
|
||||
* Gets the inode at the given id.
|
||||
* @param root the root node to start comparing on
|
||||
* @param id id of the "file"
|
||||
* @param pathLen number of characters in pathLen
|
||||
* @return the requested Inode, if available
|
||||
*/
|
||||
Inode *getInodeParent(Inode *root, InodeId_t id);
|
||||
|
||||
/**
|
||||
* Removes the inode of the given ID.
|
||||
* @param id the id of the file
|
||||
@@ -116,6 +124,12 @@ class FileStore {
|
||||
*/
|
||||
void unlink(Inode *node);
|
||||
|
||||
/**
|
||||
* Gets the address of the next available inode, assuming there is a next
|
||||
* available inode.
|
||||
*/
|
||||
FsSize_t nextInodeAddr();
|
||||
|
||||
/**
|
||||
* Gets an address for a new Inode.
|
||||
* @param size the size of the Inode
|
||||
@@ -123,9 +137,9 @@ class FileStore {
|
||||
void *alloc(FsSize_t size);
|
||||
|
||||
/**
|
||||
* Compresses all of the inode into a contiguous space, starting at m_firstInode.
|
||||
* Compresses all of the inode into a contiguous space, starting at the first inode.
|
||||
*/
|
||||
void compress();
|
||||
void compress(FsSize_t firstInode);
|
||||
|
||||
/**
|
||||
* Inserts the given insertValue into the tree of the given root.
|
||||
@@ -140,10 +154,15 @@ class FileStore {
|
||||
*/
|
||||
FsSize_t iterator();
|
||||
|
||||
Inode *firstInode();
|
||||
FsSize_t firstInode();
|
||||
|
||||
Inode *lastInode();
|
||||
|
||||
/**
|
||||
* Updates the address of the inode in the tree.
|
||||
*/
|
||||
void updateInodeAddress(InodeId_t id, FsSize_t addr);
|
||||
|
||||
ox::std::uint8_t *begin() {
|
||||
return (ox::std::uint8_t*) this;
|
||||
}
|
||||
@@ -203,9 +222,10 @@ int FileStore<FsSize_t>::write(InodeId_t id, void *data, FsSize_t dataLen) {
|
||||
const FsSize_t size = sizeof(Inode) + dataLen;
|
||||
auto inode = (Inode*) alloc(size);
|
||||
if (inode) {
|
||||
auto root = ptr<Inode*>(m_rootInode);
|
||||
remove(id);
|
||||
inode->m_id = id;
|
||||
inode->setData(data, dataLen);
|
||||
auto root = ptr<Inode*>(m_rootInode);
|
||||
if (insert(root, inode) || root == inode) {
|
||||
retval = 0;
|
||||
}
|
||||
@@ -228,7 +248,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
|
||||
if (node->m_id != id) {
|
||||
err = remove(node, id);
|
||||
} else {
|
||||
root->left = node->left;
|
||||
root->left = 0;
|
||||
if (node->right) {
|
||||
insert(root, ptr<Inode*>(node->right));
|
||||
}
|
||||
@@ -236,6 +256,9 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
|
||||
insert(root, ptr<Inode*>(node->left));
|
||||
}
|
||||
unlink(node);
|
||||
node->m_id = 0;
|
||||
node->left = 0;
|
||||
node->right = 0;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
@@ -245,7 +268,7 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
|
||||
if (node->m_id != id) {
|
||||
err = remove(node, id);
|
||||
} else {
|
||||
root->right = node->right;
|
||||
root->right = 0;
|
||||
if (node->right) {
|
||||
insert(root, ptr<Inode*>(node->right));
|
||||
}
|
||||
@@ -253,15 +276,21 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
|
||||
insert(root, ptr<Inode*>(node->left));
|
||||
}
|
||||
unlink(node);
|
||||
node->m_id = 0;
|
||||
node->left = 0;
|
||||
node->right = 0;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (ptr<Inode*>(m_rootInode)->m_id == id) {
|
||||
m_rootInode = root->right;
|
||||
if (root->left) {
|
||||
insert(ptr<Inode*>(m_rootInode), ptr<Inode*>(root->left));
|
||||
}
|
||||
unlink(root);
|
||||
root->m_id = 0;
|
||||
root->left = 0;
|
||||
root->right = 0;
|
||||
err = 0;
|
||||
}
|
||||
|
||||
@@ -269,11 +298,27 @@ int FileStore<FsSize_t>::remove(Inode *root, InodeId_t id) {
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void FileStore<FsSize_t>::unlink(Inode *node) {
|
||||
auto next = ptr<Inode*>(node->next);
|
||||
auto prev = ptr<Inode*>(node->prev);
|
||||
void FileStore<FsSize_t>::unlink(Inode *inode) {
|
||||
auto next = ptr<Inode*>(inode->next);
|
||||
auto prev = ptr<Inode*>(inode->prev);
|
||||
prev->next = ptr(next);
|
||||
next->prev = ptr(prev);
|
||||
|
||||
ox::std::memset(inode, 0, inode->size());
|
||||
inode->prev = firstInode();
|
||||
inode->next = firstInode();
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void FileStore<FsSize_t>::updateInodeAddress(InodeId_t id, FsSize_t addr) {
|
||||
auto parent = getInodeParent(ptr<Inode*>(m_rootInode), id);
|
||||
if (parent) {
|
||||
if (parent->left && ptr<Inode*>(parent->left)->m_id == id) {
|
||||
parent->left = addr;
|
||||
} else if (parent->right && ptr<Inode*>(parent->right)->m_id == id) {
|
||||
parent->right = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
@@ -322,36 +367,79 @@ typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInode(Inode *root,
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::getInodeParent(Inode *root, InodeId_t id) {
|
||||
Inode *retval = nullptr;
|
||||
|
||||
if (root->m_id > id) {
|
||||
if (root->left) {
|
||||
if (ptr<Inode*>(root->left)->m_id == id) {
|
||||
retval = root;
|
||||
} else {
|
||||
retval = getInode(ptr<Inode*>(root->left), id);
|
||||
}
|
||||
}
|
||||
} else if (root->m_id < id) {
|
||||
if (root->right) {
|
||||
if (ptr<Inode*>(root->right)->m_id == id) {
|
||||
retval = root;
|
||||
} else {
|
||||
retval = getInode(ptr<Inode*>(root->right), id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
FsSize_t FileStore<FsSize_t>::nextInodeAddr() {
|
||||
FsSize_t next = ptr(lastInode()) + lastInode()->size();
|
||||
return next;
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void *FileStore<FsSize_t>::alloc(FsSize_t size) {
|
||||
if ((lastInode()->next + size) > (ox::std::uint64_t) end()) {
|
||||
compress();
|
||||
if ((lastInode()->next + size) > (ox::std::uint64_t) end()) {
|
||||
FsSize_t next = nextInodeAddr();
|
||||
if ((next + size) > (ox::std::uint64_t) end()) {
|
||||
compress(firstInode());
|
||||
next = nextInodeAddr();
|
||||
if ((next + size) > (ox::std::uint64_t) end()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const auto retval = lastInode()->next;
|
||||
const auto retval = next;
|
||||
const auto inode = ptr<Inode*>(retval);
|
||||
ox::std::memset(inode, 0, size);
|
||||
inode->prev = ptr<Inode*>(firstInode())->prev;
|
||||
inode->next = retval + size;
|
||||
ptr<Inode*>(m_firstInode)->prev = retval;
|
||||
ptr<Inode*>(firstInode())->prev = retval;
|
||||
return inode;
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
void FileStore<FsSize_t>::compress() {
|
||||
auto current = ptr<Inode*>(m_firstInode);
|
||||
while (current->next) {
|
||||
auto prevEnd = current + current->size();
|
||||
auto prev = ptr(current);
|
||||
current->next = ptr(current) + current->size();
|
||||
current = ptr<Inode*>(current->next);
|
||||
current->prev = prev;
|
||||
if (prevEnd != current) {
|
||||
ox::std::memcpy(prevEnd, current, current->size());
|
||||
current = prevEnd;
|
||||
void FileStore<FsSize_t>::compress(FsSize_t start) {
|
||||
auto dest = ptr<Inode*>(firstInode());
|
||||
auto current = ptr<Inode*>(start);
|
||||
while (current->next > ptr(begin()) && current->next < ptr(end())) {
|
||||
ox::std::memcpy(dest, current, current->size());
|
||||
if (dest->next != firstInode()) {
|
||||
dest->next = ptr(dest) + dest->size();
|
||||
}
|
||||
ptr<Inode*>(dest->next)->prev = ptr(dest);
|
||||
current = ptr<Inode*>(dest->next);
|
||||
dest = ptr<Inode*>(ptr(dest) + dest->size());
|
||||
updateInodeAddress(dest->m_id, ptr(dest));
|
||||
//auto prevEnd = current + current->size();
|
||||
//auto prev = ptr(current);
|
||||
//current->next = ptr(current) + current->size();
|
||||
//current = ptr<Inode*>(current->next);
|
||||
//current->prev = prev;
|
||||
//if (prevEnd != current) {
|
||||
// ox::std::memcpy(prevEnd, current, current->size());
|
||||
// current = prevEnd;
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,6 +461,9 @@ bool FileStore<FsSize_t>::insert(Inode *root, Inode *insertValue) {
|
||||
root->right = ptr(insertValue);
|
||||
retval = true;
|
||||
}
|
||||
} else if (m_rootInode == 0) {
|
||||
m_rootInode = ptr(insertValue);
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -389,13 +480,13 @@ FsSize_t FileStore<FsSize_t>::ptr(void *ptr) {
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::firstInode() {
|
||||
return ptr<Inode*>(sizeof(FileStore<FsSize_t>));
|
||||
FsSize_t FileStore<FsSize_t>::firstInode() {
|
||||
return sizeof(FileStore<FsSize_t>);
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
typename FileStore<FsSize_t>::Inode *FileStore<FsSize_t>::lastInode() {
|
||||
return ptr<Inode*>(ptr<Inode*>(m_firstInode)->prev);
|
||||
return ptr<Inode*>(ptr<Inode*>(firstInode())->prev);
|
||||
}
|
||||
|
||||
template<typename FsSize_t>
|
||||
@@ -411,8 +502,7 @@ ox::std::uint8_t *FileStore<FsSize_t>::format(ox::std::uint8_t *buffer, FsSize_t
|
||||
fs->m_fsType = fsType;
|
||||
fs->m_size = size;
|
||||
fs->m_rootInode = sizeof(FileStore<FsSize_t>);
|
||||
fs->m_firstInode = sizeof(FileStore<FsSize_t>);
|
||||
fs->firstInode()->prev = fs->m_firstInode;
|
||||
((Inode*) (fs + 1))->prev = fs->firstInode();
|
||||
fs->lastInode()->next = sizeof(FileStore<FsSize_t>);
|
||||
|
||||
return (ox::std::uint8_t*) buffer;
|
||||
|
||||
@@ -34,6 +34,8 @@ class FileSystem {
|
||||
|
||||
virtual ox::std::uint8_t *read(ox::std::uint64_t inode, ox::std::uint64_t *size) = 0;
|
||||
|
||||
virtual int remove(ox::std::uint64_t inode) = 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;
|
||||
@@ -85,6 +87,8 @@ class FileSystemTemplate: public FileSystem {
|
||||
|
||||
int read(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override;
|
||||
|
||||
int remove(ox::std::uint64_t inode);
|
||||
|
||||
int write(ox::std::uint64_t inode, void *buffer, ox::std::uint64_t size) override;
|
||||
|
||||
FileStat stat(const char *path);
|
||||
@@ -146,6 +150,11 @@ ox::std::uint8_t *FileSystemTemplate<FileStore>::read(ox::std::uint64_t inode, o
|
||||
return buff;
|
||||
}
|
||||
|
||||
template<typename FileStore>
|
||||
int FileSystemTemplate<FileStore>::remove(ox::std::uint64_t inode) {
|
||||
return store->remove(inode);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
+62
-11
@@ -94,15 +94,19 @@ int read(int argc, char **args) {
|
||||
if (fsBuff) {
|
||||
auto fs = createFileSystem(fsBuff);
|
||||
|
||||
auto output = fs->read(inode, &fileSize);
|
||||
if (fs) {
|
||||
auto output = fs->read(inode, &fileSize);
|
||||
|
||||
if (output) {
|
||||
fwrite(output, fileSize, 1, stdout);
|
||||
err = 0;
|
||||
if (output) {
|
||||
fwrite(output, fileSize, 1, stdout);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
delete fs;
|
||||
free(fsBuff);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid file system type: %d.\n", *(ox::std::uint32_t*) fsBuff);
|
||||
}
|
||||
|
||||
delete fs;
|
||||
delete fsBuff;
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file: %s\n", fsPath);
|
||||
}
|
||||
@@ -133,13 +137,15 @@ int write(int argc, char **args) {
|
||||
auto fs = createFileSystem(fsBuff);
|
||||
if (fs) {
|
||||
err |= fs->write(inode, srcBuff, srcSize);
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid file system.\n");
|
||||
fprintf(stderr, "Invalid file system type: %d.\n", *(ox::std::uint32_t*) fsBuff);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
} else {
|
||||
if (!err) {
|
||||
fsFile = fopen(fsPath, "wb");
|
||||
|
||||
if (fsFile) {
|
||||
@@ -166,6 +172,49 @@ int write(int argc, char **args) {
|
||||
return err;
|
||||
}
|
||||
|
||||
int remove(int argc, char **args) {
|
||||
auto err = 1;
|
||||
if (argc >= 4) {
|
||||
auto fsPath = args[2];
|
||||
auto inode = ox::std::atoi(args[3]);
|
||||
::size_t fsSize;
|
||||
|
||||
auto fsBuff = loadFileBuff(fsPath, &fsSize);
|
||||
if (fsBuff) {
|
||||
auto fs = createFileSystem(fsBuff);
|
||||
|
||||
if (fs) {
|
||||
err = fs->remove(inode);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid file system.\n");
|
||||
}
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "Could not write to file system.\n");
|
||||
} else {
|
||||
auto 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;
|
||||
}
|
||||
}
|
||||
|
||||
delete fs;
|
||||
free(fsBuff);
|
||||
} else {
|
||||
fprintf(stderr, "Could not open file: %s\n", fsPath);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Insufficient arguments\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int main(int argc, char **args) {
|
||||
auto err = 0;
|
||||
if (argc > 1) {
|
||||
@@ -176,6 +225,8 @@ int main(int argc, char **args) {
|
||||
err = read(argc, args);
|
||||
} else if (::strcmp(cmd, "write") == 0) {
|
||||
err = write(argc, args);
|
||||
} else if (::strcmp(cmd, "rm") == 0) {
|
||||
err = remove(argc, args);
|
||||
} else if (::strcmp(cmd, "help") == 0) {
|
||||
printf("%s\n", usage);
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ox/std/std.hpp>
|
||||
#include <ox/fs/filestore.hpp>
|
||||
|
||||
@@ -23,27 +24,32 @@ int test() {
|
||||
if (fs->write(1, (void*) "Hello", 6) ||
|
||||
fs->read(1, (char*) out, &outSize) ||
|
||||
strcmp("Hello", out)) {
|
||||
printf("Failure 1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fs->write(2, (void*) "World", 6) ||
|
||||
fs->read(2, (char*) out, &outSize) ||
|
||||
strcmp("World", out)) {
|
||||
printf("Failure 2\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// make sure first value was not overwritten
|
||||
if (fs->read(1, (char*) out, &outSize) ||
|
||||
strcmp("Hello", out)) {
|
||||
printf("Failure 3\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (fs->remove(1)) {
|
||||
printf("Failure 4\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
// make sure inode is not found
|
||||
if (fs->read(1, (char*) out, &outSize) == 0) {
|
||||
printf("Failure 5\n");
|
||||
return 5;
|
||||
}
|
||||
|
||||
@@ -51,6 +57,7 @@ int test() {
|
||||
if (fs->write(2, (void*) "World", 6) ||
|
||||
fs->read(2, (char*) out, &outSize) ||
|
||||
strcmp("World", out)) {
|
||||
printf("Failure 6\n");
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user