fix(windows): hopefully fix path tweaking / canonicalization

This commit is contained in:
Marcus Holland-Moritz 2024-02-13 00:20:49 +01:00
parent 23bcf046ff
commit f5ac66503d
6 changed files with 64 additions and 34 deletions

View File

@ -21,6 +21,7 @@
#pragma once #pragma once
#include <filesystem>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <string> #include <string>
@ -44,7 +45,8 @@ class filesystem_extractor {
public: public:
filesystem_extractor(logger& lgr, os_access const& os); 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); return impl_->open_archive(output, format);
} }
@ -52,7 +54,9 @@ class filesystem_extractor {
return impl_->open_stream(os, format); 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(); } void close() { return impl_->close(); }
@ -66,10 +70,10 @@ class filesystem_extractor {
public: public:
virtual ~impl() = default; virtual ~impl() = default;
virtual void virtual void open_archive(std::filesystem::path const& output,
open_archive(std::string const& output, std::string const& format) = 0; std::string const& format) = 0;
virtual void open_stream(std::ostream& os, 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 void close() = 0;
virtual bool extract(filesystem_v2 const& fs, virtual bool extract(filesystem_v2 const& fs,
filesystem_extractor_options const& opts) = 0; filesystem_extractor_options const& opts) = 0;

View File

@ -104,13 +104,19 @@ class filesystem_extractor_ final : public filesystem_extractor::impl {
} }
} }
void void open_archive(std::filesystem::path const& output,
open_archive(std::string const& output, std::string const& format) override { std::string const& format) override {
a_ = ::archive_write_new(); a_ = ::archive_write_new();
check_result(::archive_write_set_format_by_name(a_, format.c_str())); 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( 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 { 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])); 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 (!output.empty()) {
if (::chdir(output.c_str()) != 0) { std::filesystem::current_path(output);
DWARFS_THROW(runtime_error,
output + ": " + std::string(strerror(errno)));
}
} }
a_ = ::archive_write_disk_new(); a_ = ::archive_write_disk_new();

View File

@ -305,15 +305,17 @@ void shorten_path_string(std::string& path, char separator, size_t max_len) {
} }
std::filesystem::path canonical_path(std::filesystem::path p) { std::filesystem::path canonical_path(std::filesystem::path p) {
if (!p.empty()) {
#ifdef _WIN32
p = std::filesystem::path(L"\\\\?\\" + p.wstring());
#endif
try { try {
p = std::filesystem::canonical(p); p = std::filesystem::canonical(p);
} catch (std::filesystem::filesystem_error const&) { } catch (std::filesystem::filesystem_error const&) {
p = std::filesystem::absolute(p); p = std::filesystem::absolute(p);
} }
}
#ifdef _WIN32
p = std::filesystem::path(L"\\\\?\\" + p.wstring());
#endif
return p; return p;
} }

View File

@ -90,6 +90,7 @@
#include "dwarfs/metadata_v2.h" #include "dwarfs/metadata_v2.h"
#include "dwarfs/mmap.h" #include "dwarfs/mmap.h"
#include "dwarfs/options.h" #include "dwarfs/options.h"
#include "dwarfs/os_access.h"
#include "dwarfs/performance_monitor.h" #include "dwarfs/performance_monitor.h"
#include "dwarfs/tool.h" #include "dwarfs/tool.h"
#include "dwarfs/util.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_getxattr)
PERFMON_EXT_TIMER_SETUP(userdata, op_listxattr) 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<char8_t const*>(opts.fsimage->data()))); reinterpret_cast<char8_t const*>(opts.fsimage->data())));
LOG_DEBUG << "attempting to load filesystem from " << fsimage;
userdata.fs = userdata.fs =
filesystem_v2(userdata.lgr, *userdata.iol.os, filesystem_v2(userdata.lgr, *userdata.iol.os,
std::make_shared<mmap>(fsimage), fsopts, userdata.perfmon); std::make_shared<mmap>(fsimage), fsopts, userdata.perfmon);

View File

