From f5ac66503dd342eba4db379cdebb57b95d077c4a Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Tue, 13 Feb 2024 00:20:49 +0100 Subject: [PATCH] fix(windows): hopefully fix path tweaking / canonicalization --- include/dwarfs/filesystem_extractor.h | 14 ++++++++----- src/dwarfs/filesystem_extractor.cpp | 19 ++++++++++------- src/dwarfs/util.cpp | 16 +++++++------- src/dwarfs_main.cpp | 5 ++++- src/dwarfsck_main.cpp | 14 ++++++++----- src/dwarfsextract_main.cpp | 30 ++++++++++++++++++++------- 6 files changed, 64 insertions(+), 34 deletions(-) diff --git a/include/dwarfs/filesystem_extractor.h b/include/dwarfs/filesystem_extractor.h index 07f68dca..a52c7588 100644 --- a/include/dwarfs/filesystem_extractor.h +++ b/include/dwarfs/filesystem_extractor.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include #include @@ -44,7 +45,8 @@ class filesystem_extractor { public: filesystem_extractor(logger& lgr, os_access const& os); - void open_archive(std::string const& output, std::string const& format) { + void + open_archive(std::filesystem::path const& output, std::string const& format) { return impl_->open_archive(output, format); } @@ -52,7 +54,9 @@ class filesystem_extractor { return impl_->open_stream(os, format); } - void open_disk(std::string const& output) { return impl_->open_disk(output); } + void open_disk(std::filesystem::path const& output) { + return impl_->open_disk(output); + } void close() { return impl_->close(); } @@ -66,10 +70,10 @@ class filesystem_extractor { public: virtual ~impl() = default; - virtual void - open_archive(std::string const& output, std::string const& format) = 0; + virtual void open_archive(std::filesystem::path const& output, + std::string const& format) = 0; virtual void open_stream(std::ostream& os, std::string const& format) = 0; - virtual void open_disk(std::string const& output) = 0; + virtual void open_disk(std::filesystem::path const& output) = 0; virtual void close() = 0; virtual bool extract(filesystem_v2 const& fs, filesystem_extractor_options const& opts) = 0; diff --git a/src/dwarfs/filesystem_extractor.cpp b/src/dwarfs/filesystem_extractor.cpp index 348606cd..390f0ec7 100644 --- a/src/dwarfs/filesystem_extractor.cpp +++ b/src/dwarfs/filesystem_extractor.cpp @@ -104,13 +104,19 @@ class filesystem_extractor_ final : public filesystem_extractor::impl { } } - void - open_archive(std::string const& output, std::string const& format) override { + void open_archive(std::filesystem::path const& output, + std::string const& format) override { a_ = ::archive_write_new(); check_result(::archive_write_set_format_by_name(a_, format.c_str())); + +#ifdef _WIN32 + check_result(::archive_write_open_filename_w( + a_, output.empty() ? nullptr : output.wstring().c_str())); +#else check_result(::archive_write_open_filename( - a_, output.empty() ? nullptr : output.c_str())); + a_, output.empty() ? nullptr : output.string().c_str())); +#endif } void open_stream(std::ostream& os, std::string const& format) override { @@ -133,12 +139,9 @@ class filesystem_extractor_ final : public filesystem_extractor::impl { check_result(::archive_write_open_fd(a_, pipefd_[1])); } - void open_disk(std::string const& output) override { + void open_disk(std::filesystem::path const& output) override { if (!output.empty()) { - if (::chdir(output.c_str()) != 0) { - DWARFS_THROW(runtime_error, - output + ": " + std::string(strerror(errno))); - } + std::filesystem::current_path(output); } a_ = ::archive_write_disk_new(); diff --git a/src/dwarfs/util.cpp b/src/dwarfs/util.cpp index be1aa13f..29819080 100644 --- a/src/dwarfs/util.cpp +++ b/src/dwarfs/util.cpp @@ -305,16 +305,18 @@ void shorten_path_string(std::string& path, char separator, size_t max_len) { } std::filesystem::path canonical_path(std::filesystem::path p) { - try { - p = std::filesystem::canonical(p); - } catch (std::filesystem::filesystem_error const&) { - p = std::filesystem::absolute(p); - } - + if (!p.empty()) { #ifdef _WIN32 - p = std::filesystem::path(L"\\\\?\\" + p.wstring()); + p = std::filesystem::path(L"\\\\?\\" + p.wstring()); #endif + try { + p = std::filesystem::canonical(p); + } catch (std::filesystem::filesystem_error const&) { + p = std::filesystem::absolute(p); + } + } + return p; } diff --git a/src/dwarfs_main.cpp b/src/dwarfs_main.cpp index 9efedf9b..80bf703a 100644 --- a/src/dwarfs_main.cpp +++ b/src/dwarfs_main.cpp @@ -90,6 +90,7 @@ #include "dwarfs/metadata_v2.h" #include "dwarfs/mmap.h" #include "dwarfs/options.h" +#include "dwarfs/os_access.h" #include "dwarfs/performance_monitor.h" #include "dwarfs/tool.h" #include "dwarfs/util.h" @@ -1289,9 +1290,11 @@ void load_filesystem(dwarfs_userdata& userdata) { PERFMON_EXT_TIMER_SETUP(userdata, op_getxattr) PERFMON_EXT_TIMER_SETUP(userdata, op_listxattr) - auto fsimage = canonical_path(std::filesystem::path( + auto fsimage = userdata.iol.os->canonical(std::filesystem::path( reinterpret_cast(opts.fsimage->data()))); + LOG_DEBUG << "attempting to load filesystem from " << fsimage; + userdata.fs = filesystem_v2(userdata.lgr, *userdata.iol.os, std::make_shared(fsimage), fsopts, userdata.perfmon); diff --git a/src/dwarfsck_main.cpp b/src/dwarfsck_main.cpp index 3f7ea979..0e8c8767 100644 --- a/src/dwarfsck_main.cpp +++ b/src/dwarfsck_main.cpp @@ -46,6 +46,7 @@ #include "dwarfs/mmap.h" #include "dwarfs/options.h" #include "dwarfs/os_access.h" +#include "dwarfs/program_options_helpers.h" #include "dwarfs/tool.h" #include "dwarfs/util.h" #include "dwarfs/worker_group.h" @@ -162,7 +163,8 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) { auto checksum_desc = "print checksums for all files (" + (from(algo_list) | unsplit(", ")) + ")"; - std::string input, export_metadata, image_offset, checksum_algo; + sys_string input, export_metadata; + std::string image_offset, checksum_algo; logger_options logopts; size_t num_workers; int detail; @@ -178,7 +180,7 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) { po::options_description opts("Command line options"); opts.add_options() ("input,i", - po::value(&input), + po_sys_value(&input), "input filesystem") ("detail,d", po::value(&detail)->default_value(2), @@ -214,7 +216,7 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) { po::value(&output_json)->zero_tokens(), "print information in JSON format") ("export-metadata", - po::value(&export_metadata), + po_sys_value(&export_metadata), "export raw metadata as JSON to file") ; // clang-format on @@ -280,7 +282,9 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) { fsopts.metadata.check_consistency = check_integrity; fsopts.image_offset = parse_image_offset(image_offset); - std::shared_ptr mm = iol.os->map_file(input); + auto input_path = iol.os->canonical(input); + + std::shared_ptr mm = iol.os->map_file(input_path); if (print_header) { if (auto hdr = filesystem_v2::header(mm, fsopts.image_offset)) { @@ -303,7 +307,7 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) { if (!export_metadata.empty()) { std::error_code ec; - auto of = iol.file->open_output(export_metadata, ec); + auto of = iol.file->open_output(iol.os->canonical(export_metadata), ec); if (ec) { LOG_ERROR << "failed to open metadata output file: " << ec.message(); return 1; diff --git a/src/dwarfsextract_main.cpp b/src/dwarfsextract_main.cpp index c2e15c5a..ff29e347 100644 --- a/src/dwarfsextract_main.cpp +++ b/src/dwarfsextract_main.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -37,6 +38,7 @@ #include "dwarfs/options.h" #include "dwarfs/os_access.h" #include "dwarfs/performance_monitor.h" +#include "dwarfs/program_options_helpers.h" #include "dwarfs/tool.h" #include "dwarfs/util.h" #include "dwarfs_tool_main.h" @@ -45,8 +47,19 @@ namespace po = boost::program_options; namespace dwarfs { +namespace { + +#ifdef _WIN32 +constexpr std::wstring_view kDash{L"-"}; +#else +constexpr std::string_view kDash{"-"}; +#endif + +} // namespace + int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) { - std::string filesystem, output, format, cache_size_str, image_offset; + sys_string filesystem, output; + std::string format, cache_size_str, image_offset; logger_options logopts; #if DWARFS_PERFMON_ENABLED std::string perfmon_str; @@ -59,10 +72,10 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) { po::options_description opts("Command line options"); opts.add_options() ("input,i", - po::value(&filesystem), + po_sys_value(&filesystem), "input filesystem file") ("output,o", - po::value(&output), + po_sys_value(&output), "output file or directory") ("image-offset,O", po::value(&image_offset)->default_value("auto"), @@ -145,16 +158,17 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) { std::shared_ptr perfmon = performance_monitor::create(perfmon_enabled); - filesystem_v2 fs(lgr, *iol.os, iol.os->map_file(filesystem), fsopts, - perfmon); + auto fs_path = iol.os->canonical(filesystem); + + filesystem_v2 fs(lgr, *iol.os, iol.os->map_file(fs_path), fsopts, perfmon); filesystem_extractor fsx(lgr, *iol.os); if (format.empty()) { - fsx.open_disk(output); + fsx.open_disk(iol.os->canonical(output)); } else { std::ostream* stream{nullptr}; - if (output.empty() or output == "-") { + if (output.empty() or output == kDash) { if (stdout_progress) { DWARFS_THROW(runtime_error, "cannot use --stdout-progress with --output=-"); @@ -170,7 +184,7 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) { if (stream) { fsx.open_stream(*stream, format); } else { - fsx.open_archive(output, format); + fsx.open_archive(iol.os->canonical(output), format); } }