diff --git a/.liccor b/.liccor deleted file mode 100644 index 7fed3f1e..00000000 --- a/.liccor +++ /dev/null @@ -1,5 +0,0 @@ -Copyright 2015 - 2017 gtalent2@gmail.com - -This Source Code Form is subject to the terms of the Mozilla Public -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/. diff --git a/.liccor.yml b/.liccor.yml new file mode 100644 index 00000000..55025146 --- /dev/null +++ b/.liccor.yml @@ -0,0 +1,9 @@ +--- +source: +- src +copyright_notice: |- + Copyright 2015 - 2017 gtalent2@gmail.com + + This Source Code Form is subject to the terms of the Mozilla Public + 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/. diff --git a/scripts/check b/scripts/check deleted file mode 100755 index 74346523..00000000 --- a/scripts/check +++ /dev/null @@ -1 +0,0 @@ -clang-check `find . | grep "\.cpp" | grep -v CMakeFiles | grep -v editormodels\.cpp` diff --git a/scripts/newcpp b/scripts/newcpp deleted file mode 100755 index c9ef12ab..00000000 --- a/scripts/newcpp +++ /dev/null @@ -1,16 +0,0 @@ -#! /usr/bin/env python - -import sys - -if len(sys.argv) < 3: - sys.exit(1) - -pkg = sys.argv[1] -name = sys.argv[2] -ifdef = "WOMBAT_%s_%s_HPP" % (pkg.upper(), name.upper()) -namespace = "namespace wombat {\nnamespace %s {\n\n}\n}" % pkg -hpp = "#ifndef %s\n#define %s\n\n%s\n\n#endif" % (ifdef, ifdef, namespace) -cpp = "#include \"%s.hpp\"\n\n%s" % (name, namespace) - -open("src/%s/%s.hpp" % (pkg, name), "w").write(hpp) -open("src/%s/%s.cpp" % (pkg, name), "w").write(cpp) diff --git a/src/ox/fs/filestore.hpp b/src/ox/fs/filestore.hpp index 20b261a5..cedcf99c 100644 --- a/src/ox/fs/filestore.hpp +++ b/src/ox/fs/filestore.hpp @@ -17,7 +17,7 @@ struct __attribute__((packed)) FileStoreHeader { public: typedef InodeId InodeId_t; typedef FsT FsSize_t; - const static auto VERSION = 5; + const static auto VERSION = 6; private: uint16_t m_version; @@ -103,6 +103,7 @@ class FileStore { struct StatInfo { InodeId_t inodeId; + InodeId_t links; typename Header::FsSize_t size; uint8_t fileType; }; @@ -116,6 +117,7 @@ class FileStore { typename Header::FsSize_t m_dataLen; InodeId_t m_id; + InodeId_t m_links; uint8_t m_fileType; typename Header::FsSize_t m_left; typename Header::FsSize_t m_right; @@ -135,6 +137,9 @@ class FileStore { void setId(InodeId_t); InodeId_t getId(); + void setLinks(InodeId_t); + InodeId_t getLinks(); + void setFileType(uint8_t); uint8_t getFileType(); @@ -178,6 +183,18 @@ class FileStore { */ int remove(InodeId_t id); + /** + * Increments the links of the inode of the given ID. + * @param id the id of the inode + */ + int incLinks(InodeId_t id); + + /** + * Decrements the links of the inode of the given ID. + * @param id the id of the inode + */ + int decLinks(InodeId_t id); + /** * Removes all inodes of the type. * @param fileType the type of file to remove @@ -251,6 +268,8 @@ class FileStore { */ typename Header::FsSize_t available(); + void walk(int(*cb)(const char*, uint64_t start, uint64_t end)); + uint16_t fsType(); uint16_t version(); @@ -268,7 +287,7 @@ class FileStore { Inode *getInode(Inode *root, InodeId_t id); /** - * Gets the inode at the given id. + * Gets the parent 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 @@ -405,6 +424,16 @@ typename Header::InodeId_t FileStore
::Inode::getId() { return bigEndianAdapt(m_id); } +template +void FileStore
::Inode::setLinks(InodeId_t links) { + this->m_links = bigEndianAdapt(links); +} + +template +typename Header::InodeId_t FileStore
::Inode::getLinks() { + return bigEndianAdapt(m_links); +} + template void FileStore
::Inode::setFileType(uint8_t fileType) { this->m_fileType = bigEndianAdapt(fileType); @@ -441,7 +470,6 @@ void FileStore
::Inode::setData(void *data, typename Header::FsSize_t siz setDataLen(size); } - template uint8_t *FileStore
::Inode::getData() { return (uint8_t*) (this + 1); @@ -511,6 +539,36 @@ int FileStore
::remove(InodeId_t id) { return remove(ptr(m_header.getRootInode()), id); } +/** + * Increments the links of the inode of the given ID. + * @param id the id of the inode + */ +template +int FileStore
::incLinks(InodeId_t id) { + auto inode = getInode(ptr(m_header.getRootInode()), id); + if (inode) { + inode->setLinks(inode->getLinks() + 1); + return 0; + } else { + return 1; + } +} + +/** + * Decrements the links of the inode of the given ID. + * @param id the id of the inode + */ +template +int FileStore
::decLinks(InodeId_t id) { + auto inode = getInode(ptr(m_header.getRootInode()), id); + if (inode) { + inode->setLinks(inode->getLinks() - 1); + return 0; + } else { + return 1; + } +} + template int FileStore
::remove(Inode *root, InodeId_t id) { auto err = 1; @@ -664,6 +722,7 @@ typename FileStore
::StatInfo FileStore
::stat(InodeId_t id) { if (inode) { stat.size = inode->getDataLen(); stat.fileType = inode->getFileType(); + stat.links = inode->getLinks(); stat.inodeId = id; } else { stat.inodeId = 0; @@ -830,6 +889,17 @@ uint16_t FileStore
::version() { return m_header.getVersion(); }; +template +void FileStore
::walk(int(*cb)(const char*, uint64_t start, uint64_t end)) { + auto err = cb("Header", 0, sizeof(Header)); + auto inode = ptr(firstInode()); + while (!err && inode != (Inode*) begin()) { + inode = ptr(inode->getNext()); + auto start = ptr(inode); + err = cb("Inode", start, start + inode->size()); + } +} + template uint8_t *FileStore
::format(uint8_t *buffer, typename Header::FsSize_t size, uint16_t fsType) { ox_memset(buffer, 0, size); diff --git a/src/ox/fs/filesystem.cpp b/src/ox/fs/filesystem.cpp index ceeaa5fb..b6f9b94f 100644 --- a/src/ox/fs/filesystem.cpp +++ b/src/ox/fs/filesystem.cpp @@ -16,7 +16,7 @@ FileSystem *createFileSystem(uint8_t *buff, size_t buffSize, bool ownsBuff) { FileSystem *fs = nullptr; switch (version) { - case 5: + case 6: switch (type) { case ox::OxFS_16: fs = new FileSystem16(buff, ownsBuff); diff --git a/src/ox/fs/filesystem.hpp b/src/ox/fs/filesystem.hpp index 0854456e..3fc5cee6 100644 --- a/src/ox/fs/filesystem.hpp +++ b/src/ox/fs/filesystem.hpp @@ -26,6 +26,7 @@ enum FileType { struct FileStat { uint64_t inode; + uint64_t links; uint64_t size; uint8_t fileType; }; @@ -42,6 +43,11 @@ struct DirectoryListing { } }; +template +bool operator<(const DirectoryListing &a, const DirectoryListing &b) { + return a.name < b.name; +} + template struct __attribute__((packed)) DirectoryEntry { InodeId_t inode; @@ -81,7 +87,7 @@ struct __attribute__((packed)) Directory { return size ? (DirectoryEntry*) (this + 1) : nullptr; } - uint64_t getFileInode(const char *name, uint64_t buffSize); + uint64_t getFileInode(const char *name); int getChildrenInodes(InodeId_t *inodes, size_t inodesLen); @@ -94,7 +100,7 @@ struct __attribute__((packed)) Directory { }; template -uint64_t Directory::getFileInode(const char *name, uint64_t buffSize) { +uint64_t Directory::getFileInode(const char *name) { uint64_t inode = 0; auto current = files(); if (current) { @@ -120,7 +126,9 @@ int Directory::getChildrenInodes(InodeId_t *inodes, size_t auto current = files(); if (current) { for (uint64_t i = 0; i < this->children; i++) { - inodes[i] = current->inode; + if (ox_strcmp(current->getName(), ".") and ox_strcmp(current->getName(), "..")) { + inodes[i] = current->inode; + } current = (DirectoryEntry*) (((uint8_t*) current) + current->size()); } return 0; @@ -201,6 +209,13 @@ class FileSystem { virtual int mkdir(const char *path) = 0; + /** + * Moves an entry from one directory to another. + * @param src the path to the file + * @param dest the path of the destination directory + */ + virtual int move(const char *src, const char *dest) = 0; + template int ls(const char *path, List *list); @@ -234,17 +249,22 @@ class FileSystem { virtual uint8_t *buff() = 0; + virtual void walk(int(*cb)(const char*, uint64_t, uint64_t)) = 0; + protected: virtual int readDirectory(const char *path, Directory *dirOut) = 0; }; template int FileSystem::ls(const char *path, List *list) { + int err = 0; auto s = stat(path); - uint8_t dirBuff[s.size * 4]; - auto dir = (Directory*) dirBuff; - auto err = readDirectory(path, dir); - err |= dir->ls(list); + if (s.fileType == FileType_Directory) { + uint8_t dirBuff[s.size * 4]; + auto dir = (Directory*) dirBuff; + err = readDirectory(path, dir); + err |= dir->ls(list); + } return err; } @@ -314,18 +334,15 @@ class FileSystemTemplate: public FileSystem { uint8_t *buff() override; - /** - * Moves an entry from one directory to another. - * @param src the path to the file - * @param dest the path of the destination directory - */ - int move(const char *src, const char *dest); + int move(const char *src, const char *dest) override; /** * Removes an entry from a directory. This does not delete the referred to file. */ int rmDirectoryEntry(const char *path); + void walk(int(*cb)(const char*, uint64_t, uint64_t)) override; + static uint8_t *format(uint8_t *buffer, typename FileStore::FsSize_t size, bool useDirectories); protected: @@ -368,8 +385,36 @@ int FileSystemTemplate::stripDirectories() { template int FileSystemTemplate::mkdir(const char *path) { - Directory dir; - return write(path, &dir, sizeof(dir), FileType::FileType_Directory); + if (!stat(path).inode) { + Directory dir; + auto err = write(path, &dir, sizeof(dir), FileType::FileType_Directory); + if (err) { + return err; + } + + // add . entry for self + auto inode = findInodeOf(path); + err = insertDirectoryEntry(path, ".", inode); + if (err) { + remove(inode); + return err; + } + + // add .. entry for parent + size_t pathLen = ox_strlen(path); + char dirPath[pathLen]; + PathIterator pathReader(path, pathLen); + err |= pathReader.dirPath(dirPath, pathLen); + err = insertDirectoryEntry(path, "..", findInodeOf(dirPath)); + if (err) { + remove(inode); + return err; + } + + return err; + } else { + return 1; + } } template @@ -392,6 +437,7 @@ FileStat FileSystemTemplate::stat(uint64_t inode) { auto s = m_store->stat(inode); stat.size = s.size; stat.inode = s.inodeId; + stat.links = s.links; stat.fileType = s.fileType; return stat; } @@ -476,7 +522,7 @@ template int FileSystemTemplate::remove(const char *path, bool recursive) { auto inode = findInodeOf(path); if (inode) { - return remove(inode, recursive) | rmDirectoryEntry(path); + return rmDirectoryEntry(path) | remove(inode, recursive); } else { return 1; } @@ -503,10 +549,13 @@ int FileSystemTemplate::remove(uint64_t inode, bool recursiv } typename FileStore::InodeId_t inodes[dir->children]; + ox_memset(inodes, 0, sizeof(typename FileStore::InodeId_t) * dir->children); dir->getChildrenInodes(inodes, dir->children); for (auto i : inodes) { - err |= remove(i, true); + if (i) { + err |= remove(i, true); + } } if (!err) { @@ -542,7 +591,8 @@ int FileSystemTemplate::write(const char *path, void *buffer // find an inode value for the given path if (!inode) { inode = generateInodeId(); - err = insertDirectoryEntry(dirPath, fileName, inode); + err |= write(inode, buffer, 0, fileType); // ensure file exists before indexing it + err |= insertDirectoryEntry(dirPath, fileName, inode); } if (!err) { @@ -587,7 +637,7 @@ uint64_t FileSystemTemplate::findInodeOf(const char *path) { auto dir = (Directory*) dirBuffer; if (read(inode, dirBuffer, dirStat.size) == 0) { if (dirStat.fileType == FileType::FileType_Directory && it.next(fileName, pathLen) == 0) { - inode = dir->getFileInode(fileName, dirStat.size); + inode = dir->getFileInode(fileName); } else { inode = 0; // null out inode and break break; @@ -693,7 +743,9 @@ int FileSystemTemplate::insertDirectoryEntry(const char *dir auto entry = (DirectoryEntry*) &dirBuff[s.size]; entry->inode = inode; entry->setName(fileName); - return write(s.inode, dirBuff, dirBuffSize, FileType_Directory); + err = write(s.inode, dirBuff, dirBuffSize, FileType_Directory); + err |= m_store->incLinks(inode); + return err; } else { return 1; } @@ -770,7 +822,9 @@ int FileSystemTemplate::rmDirectoryEntry(const char *path) { } auto dir = (Directory*) dirBuff; - err = dir->rmFile(fileName); + auto inode = dir->getFileInode(fileName); + err |= dir->rmFile(fileName); + err |= m_store->decLinks(inode); if (err) { return err; @@ -809,6 +863,11 @@ void FileSystemTemplate::expand(uint64_t newSize) { } } +template +void FileSystemTemplate::walk(int(*cb)(const char*, uint64_t, uint64_t)) { + m_store->walk(cb); +} + typedef FileSystemTemplate FileSystem16; typedef FileSystemTemplate FileSystem32; typedef FileSystemTemplate FileSystem64; diff --git a/src/ox/fs/oxfstool.cpp b/src/ox/fs/oxfstool.cpp index ee241245..4d52e5b3 100644 --- a/src/ox/fs/oxfstool.cpp +++ b/src/ox/fs/oxfstool.cpp @@ -20,7 +20,7 @@ using namespace ox; using namespace std; -const static auto oxfstoolVersion = "1.3.0"; +const static auto oxfstoolVersion = "1.4.0"; const static auto usage = "usage:\n" "\toxfs format [16,32,64] \n" "\toxfs read \n" @@ -28,6 +28,7 @@ const static auto usage = "usage:\n" "\toxfs write-expand \n" "\toxfs rm \n" "\toxfs compact \n" +"\toxfs walk \n" "\toxfs version\n"; uint8_t *loadFileBuff(FILE *file, ::size_t *sizeOut = nullptr) { @@ -148,7 +149,7 @@ int read(int argc, char **args) { size_t fileSize; auto fsBuff = loadFileBuff(fsPath, &fsSize); - + if (fsBuff) { auto fs = createFileSystem(fsBuff, fsSize); @@ -333,6 +334,31 @@ int remove(int argc, char **args) { return err; } +int walk(int argc, char **args) { + int err = 0; + size_t fsSize; + auto fsPath = args[2]; + auto fsBuff = loadFileBuff(fsPath, &fsSize); + if (fsBuff) { + auto fs = createFileSystem(fsBuff, fsSize); + if (fs) { + fs->walk([](const char *type, uint64_t start, uint64_t end) { + cout << "narf\n"; + cout << type << ", start: " << start << ", end: " << end << endl; + return 0; + }); + delete fs; + } else { + cerr << "Invalid file system.\n"; + err = 1; + } + delete []fsBuff; + } else { + err = 2; + } + return err; +} + int main(int argc, char **args) { auto err = 0; if (argc > 1) { @@ -349,6 +375,8 @@ int main(int argc, char **args) { err = compact(argc, args); } else if (ox_strcmp(cmd, "rm") == 0) { err = remove(argc, args); + } else if (ox_strcmp(cmd, "walk") == 0) { + err = walk(argc, args); } else if (ox_strcmp(cmd, "help") == 0) { printf("%s\n", usage); } else if (ox_strcmp(cmd, "version") == 0) { diff --git a/src/ox/fs/test/tests.cpp b/src/ox/fs/test/tests.cpp index d29d3b32..47e5a4a2 100644 --- a/src/ox/fs/test/tests.cpp +++ b/src/ox/fs/test/tests.cpp @@ -314,9 +314,11 @@ map tests = { fs->ls("/usr/share/", &files); - retval |= !(files[0].name == "a.txt"); - retval |= !(files[1].name == "b.txt"); - retval |= !(files[2].name == "c.txt"); + retval |= !(files[0].name == "."); + retval |= !(files[1].name == ".."); + retval |= !(files[2].name == "a.txt"); + retval |= !(files[3].name == "b.txt"); + retval |= !(files[4].name == "c.txt"); delete fs; delete []buff;