@ -46,6 +46,7 @@
#include "dwarfs/mmap.h" #include "dwarfs/mmap.h"
#include "dwarfs/options.h" #include "dwarfs/options.h"
#include "dwarfs/os_access.h" #include "dwarfs/os_access.h"
#include "dwarfs/program_options_helpers.h"
#include "dwarfs/tool.h" #include "dwarfs/tool.h"
#include "dwarfs/util.h" #include "dwarfs/util.h"
#include "dwarfs/worker_group.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 (" + auto checksum_desc = "print checksums for all files (" +
(from(algo_list) | unsplit(", ")) + ")"; (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; logger_options logopts;
size_t num_workers; size_t num_workers;
int detail; int detail;
@ -178,7 +180,7 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) {
po::options_description opts("Command line options"); po::options_description opts("Command line options");
opts.add_options() opts.add_options()
("input,i", ("input,i",
po::value<std::string>(&input), po_sys_value<sys_string>(&input),
"input filesystem") "input filesystem")
("detail,d", ("detail,d",
po::value<int>(&detail)->default_value(2), po::value<int>(&detail)->default_value(2),
@ -214,7 +216,7 @@ int dwarfsck_main(int argc, sys_char** argv, iolayer const& iol) {
po::value<bool>(&output_json)->zero_tokens(), po::value<bool>(&output_json)->zero_tokens(),
"print information in JSON format") "print information in JSON format")
("export-metadata", ("export-metadata",
po::value<std::string>(&export_metadata), po_sys_value<sys_string>(&export_metadata),
"export raw metadata as JSON to file") "export raw metadata as JSON to file")
; ;
// clang-format on // 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.metadata.check_consistency = check_integrity;
fsopts.image_offset = parse_image_offset(image_offset); fsopts.image_offset = parse_image_offset(image_offset);
std::shared_ptr<mmif> mm = iol.os->map_file(input); auto input_path = iol.os->canonical(input);
std::shared_ptr<mmif> mm = iol.os->map_file(input_path);
if (print_header) { if (print_header) {
if (auto hdr = filesystem_v2::header(mm, fsopts.image_offset)) { 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()) { if (!export_metadata.empty()) {
std::error_code ec; 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) { if (ec) {
LOG_ERROR << "failed to open metadata output file: " << ec.message(); LOG_ERROR << "failed to open metadata output file: " << ec.message();
return 1; return 1;

View File

@ -22,6 +22,7 @@
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <string_view>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@ -37,6 +38,7 @@
#include "dwarfs/options.h" #include "dwarfs/options.h"
#include "dwarfs/os_access.h" #include "dwarfs/os_access.h"
#include "dwarfs/performance_monitor.h" #include "dwarfs/performance_monitor.h"
#include "dwarfs/program_options_helpers.h"
#include "dwarfs/tool.h" #include "dwarfs/tool.h"
#include "dwarfs/util.h" #include "dwarfs/util.h"
#include "dwarfs_tool_main.h" #include "dwarfs_tool_main.h"
@ -45,8 +47,19 @@ namespace po = boost::program_options;
namespace dwarfs { 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) { 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; logger_options logopts;
#if DWARFS_PERFMON_ENABLED #if DWARFS_PERFMON_ENABLED
std::string perfmon_str; 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"); po::options_description opts("Command line options");
opts.add_options() opts.add_options()
("input,i", ("input,i",
po::value<std::string>(&filesystem), po_sys_value<sys_string>(&filesystem),
"input filesystem file") "input filesystem file")
("output,o", ("output,o",
po::value<std::string>(&output), po_sys_value<sys_string>(&output),
"output file or directory") "output file or directory")
("image-offset,O", ("image-offset,O",
po::value<std::string>(&image_offset)->default_value("auto"), po::value<std::string>(&image_offset)->default_value("auto"),
@ -145,16 +158,17 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
std::shared_ptr<performance_monitor> perfmon = std::shared_ptr<performance_monitor> perfmon =
performance_monitor::create(perfmon_enabled); performance_monitor::create(perfmon_enabled);
filesystem_v2 fs(lgr, *iol.os, iol.os->map_file(filesystem), fsopts, auto fs_path = iol.os->canonical(filesystem);
perfmon);
filesystem_v2 fs(lgr, *iol.os, iol.os->map_file(fs_path), fsopts, perfmon);
filesystem_extractor fsx(lgr, *iol.os); filesystem_extractor fsx(lgr, *iol.os);
if (format.empty()) { if (format.empty()) {
fsx.open_disk(output); fsx.open_disk(iol.os->canonical(output));
} else { } else {
std::ostream* stream{nullptr}; std::ostream* stream{nullptr};
if (output.empty() or output == "-") { if (output.empty() or output == kDash) {
if (stdout_progress) { if (stdout_progress) {
DWARFS_THROW(runtime_error, DWARFS_THROW(runtime_error,
"cannot use --stdout-progress with --output=-"); "cannot use --stdout-progress with --output=-");
@ -170,7 +184,7 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
if (stream) { if (stream) {
fsx.open_stream(*stream, format); fsx.open_stream(*stream, format);
} else { } else {
fsx.open_archive(output, format); fsx.open_archive(iol.os->canonical(output), format);
} }
} }