diff --git a/README.md b/README.md index 6b1ecaa..6067c16 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ int main(int argc, char* argv[]) { - `vfs::make_vfs` Basic file system. - `vfs::make_mem_fs` Files are stored on the memory. - `vfs::make_union_fs` Provides a single coherent file system over multiple file systems. +- `vfs::make_read_only_fs` Makes the given file system read-only. ### Utilities - `vfs::Fs::change_root` Changes the root directory. diff --git a/include/vfs/fs.hpp b/include/vfs/fs.hpp index dcd74b4..0c00682 100644 --- a/include/vfs/fs.hpp +++ b/include/vfs/fs.hpp @@ -1156,7 +1156,7 @@ std::shared_ptr make_os_fs(); /** * @brief Makes empty `Fs` that is virtual. Regular files are written to the temporary directory of the OS and are deleted when the `Fs` is destructed. * - * @param temp_dir Path to the temporary directory in the created Fs. + * @param temp_dir Path to the temporary directory in the created `Fs`. * @return New empty `Fs` that is virtual. */ std::shared_ptr make_vfs(std::filesystem::path const& temp_dir = "/tmp"); @@ -1164,13 +1164,19 @@ std::shared_ptr make_vfs(std::filesystem::path const& temp_dir = "/tmp"); /** * @brief Makes empty `Fs` that is virtual. Regular files are stored on the memory. * - * @param temp_dir Path to the temporary directory in the created Fs. + * @param temp_dir Path to the temporary directory in the created `Fs`. * @return New empty `Fs` that is virtual. */ std::shared_ptr make_mem_fs(std::filesystem::path const& temp_dir = "/tmp"); std::shared_ptr make_union_fs(Fs& upper, Fs const& lower); +/** + * @brief Makes `Fs` read-only. Non-const methods of resulting `Fs` throw `std::filesystem::filesystem_error` with `std::errc::read_only_file_system`. + * + * @param fs `Fs` to make read-only. + * @return `Fs` that is the same as the given `Fs` but read-only. + */ std::shared_ptr make_read_only_fs(Fs const& fs); } // namespace vfs diff --git a/internal/vfs/impl/fs.hpp b/internal/vfs/impl/fs.hpp index f6b201a..d317884 100644 --- a/internal/vfs/impl/fs.hpp +++ b/internal/vfs/impl/fs.hpp @@ -7,14 +7,155 @@ #include #include "vfs/impl/file.hpp" +#include "vfs/impl/utils.hpp" #include "vfs/fs.hpp" +#define VFS_FS_METHOD_NAMES \ + Fs::canonical, \ + Fs::weakly_canonical, \ + Fs::copy, \ + Fs::copy_file, \ + Fs::create_directory, \ + Fs::create_directories, \ + Fs::create_hard_link, \ + Fs::create_symlink, \ + Fs::current_path, \ + Fs::equivalent, \ + Fs::file_size, \ + Fs::hard_link_count, \ + Fs::last_write_time, \ + Fs::permissions, \ + Fs::read_symlink, \ + Fs::remove, \ + Fs::remove_all, \ + Fs::rename, \ + Fs::resize_file, \ + Fs::space, \ + Fs::status, \ + Fs::symlink_status, \ + Fs::temp_directory_path, \ + Fs::is_empty + namespace vfs { namespace impl { class FsBase: public Fs { public: + using VFS_FS_METHOD_NAMES; + + std::filesystem::path canonical(std::filesystem::path const& p, std::error_code& ec) const override { + return handle_error([&] { return this->canonical(p); }, ec); + } + + std::filesystem::path weakly_canonical(std::filesystem::path const& p, std::error_code& ec) const override { + return handle_error([&] { return this->weakly_canonical(p); }, ec); + } + + void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override { + handle_error([&] { this->copy(src, dst, opts); return 0; }, ec); + } + + bool copy_file(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override { + return handle_error([&] { return this->copy_file(src, dst, opts); }, ec); + } + + bool create_directory(std::filesystem::path const& p, std::error_code& ec) noexcept override { + return handle_error([&] { return this->create_directory(p); }, ec); + } + + bool create_directory(std::filesystem::path const& p, std::filesystem::path const& attr, std::error_code& ec) noexcept override { + return handle_error([&] { return this->create_directory(p, attr); }, ec); + } + + bool create_directories(std::filesystem::path const& p, std::error_code& ec) override { + return handle_error([&] { return this->create_directories(p); }, ec); + } + + void create_hard_link(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override { + handle_error([&] { this->create_hard_link(target, link); return 0; }, ec); + } + + void create_symlink(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override { + handle_error([&] { this->create_symlink(target, link); return 0; }, ec); + } + + [[nodiscard]] std::filesystem::path current_path(std::error_code& ec) const override { + return handle_error([&] { return this->current_path(); }, ec); + } + + [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->current_path(p); }, ec); + } + + [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) noexcept override { + return handle_error([&] { return this->current_path(p); }, ec); + } + + [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->equivalent(p1, p2); }, ec); + } + + [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->file_size(p); }, ec, static_cast(-1)); + } + + [[nodiscard]] std::uintmax_t hard_link_count(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->hard_link_count(p); }, ec, static_cast(-1)); + } + + [[nodiscard]] std::filesystem::file_time_type last_write_time(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->last_write_time(p); }, ec); + } + + void last_write_time(std::filesystem::path const& p, std::filesystem::file_time_type t, std::error_code& ec) noexcept override { + handle_error([&] { this->last_write_time(p, t); return 0; }, ec); + } + + void permissions(std::filesystem::path const& p, std::filesystem::perms prms, std::filesystem::perm_options opts, std::error_code& ec) override { + handle_error([&] { this->permissions(p, prms, opts); return 0; }, ec); + } + + [[nodiscard]] std::filesystem::path read_symlink(std::filesystem::path const& p, std::error_code& ec) const override { + return handle_error([&] { return this->read_symlink(p); }, ec); + } + + bool remove(std::filesystem::path const& p, std::error_code& ec) noexcept override { + return handle_error([&] { return this->remove(p); }, ec); + } + + std::uintmax_t remove_all(std::filesystem::path const& p, std::error_code& ec) override { + return handle_error([&] { return this->remove_all(p); }, ec, static_cast(-1)); + } + + void rename(std::filesystem::path const& src, std::filesystem::path const& dst, std::error_code& ec) noexcept override { + handle_error([&] { this->rename(src, dst); return 0; }, ec); + } + + void resize_file(std::filesystem::path const& p, std::uintmax_t n, std::error_code& ec) noexcept override { + handle_error([&] { this->resize_file(p, n); return 0; }, ec); + } + + [[nodiscard]] std::filesystem::space_info space(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->space(p); }, ec); + } + + [[nodiscard]] std::filesystem::file_status status(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->status(p); }, ec); + } + + [[nodiscard]] std::filesystem::file_status symlink_status(std::filesystem::path const& p, std::error_code& ec) const noexcept override { + return handle_error([&] { return this->symlink_status(p); }, ec); + } + + [[nodiscard]] std::filesystem::path temp_directory_path(std::error_code& ec) const override { + return handle_error([&] { return this->temp_directory_path(); }, ec); + } + + [[nodiscard]] bool is_empty(std::filesystem::path const& p, std::error_code& ec) const override { + return handle_error([&] { return this->is_empty(p); }, ec); + } + [[nodiscard]] virtual std::shared_ptr file_at(std::filesystem::path const& p) const = 0; virtual std::shared_ptr file_at(std::filesystem::path const& p) = 0; diff --git a/internal/vfs/impl/fs_proxy.hpp b/internal/vfs/impl/fs_proxy.hpp index 1fc0425..01d77bb 100644 --- a/internal/vfs/impl/fs_proxy.hpp +++ b/internal/vfs/impl/fs_proxy.hpp @@ -9,6 +9,7 @@ #include #include "vfs/impl/fs.hpp" +#include "vfs/impl/utils.hpp" #include "vfs/fs.hpp" @@ -52,236 +53,114 @@ class BasicFsProxy: public FsBase { return this->fs_->canonical(p); } - [[nodiscard]] std::filesystem::path canonical(std::filesystem::path const& p, std::error_code& ec) const override { - return this->fs_->canonical(p, ec); - } - [[nodiscard]] std::filesystem::path weakly_canonical(std::filesystem::path const& p) const override { return this->fs_->weakly_canonical(p); } - [[nodiscard]] std::filesystem::path weakly_canonical(std::filesystem::path const& p, std::error_code& ec) const override { - return this->fs_->weakly_canonical(p, ec); - } - void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts) override { this->mutable_fs_()->copy(src, dst, opts); } - void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override { - this->mutable_fs_()->copy(src, dst, opts, ec); - } - bool copy_file(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts) override { return this->mutable_fs_()->copy_file(src, dst, opts); } - bool copy_file(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override { - return this->mutable_fs_()->copy_file(src, dst, opts, ec); - } - bool create_directory(std::filesystem::path const& p) override { return this->mutable_fs_()->create_directory(p); } - bool create_directory(std::filesystem::path const& p, std::error_code& ec) noexcept override { - return this->mutable_fs_()->create_directory(p, ec); - } - bool create_directory(std::filesystem::path const& p, std::filesystem::path const& attr) override { return this->mutable_fs_()->create_directory(p, attr); } - bool create_directory(std::filesystem::path const& p, std::filesystem::path const& attr, std::error_code& ec) noexcept override { - return this->mutable_fs_()->create_directory(p, attr, ec); - } - bool create_directories(std::filesystem::path const& p) override { return this->mutable_fs_()->create_directories(p); } - bool create_directories(std::filesystem::path const& p, std::error_code& ec) override { - return this->mutable_fs_()->create_directories(p, ec); - } - void create_hard_link(std::filesystem::path const& target, std::filesystem::path const& link) override { return this->mutable_fs_()->create_hard_link(target, link); } - void create_hard_link(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override { - return this->mutable_fs_()->create_hard_link(target, link, ec); - } - void create_symlink(std::filesystem::path const& target, std::filesystem::path const& link) override { return this->mutable_fs_()->create_symlink(target, link); } - void create_symlink(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override { - return this->mutable_fs_()->create_symlink(target, link, ec); - } - [[nodiscard]] std::filesystem::path current_path() const override { return this->fs_->current_path(); } - [[nodiscard]] std::filesystem::path current_path(std::error_code& ec) const override { - return this->fs_->current_path(ec); - } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p) const override { return this->make_proxy_(this->fs_->current_path(p)); } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - auto fs = this->fs_->current_path(p, ec); - if(ec) { - return nullptr; - } - - return this->make_proxy_(std::move(fs)); - } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p) override { return this->make_proxy_(this->mutable_fs_()->current_path(p)); } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) noexcept override { - auto fs = this->mutable_fs_()->current_path(p, ec); - if(ec) { - return nullptr; - } - - return this->make_proxy_(std::move(fs)); - } - [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2) const override { return this->fs_->equivalent(p1, p2); } - [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2, std::error_code& ec) const noexcept override { - return this->fs_->equivalent(p1, p2, ec); - } - [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p) const override { return this->fs_->file_size(p); } - [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->file_size(p, ec); - } - [[nodiscard]] std::uintmax_t hard_link_count(std::filesystem::path const& p) const override { return this->fs_->hard_link_count(p); } - [[nodiscard]] std::uintmax_t hard_link_count(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->hard_link_count(p, ec); - } - [[nodiscard]] std::filesystem::file_time_type last_write_time(std::filesystem::path const& p) const override { return this->fs_->last_write_time(p); } - [[nodiscard]] std::filesystem::file_time_type last_write_time(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->last_write_time(p, ec); - } - void last_write_time(std::filesystem::path const& p, std::filesystem::file_time_type t) override { this->mutable_fs_()->last_write_time(p, t); } - void last_write_time(std::filesystem::path const& p, std::filesystem::file_time_type t, std::error_code& ec) noexcept override { - this->mutable_fs_()->last_write_time(p, t, ec); - } - void permissions(std::filesystem::path const& p, std::filesystem::perms prms, std::filesystem::perm_options opts) override { this->mutable_fs_()->permissions(p, prms, opts); } - void permissions(std::filesystem::path const& p, std::filesystem::perms prms, std::filesystem::perm_options opts, std::error_code& ec) override { - this->mutable_fs_()->permissions(p, prms, opts, ec); - } - [[nodiscard]] std::filesystem::path read_symlink(std::filesystem::path const& p) const override { return this->fs_->read_symlink(p); } - [[nodiscard]] std::filesystem::path read_symlink(std::filesystem::path const& p, std::error_code& ec) const override { - return this->fs_->read_symlink(p, ec); - } - bool remove(std::filesystem::path const& p) override { return this->mutable_fs_()->remove(p); } - bool remove(std::filesystem::path const& p, std::error_code& ec) noexcept override { - return this->mutable_fs_()->remove(p, ec); - } - std::uintmax_t remove_all(std::filesystem::path const& p) override { return this->mutable_fs_()->remove_all(p); } - std::uintmax_t remove_all(std::filesystem::path const& p, std::error_code& ec) override { - return this->mutable_fs_()->remove_all(p, ec); - } - void rename(std::filesystem::path const& src, std::filesystem::path const& dst) override { this->mutable_fs_()->rename(src, dst); } - void rename(std::filesystem::path const& src, std::filesystem::path const& dst, std::error_code& ec) noexcept override { - this->mutable_fs_()->rename(src, dst, ec); - } - void resize_file(std::filesystem::path const& p, std::uintmax_t n) override { this->mutable_fs_()->resize_file(p, n); } - void resize_file(std::filesystem::path const& p, std::uintmax_t n, std::error_code& ec) noexcept override { - this->mutable_fs_()->resize_file(p, n, ec); - } - [[nodiscard]] std::filesystem::space_info space(std::filesystem::path const& p) const override { return this->fs_->space(p); } - [[nodiscard]] std::filesystem::space_info space(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->space(p, ec); - } - [[nodiscard]] std::filesystem::file_status status(std::filesystem::path const& p) const override { return this->fs_->status(p); } - [[nodiscard]] std::filesystem::file_status status(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->status(p, ec); - } - [[nodiscard]] std::filesystem::file_status symlink_status(std::filesystem::path const& p) const override { return this->fs_->symlink_status(p); } - [[nodiscard]] std::filesystem::file_status symlink_status(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return this->fs_->symlink_status(p, ec); - } - [[nodiscard]] std::filesystem::path temp_directory_path() const override { return this->fs_->temp_directory_path(); } - [[nodiscard]] std::filesystem::path temp_directory_path(std::error_code& ec) const override { - return this->fs_->temp_directory_path(ec); - } - [[nodiscard]] bool is_empty(std::filesystem::path const& p) const override { return this->fs_->is_empty(p); } - bool is_empty(std::filesystem::path const& p, std::error_code& ec) const override { - return this->fs_->is_empty(p, ec); - } - [[nodiscard]] std::shared_ptr file_at(std::filesystem::path const& p) const override { return this->fs_->file_at(p); } diff --git a/internal/vfs/impl/os_fs.hpp b/internal/vfs/impl/os_fs.hpp index caefc8a..302bb95 100644 --- a/internal/vfs/impl/os_fs.hpp +++ b/internal/vfs/impl/os_fs.hpp @@ -101,10 +101,6 @@ class StdFs: public OsFs { return std::filesystem::canonical(this->os_path_of(p)); } - [[nodiscard]] std::filesystem::path canonical(std::filesystem::path const& p, std::error_code& ec) const override { - return handle_error([&] { return this->canonical(p); }, ec); - } - [[nodiscard]] std::filesystem::path weakly_canonical(std::filesystem::path const& p) const override { if(p.empty()) { return p; @@ -116,10 +112,6 @@ class StdFs: public OsFs { return std::filesystem::weakly_canonical(this->os_path_of(p)); } - [[nodiscard]] std::filesystem::path weakly_canonical(std::filesystem::path const& p, std::error_code& ec) const override { - return handle_error([&] { return this->weakly_canonical(p); }, ec); - } - void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts) override { std::filesystem::copy(this->os_path_of(src), this->os_path_of(dst), opts); } @@ -193,26 +185,14 @@ class StdFs: public OsFs { return std::make_shared(this->canonical(p)); } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) const noexcept override { - return handle_error([&] { return this->current_path(p); }, ec); - } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p) override { return std::const_pointer_cast(static_cast(this)->current_path(p)); } - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) noexcept override { - return handle_error([&] { return this->current_path(p); }, ec); - } - [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2) const override { return std::filesystem::equivalent(this->os_path_of(p1), this->os_path_of(p2)); } - [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2, std::error_code& ec) const noexcept override { - return handle_error([&] { return this->equivalent(p1, p2); }, ec); - } - [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p) const override { return std::filesystem::file_size(this->os_path_of(p)); } @@ -321,18 +301,10 @@ class StdFs: public OsFs { return std::filesystem::temp_directory_path(); } - [[nodiscard]] std::filesystem::path temp_directory_path(std::error_code& ec) const override { - return handle_error([&] { return this->temp_directory_path(); }, ec); - } - [[nodiscard]] bool is_empty(std::filesystem::path const& p) const override { return std::filesystem::is_empty(this->os_path_of(p)); } - [[nodiscard]] bool is_empty(std::filesystem::path const& p, std::error_code& ec) const override { - return handle_error([&] { return this->is_empty(p); }, ec); - } - [[nodiscard]] std::shared_ptr file_at(std::filesystem::path const& p) const override; [[nodiscard]] std::shared_ptr file_at(std::filesystem::path const& p) override { diff --git a/internal/vfs/impl/vfs.hpp b/internal/vfs/impl/vfs.hpp index cfe8a02..a0a64fb 100644 --- a/internal/vfs/impl/vfs.hpp +++ b/internal/vfs/impl/vfs.hpp @@ -50,88 +50,62 @@ class Vfs: public FsBase { } [[nodiscard]] std::filesystem::path canonical(std::filesystem::path const& p) const override; - std::filesystem::path canonical(std::filesystem::path const& p, std::error_code& ec) const override; [[nodiscard]] std::filesystem::path weakly_canonical(std::filesystem::path const& p) const override; - std::filesystem::path weakly_canonical(std::filesystem::path const& p, std::error_code& ec) const override; void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts) override; - void copy(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override; bool copy_file(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts) override; - bool copy_file(std::filesystem::path const& src, std::filesystem::path const& dst, std::filesystem::copy_options opts, std::error_code& ec) override; bool create_directory(std::filesystem::path const& p) override; - bool create_directory(std::filesystem::path const& p, std::error_code& ec) noexcept override; bool create_directory(std::filesystem::path const& p, std::filesystem::path const& attr) override; - bool create_directory(std::filesystem::path const& p, std::filesystem::path const& attr, std::error_code& ec) noexcept override; bool create_directories(std::filesystem::path const& p) override; - bool create_directories(std::filesystem::path const& p, std::error_code& ec) override; void create_hard_link(std::filesystem::path const& target, std::filesystem::path const& link) override; - void create_hard_link(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override; void create_symlink(std::filesystem::path const& target, std::filesystem::path const& link) override; - void create_symlink(std::filesystem::path const& target, std::filesystem::path const& link, std::error_code& ec) noexcept override; [[nodiscard]] std::filesystem::path current_path() const override; + [[nodiscard]] std::filesystem::path current_path(std::error_code& ec) const override; [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p) const override; - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p) override; - [[nodiscard]] std::shared_ptr current_path(std::filesystem::path const& p, std::error_code& ec) noexcept override; [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2) const override; - [[nodiscard]] bool equivalent(std::filesystem::path const& p1, std::filesystem::path const& p2, std::error_code& ec) const noexcept override; [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p) const override; - [[nodiscard]] std::uintmax_t file_size(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::uintmax_t hard_link_count(std::filesystem::path const& p) const override; - [[nodiscard]] std::uintmax_t hard_link_count(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::filesystem::file_time_type last_write_time(std::filesystem::path const& p) const override; - [[nodiscard]] std::filesystem::file_time_type last_write_time(std::filesystem::path const& p, std::error_code& ec) const noexcept override; void last_write_time(std::filesystem::path const& p, std::filesystem::file_time_type t) override; - void last_write_time(std::filesystem::path const& p, std::filesystem::file_time_type t, std::error_code& ec) noexcept override; void permissions(std::filesystem::path const& p, std::filesystem::perms prms, std::filesystem::perm_options opts = std::filesystem::perm_options::replace) override; - void permissions(std::filesystem::path const& p, std::filesystem::perms prms, std::filesystem::perm_options opts, std::error_code& ec) override; [[nodiscard]] std::filesystem::path read_symlink(std::filesystem::path const& p) const override; - [[nodiscard]] std::filesystem::path read_symlink(std::filesystem::path const& p, std::error_code& ec) const override; bool remove(std::filesystem::path const& p) override; - bool remove(std::filesystem::path const& p, std::error_code& ec) noexcept override; std::uintmax_t remove_all(std::filesystem::path const& p) override; - std::uintmax_t remove_all(std::filesystem::path const& p, std::error_code& ec) override; void rename(std::filesystem::path const& src, std::filesystem::path const& dst) override; - void rename(std::filesystem::path const& src, std::filesystem::path const& dst, std::error_code& ec) noexcept override; void resize_file(std::filesystem::path const& p, std::uintmax_t n) override; - void resize_file(std::filesystem::path const& p, std::uintmax_t n, std::error_code& ec) noexcept override; [[nodiscard]] std::filesystem::space_info space(std::filesystem::path const& p) const override; - [[nodiscard]] std::filesystem::space_info space(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::filesystem::file_status status(std::filesystem::path const& p) const override; - [[nodiscard]] std::filesystem::file_status status(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::filesystem::file_status symlink_status(std::filesystem::path const& p) const override; - [[nodiscard]] std::filesystem::file_status symlink_status(std::filesystem::path const& p, std::error_code& ec) const noexcept override; [[nodiscard]] std::filesystem::path temp_directory_path() const override; - [[nodiscard]] std::filesystem::path temp_directory_path(std::error_code& ec) const override; [[nodiscard]] bool is_empty(std::filesystem::path const& p) const override; - [[nodiscard]] bool is_empty(std::filesystem::path const& p, std::error_code& ec) const override; [[nodiscard]] std::shared_ptr file_at(std::filesystem::path const& p) const override { return this->navigate(p)->file(); diff --git a/src/vfs.cpp b/src/vfs.cpp index e2ae0fb..8aea267 100644 --- a/src/vfs.cpp +++ b/src/vfs.cpp @@ -132,10 +132,6 @@ fs::path Vfs::canonical(fs::path const& p) const { return this->navigate(p)->follow_chain()->path(); } -fs::path Vfs::canonical(fs::path const& p, std::error_code& ec) const { - return handle_error([&] { return this->canonical(p); }, ec); -} - fs::path Vfs::weakly_canonical(fs::path const& p) const { auto ec = std::error_code(); auto [f, it] = this->navigate(p.begin(), p.end(), ec); @@ -150,14 +146,6 @@ fs::path Vfs::weakly_canonical(fs::path const& p) const { return t.lexically_normal(); } -fs::path Vfs::weakly_canonical(fs::path const& p, std::error_code& ec) const { - return handle_error([&] { return this->weakly_canonical(p); }, ec); -} - -void Vfs::copy(fs::path const& src, fs::path const& dst, fs::copy_options opts, std::error_code& ec) { - handle_error([&] { this->copy(src, dst, opts); return 0; }, ec); -} - bool Vfs::copy_file(fs::path const& src, fs::path const& dst, fs::copy_options opts) { auto const src_f = this->navigate(src)->follow_chain(); auto const src_r = std::dynamic_pointer_cast(src_f); @@ -196,18 +184,10 @@ bool Vfs::copy_file(fs::path const& src, fs::path const& dst, fs::copy_options o throw fs::filesystem_error("", src_r->path(), dst_p, std::make_error_code(std::errc::file_exists)); } -bool Vfs::copy_file(fs::path const& src, fs::path const& dst, fs::copy_options opts, std::error_code& ec) { - return handle_error([&] { return this->copy_file(src, dst, opts); }, ec, false); -} - bool Vfs::create_directory(fs::path const& p) { return this->create_directory(p, fs::path("/")); } -bool Vfs::create_directory(fs::path const& p, std::error_code& ec) noexcept { - return this->create_directory(p, fs::path("/"), ec); -} - bool Vfs::create_directory(fs::path const& p, fs::path const& attr) { auto const dst_p = this->weakly_canonical(p); auto const prev = this->navigate(p.parent_path() / "")->must_be(); @@ -233,10 +213,6 @@ bool Vfs::create_directory(fs::path const& p, fs::path const& attr) { throw fs::filesystem_error("", dst_p, std::make_error_code(std::errc::file_exists)); } -bool Vfs::create_directory(fs::path const& p, fs::path const& attr, std::error_code& ec) noexcept { - return handle_error([&] { return this->create_directory(p, attr); }, ec); -} - bool Vfs::create_directories(fs::path const& p) { auto const t = this->weakly_canonical(p); auto [f, it] = this->navigate(t.begin(), t.end()); @@ -260,10 +236,6 @@ bool Vfs::create_directories(fs::path const& p) { return true; } -bool Vfs::create_directories(fs::path const& p, std::error_code& ec) { - return handle_error([&] { return this->create_directories(p); }, ec); -} - void Vfs::create_hard_link(fs::path const& target, fs::path const& link) { auto const dst_f = this->navigate(target); if(dst_f->file()->type() == fs::file_type::directory) { @@ -275,10 +247,6 @@ void Vfs::create_hard_link(fs::path const& target, fs::path const& link) { prev->typed_file()->link(src_p.filename(), dst_f->file()); } -void Vfs::create_hard_link(fs::path const& target, fs::path const& link, std::error_code& ec) noexcept { - handle_error([&] { this->create_hard_link(target, link); return 0; }, ec); -} - void Vfs::create_symlink(fs::path const& target, fs::path const& link) { auto const src_p = this->weakly_canonical(link); auto const prev = this->navigate(src_p.parent_path() / "")->must_be(); @@ -289,10 +257,6 @@ void Vfs::create_symlink(fs::path const& target, fs::path const& link) { prev->emplace_symlink(src_p.filename(), target); } -void Vfs::create_symlink(fs::path const& target, fs::path const& link, std::error_code& ec) noexcept { - handle_error([&] {this->create_symlink(target, link); return 0; }, ec); -} - fs::path Vfs::current_path() const { return this->cwd_->path(); } @@ -306,18 +270,10 @@ std::shared_ptr Vfs::current_path(fs::path const& p) const { return std::make_shared(*this, const_cast(*d)); } -std::shared_ptr Vfs::current_path(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->current_path(p); }, ec); -} - std::shared_ptr Vfs::current_path(fs::path const& p) { return std::const_pointer_cast(static_cast(this)->current_path(p)); } -std::shared_ptr Vfs::current_path(fs::path const& p, std::error_code& ec) noexcept { - return std::const_pointer_cast(static_cast(this)->current_path(p, ec)); -} - bool Vfs::equivalent(fs::path const& p1, fs::path const& p2) const { std::shared_ptr f1; std::shared_ptr f2; @@ -342,10 +298,6 @@ bool Vfs::equivalent(fs::path const& p1, fs::path const& p2) const { throw fs::filesystem_error("", p1, p2, std::make_error_code(std::errc::no_such_file_or_directory)); } -bool Vfs::equivalent(fs::path const& p1, fs::path const& p2, std::error_code& ec) const noexcept { - return handle_error([&] { return this->equivalent(p1, p2); }, ec); -} - std::uintmax_t Vfs::file_size(fs::path const& p) const { auto const f = this->navigate(p)->follow_chain(); if(auto const d = std::dynamic_pointer_cast(f); d) { @@ -360,37 +312,21 @@ std::uintmax_t Vfs::file_size(fs::path const& p) const { return r->typed_file()->size(); } -std::uintmax_t Vfs::file_size(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->file_size(p); }, ec, static_cast(-1)); -} - std::uintmax_t Vfs::hard_link_count(fs::path const& p) const { auto const f = this->navigate(p)->file(); return f.use_count() - 1; // Minus one for being held by `f`. } -std::uintmax_t Vfs::hard_link_count(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->hard_link_count(p); }, ec, static_cast(-1)); -} - fs::file_time_type Vfs::last_write_time(fs::path const& p) const { auto const f = this->navigate(p)->follow_chain(); return f->file()->last_write_time(); } -fs::file_time_type Vfs::last_write_time(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->last_write_time(p); }, ec, fs::file_time_type::min()); -} - void Vfs::last_write_time(fs::path const& p, fs::file_time_type t) { auto const f = this->navigate(p)->follow_chain(); f->file()->last_write_time(t); } -void Vfs::last_write_time(fs::path const& p, fs::file_time_type t, std::error_code& ec) noexcept { - handle_error([&] { this->last_write_time(p, t); return 0; }, ec); -} - void Vfs::permissions(fs::path const& p, fs::perms prms, fs::perm_options opts) { auto f = this->navigate(p); if((opts & fs::perm_options::nofollow) != fs::perm_options::nofollow) { @@ -400,10 +336,6 @@ void Vfs::permissions(fs::path const& p, fs::perms prms, fs::perm_options opts) f->file()->perms(prms, opts); } -void Vfs::permissions(fs::path const& p, fs::perms prms, fs::perm_options opts, std::error_code& ec) { - handle_error([&] { this->permissions(p, prms, opts); return 0; }, ec); -} - fs::path Vfs::read_symlink(fs::path const& p) const { auto const f = this->navigate(p); auto const s = std::dynamic_pointer_cast(f); @@ -414,10 +346,6 @@ fs::path Vfs::read_symlink(fs::path const& p) const { return s->typed_file()->target(); } -fs::path Vfs::read_symlink(fs::path const& p, std::error_code& ec) const { - return handle_error([&] { return this->read_symlink(p); }, ec); -} - bool Vfs::remove(fs::path const& p) { auto ec = std::error_code(); auto const f = this->navigate(p, ec); @@ -434,10 +362,6 @@ bool Vfs::remove(fs::path const& p) { return true; } -bool Vfs::remove(fs::path const& p, std::error_code& ec) noexcept { - return handle_error([&] { return this->remove(p); }, ec); -} - std::uintmax_t Vfs::remove_all(fs::path const& p) { auto ec = std::error_code(); auto const f = this->navigate(p, ec); @@ -448,10 +372,6 @@ std::uintmax_t Vfs::remove_all(fs::path const& p) { return f->prev()->typed_file()->erase(f->name()); } -std::uintmax_t Vfs::remove_all(fs::path const& p, std::error_code& ec) { - return handle_error([&] { return this->remove_all(p); }, ec, static_cast(-1)); -} - namespace { void throw_if_not_overwritable_(std::shared_ptr const& src, std::shared_ptr const& dst, fs::path const& dst_p) { @@ -546,10 +466,6 @@ void Vfs::rename(fs::path const& src, fs::path const& dst) { src_f->prev()->typed_file()->unlink(src_f->name()); } -void Vfs::rename(fs::path const& src, fs::path const& dst, std::error_code& ec) noexcept { - handle_error([&] { this->rename(src, dst); return 0; }, ec); -} - void Vfs::resize_file(fs::path const& p, std::uintmax_t n) { auto const f = this->navigate(p)->follow_chain(); if(auto const d = std::dynamic_pointer_cast(f); d) { @@ -564,18 +480,10 @@ void Vfs::resize_file(fs::path const& p, std::uintmax_t n) { r->typed_file()->resize(n); } -void Vfs::resize_file(fs::path const& p, std::uintmax_t n, std::error_code& ec) noexcept { - handle_error([&] { this->resize_file(p, n); return 0; }, ec); -} - fs::space_info Vfs::space(fs::path const& p) const { return this->navigate(p)->follow_chain()->file()->space(); } -fs::space_info Vfs::space(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->space(p); }, ec); -} - fs::file_status Vfs::status(fs::path const& p) const { try { auto const f = this->navigate(p)->follow_chain()->file(); @@ -596,10 +504,6 @@ fs::file_status Vfs::status(fs::path const& p) const { } } -fs::file_status Vfs::status(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->status(p); }, ec); -} - fs::file_status Vfs::symlink_status(fs::path const& p) const { try { auto const f = this->navigate(p)->file(); @@ -620,10 +524,6 @@ fs::file_status Vfs::symlink_status(fs::path const& p) const { } } -fs::file_status Vfs::symlink_status(fs::path const& p, std::error_code& ec) const noexcept { - return handle_error([&] { return this->symlink_status(p); }, ec); -} - fs::path Vfs::temp_directory_path() const { if(this->temp_.empty()) { throw fs::filesystem_error("", std::make_error_code(std::errc::no_such_file_or_directory)); @@ -632,11 +532,6 @@ fs::path Vfs::temp_directory_path() const { return this->temp_; } -fs::path Vfs::temp_directory_path(std::error_code& ec) const { - ec.clear(); - return this->temp_; -} - bool Vfs::is_empty(fs::path const& p) const { auto const f = this->navigate(p); if(auto d = std::dynamic_pointer_cast(f); d) { @@ -648,10 +543,6 @@ bool Vfs::is_empty(fs::path const& p) const { throw fs::filesystem_error("cannot determine if file is empty", f->path(), std::make_error_code(std::errc::no_such_file_or_directory)); } -bool Vfs::is_empty(fs::path const& p, std::error_code& ec) const { - return handle_error([&] { return this->is_empty(p); }, ec); -} - class Vfs::Cursor_: public Fs::Cursor { public: Cursor_(Vfs const& fs, DirectoryEntry const& dir, std::filesystem::directory_options opts) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d38af36..75be567 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -98,6 +98,7 @@ vfs_SIMPLE_TEST(mem_fs) vfs_SIMPLE_TEST(mount) vfs_SIMPLE_TEST(os_file) vfs_SIMPLE_TEST(os_fs) +vfs_SIMPLE_TEST(read_only_fs) vfs_SIMPLE_TEST(union_file) vfs_SIMPLE_TEST(union_fs) vfs_SIMPLE_TEST(vfile) diff --git a/tests/src/read_only_fs.cpp b/tests/src/read_only_fs.cpp new file mode 100644 index 0000000..f1cc14c --- /dev/null +++ b/tests/src/read_only_fs.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include + +#include + +TEST_CASE("ReadOnlyFsProxy") { + namespace fs = std::filesystem; + + auto origin = vfs::make_mem_fs(); + auto readonly = vfs::make_read_only_fs(*origin); + + SECTION("non-const function fails") { + std::error_code ec; + + auto test = [&](std::function const& f) { + ec.clear(); + try { + f(); + return ec; + } catch(fs::filesystem_error const& error) { + return error.code(); + } + }; + + CHECK(std::errc::read_only_file_system == test([&] { readonly->open_write("foo"); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->canonical("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->weakly_canonical("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->copy("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->copy_file("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->create_directory("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->create_directory("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->create_directories("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->create_hard_link("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->create_symlink("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->current_path(ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->equivalent("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->file_size("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->hard_link_count("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->last_write_time("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->last_write_time("foo", fs::file_time_type{}, ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->permissions("foo", fs::perms::all, ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->read_symlink("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->remove("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->remove_all("foo", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->rename("foo", "bar", ec); })); + CHECK(std::errc::read_only_file_system == test([&] { readonly->resize_file("foo", 42, ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->space("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->status("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->symlink_status("foo", ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->temp_directory_path(ec); })); + CHECK(std::errc::read_only_file_system != test([&] { readonly->is_empty("foo", ec); })); + } +}