diff --git a/CMakeLists.txt b/CMakeLists.txt index 2949565..4ad7929 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,15 @@ cmake_minimum_required(VERSION 3.22) -add_compile_options(-Ofast) -add_link_options(-Ofast) +#add_compile_options(-Ofast) +#add_link_options(-Ofast) # add_compile_options(-Ofast -flto) # add_link_options(-Ofast -flto) -#add_compile_options(-Wall -O0 -Wextra -pedantic -Wshadow -Wformat=2 -Wfloat-equal -D_GLIBCXX_DEBUG -Wconversion -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g -rdynamic) -#add_compile_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover) -#add_link_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover) -#add_link_options(-rdynamic) +add_compile_options(-Wall -O0 -Wextra -pedantic -Wshadow -Wformat=2 -Wfloat-equal -D_GLIBCXX_DEBUG -Wconversion -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g -rdynamic) +add_compile_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover) +add_link_options(-fsanitize=address -fsanitize=undefined -fno-sanitize-recover) +add_link_options(-rdynamic) project(backup) diff --git a/Doxyfile b/Doxyfile index 2194c07..50ca924 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2421,7 +2421,7 @@ HIDE_UNDOC_RELATIONS = YES # set to NO # The default value is: NO. -HAVE_DOT = NO +HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 397898b..75710cc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,6 +10,7 @@ add_subdirectory(crypto) add_subdirectory(filters) add_subdirectory(repo) add_subdirectory(utils) +add_subdirectory(fuse) add_executable(backup main.cpp) target_link_libraries(backup PRIVATE change_detectors chunkers commands crypto filters repo utils) \ No newline at end of file diff --git a/src/commands/CMakeLists.txt b/src/commands/CMakeLists.txt index 975a83e..b33d3ce 100644 --- a/src/commands/CMakeLists.txt +++ b/src/commands/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.22) -add_library(commands srcs/Command.cpp srcs/CommandDiff.cpp srcs/CommandList.cpp srcs/CommandListFiles.cpp srcs/CommandRestore.cpp srcs/CommandRun.cpp srcs/CommandsCommon.cpp srcs/Diff.cpp) +add_library(commands srcs/Command.cpp srcs/CommandDiff.cpp srcs/CommandList.cpp srcs/CommandListFiles.cpp srcs/CommandRestore.cpp srcs/CommandRun.cpp srcs/CommandsCommon.cpp srcs/Diff.cpp srcs/CommandMount.cpp) target_include_directories(commands PUBLIC includes) -target_link_libraries(commands crypto repo chunkers utils change_detectors) +target_link_libraries(commands crypto repo chunkers utils change_detectors fuse) diff --git a/src/commands/includes/CommandMount.h b/src/commands/includes/CommandMount.h new file mode 100644 index 0000000..53ec45d --- /dev/null +++ b/src/commands/includes/CommandMount.h @@ -0,0 +1,17 @@ +// +// Created by Stepan Usatiuk on 07.06.2023. +// + +#ifndef BACKUP_COMMANDMOUNT_H +#define BACKUP_COMMANDMOUNT_H + +#include "Command.h" + +class CommandMount : public Command { +public: + CommandMount(); + void run(Context ctx) override; +}; + + +#endif//BACKUP_COMMANDMOUNT_H diff --git a/src/commands/srcs/CommandMount.cpp b/src/commands/srcs/CommandMount.cpp new file mode 100644 index 0000000..f0b8f37 --- /dev/null +++ b/src/commands/srcs/CommandMount.cpp @@ -0,0 +1,14 @@ +// +// Created by Stepan Usatiuk on 07.06.2023. +// + +#include "../includes/CommandMount.h" +#include "RepoFS.h" + +CommandMount::CommandMount() : Command("mount") { +} + +void CommandMount::run(Context ctx) { + RepoFS rfs(ctx.repo, ctx.repo->getObjects(Object::ObjectType::Archive).begin()->second, "./hi"); + rfs.workerFn(); +} diff --git a/src/fuse/CMakeLists.txt b/src/fuse/CMakeLists.txt new file mode 100644 index 0000000..3809227 --- /dev/null +++ b/src/fuse/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.22) + +find_package(PkgConfig REQUIRED) + +pkg_check_modules(FUSE REQUIRED IMPORTED_TARGET fuse) + +add_library(fuse srcs/RepoFS.cpp) + +target_include_directories(fuse PUBLIC includes) + +target_link_libraries(fuse utils repo PkgConfig::FUSE) diff --git a/src/fuse/includes/RepoFS.h b/src/fuse/includes/RepoFS.h new file mode 100644 index 0000000..8e764aa --- /dev/null +++ b/src/fuse/includes/RepoFS.h @@ -0,0 +1,43 @@ +// +// Created by Stepan Usatiuk on 07.06.2023. +// + +#ifndef BACKUP_REPOFS_H +#define BACKUP_REPOFS_H + +#include + +#include "Repository.h" +#include "objects/Archive.h" +#include "objects/File.h" + +struct DirEntry { + std::unordered_map children; + std::optional file; +}; + +class RepoFS { +public: + RepoFS(Repository *repo, Object::idType archiveId, std::string path); + + RepoFS &operator=(RepoFS rhs) = delete; + RepoFS(const RepoFS &orig) = delete; + + ~RepoFS(); + + void workerFn(); + static inline DirEntry root; + static inline Repository *repo; + +private: + std::atomic stop = false;///< Stop flag + + Archive archive; + std::string path; + + + // std::thread thread;///< Worker thread +}; + + +#endif//BACKUP_REPOFS_H diff --git a/src/fuse/srcs/RepoFS.cpp b/src/fuse/srcs/RepoFS.cpp new file mode 100644 index 0000000..f6163ea --- /dev/null +++ b/src/fuse/srcs/RepoFS.cpp @@ -0,0 +1,153 @@ +// +// Created by Stepan Usatiuk on 07.06.2023. +// + +#include "../includes/RepoFS.h" + +#define FUSE_USE_VERSION 26 + +#include +#include +#include +#include +#include +#include + +#include "Serialize.h" +#include "objects/Chunk.h" + +RepoFS::RepoFS(Repository *repon, Object::idType archiveId, std::string path) : archive(Serialize::deserialize(repon->getObject(archiveId))), path(std::move(path)) { + RepoFS::repo = repon; + for (auto const &f: archive.files) { + auto file = Serialize::deserialize(repo->getObject(f)); + auto path = std::filesystem::u8path(file.name); + DirEntry *entry = &root; + for (auto const &subp: path) { + entry = &entry->children[subp]; + } + entry->file.emplace(file); + } + // thread = std::thread(&RepoFS::workerFn, this); +} + +RepoFS::~RepoFS() { + // stop = true; + // thread.join(); +} + +static const char *hello_str = "Hello World!\n"; +static const char *hello_path = "/hello"; + +DirEntry *getf(std::string path) { + auto p = std::filesystem::relative(std::filesystem::u8path(path), "/"); + DirEntry *entry = &RepoFS::root; + if (p != ".") + for (auto const &subp: p) { + entry = &entry->children.at(subp); + } + return entry; +} + +static int rfsGetattr(const char *path, struct stat *stbuf) { + int res = 0; + + memset(stbuf, 0, sizeof(struct stat)); + if (strcmp(path, "/") == 0) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + return res; + } + DirEntry *e; + try { + e = getf(path); + if (e->file->fileType == File::Type::Directory) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 1; + } else if (e->file->fileType == File::Type::Normal) { + stbuf->st_mode = S_IFREG | 0444; + stbuf->st_nlink = 1; + stbuf->st_size = e->file->bytes; + } + } catch (...) { return -ENOENT; } + + return res; +} + +static int rfsReaddir(const char *path, void *buf, fuse_fill_dir_t filler, + off_t offset, struct fuse_file_info *fi) { + (void) offset; + (void) fi; + + DirEntry *entry = &RepoFS::root; + if (std::string(path) != "/") + try { + entry = getf(path); + } catch (...) { return -ENOENT; } + + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + + for (auto const &e: entry->children) { + auto pstr = std::filesystem::u8path(e.second.file->name).filename().u8string(); + std::cout << pstr << std::endl; + filler(buf, pstr.c_str(), NULL, 0); + } + + return 0; +} + +static int rfsOpen(const char *path, struct fuse_file_info *fi) { + DirEntry *entry = &RepoFS::root; + if (std::string(path) != "/") + try { + entry = getf(path); + } catch (...) { return -ENOENT; } + + if ((fi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +} + +static int rfsRead(const char *path, char *buf, size_t size, off_t offset, + struct fuse_file_info *fi) { + size_t len; + (void) fi; + DirEntry *entry = &RepoFS::root; + if (std::string(path) != "/") + try { + entry = getf(path); + } catch (...) { return -ENOENT; } + + std::vector data; + + for (auto const &id: entry->file->chunks) { + auto ch = Serialize::deserialize(RepoFS::repo->getObject(id)); + data.insert(data.end(), ch.data.begin(), ch.data.end()); + } + + len = data.size(); + if (offset < len) { + if (offset + size > len) + size = len - offset; + memcpy(buf, data.data() + offset, size); + } else + size = 0; + + return size; +} + +static struct fuse_operations rfsOps = { + .getattr = rfsGetattr, + .readdir = rfsReaddir, + .open = rfsOpen, + .read = rfsRead, +}; + +void RepoFS::workerFn() { + int argc = 3; + char *argv[] = {"", "-d", const_cast(path.c_str())}; + std::cout << static_cast(fuse_main(argc, argv, &rfsOps, nullptr)); + // while (!stop) { + // } +} diff --git a/src/main.cpp b/src/main.cpp index 08d4c39..47934ab 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include +#include "CommandMount.h" #include "commands/includes/Command.h" #include "commands/includes/CommandDiff.h" #include "commands/includes/CommandList.h" @@ -113,6 +114,7 @@ int main(int argc, char *argv[]) { commands.emplace(CommandRun().name, std::make_unique()); commands.emplace(CommandListFiles().name, std::make_unique()); commands.emplace(CommandList().name, std::make_unique()); + commands.emplace(CommandMount().name, std::make_unique()); if (commands.count(opt) == 0) { std::cerr << "Unknown argument" << std::endl;