mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-10 04:50:31 -04:00
refactor(mkdwarfs): abstract out file creation
This commit is contained in:
parent
e8238c52f7
commit
b81242d6b6
@ -378,6 +378,7 @@ list(
|
|||||||
src/dwarfs/entry.cpp
|
src/dwarfs/entry.cpp
|
||||||
src/dwarfs/error.cpp
|
src/dwarfs/error.cpp
|
||||||
src/dwarfs/features.cpp
|
src/dwarfs/features.cpp
|
||||||
|
src/dwarfs/file_access_generic.cpp
|
||||||
src/dwarfs/file_scanner.cpp
|
src/dwarfs/file_scanner.cpp
|
||||||
src/dwarfs/file_stat.cpp
|
src/dwarfs/file_stat.cpp
|
||||||
src/dwarfs/file_type.cpp
|
src/dwarfs/file_type.cpp
|
||||||
|
49
include/dwarfs/file_access.h
Normal file
49
include/dwarfs/file_access.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/**
|
||||||
|
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||||
|
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||||
|
*
|
||||||
|
* This file is part of dwarfs.
|
||||||
|
*
|
||||||
|
* dwarfs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* dwarfs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <memory>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
namespace dwarfs {
|
||||||
|
|
||||||
|
class output_stream {
|
||||||
|
public:
|
||||||
|
virtual ~output_stream() = default;
|
||||||
|
|
||||||
|
virtual std::ostream& os() = 0;
|
||||||
|
virtual void close(std::error_code& ec) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class file_access {
|
||||||
|
public:
|
||||||
|
virtual ~file_access() = default;
|
||||||
|
|
||||||
|
virtual bool exists(std::filesystem::path const& path) const = 0;
|
||||||
|
virtual std::unique_ptr<output_stream>
|
||||||
|
open_output_binary(std::filesystem::path const& path,
|
||||||
|
std::error_code& ec) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dwarfs
|
32
include/dwarfs/file_access_generic.h
Normal file
32
include/dwarfs/file_access_generic.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/**
|
||||||
|
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||||
|
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||||
|
*
|
||||||
|
* This file is part of dwarfs.
|
||||||
|
*
|
||||||
|
* dwarfs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* dwarfs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace dwarfs {
|
||||||
|
|
||||||
|
class file_access;
|
||||||
|
|
||||||
|
std::unique_ptr<file_access const> create_file_access_generic();
|
||||||
|
|
||||||
|
} // namespace dwarfs
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
namespace dwarfs {
|
namespace dwarfs {
|
||||||
|
|
||||||
|
class file_access;
|
||||||
class os_access;
|
class os_access;
|
||||||
class terminal;
|
class terminal;
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ struct iolayer {
|
|||||||
|
|
||||||
std::shared_ptr<os_access const> os;
|
std::shared_ptr<os_access const> os;
|
||||||
std::shared_ptr<terminal const> term;
|
std::shared_ptr<terminal const> term;
|
||||||
|
std::shared_ptr<file_access const> file;
|
||||||
std::istream& in;
|
std::istream& in;
|
||||||
std::ostream& out;
|
std::ostream& out;
|
||||||
std::ostream& err;
|
std::ostream& err;
|
||||||
|
91
src/dwarfs/file_access_generic.cpp
Normal file
91
src/dwarfs/file_access_generic.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/**
|
||||||
|
* \author Marcus Holland-Moritz (github@mhxnet.de)
|
||||||
|
* \copyright Copyright (c) Marcus Holland-Moritz
|
||||||
|
*
|
||||||
|
* This file is part of dwarfs.
|
||||||
|
*
|
||||||
|
* dwarfs is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* dwarfs is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <folly/portability/Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dwarfs/file_access.h"
|
||||||
|
#include "dwarfs/file_access_generic.h"
|
||||||
|
#include "dwarfs/util.h"
|
||||||
|
|
||||||
|
namespace dwarfs {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void assign_error_code(std::error_code& ec) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
ec.assign(::GetLastError(), std::system_category());
|
||||||
|
#else
|
||||||
|
ec.assign(errno, std::generic_category());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
class file_output_stream : public output_stream {
|
||||||
|
public:
|
||||||
|
file_output_stream(std::filesystem::path const& path, std::error_code& ec)
|
||||||
|
: os_{path.string().c_str(), std::ios::binary | std::ios::trunc} {
|
||||||
|
if (os_.bad() || os_.fail() || !os_.is_open()) {
|
||||||
|
assign_error_code(ec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& os() override { return os_; }
|
||||||
|
|
||||||
|
void close(std::error_code& ec) override {
|
||||||
|
os_.close();
|
||||||
|
if (os_.bad()) {
|
||||||
|
assign_error_code(ec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ofstream os_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class file_access_generic : public file_access {
|
||||||
|
public:
|
||||||
|
bool exists(std::filesystem::path const& path) const override {
|
||||||
|
return std::filesystem::exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<output_stream>
|
||||||
|
open_output_binary(std::filesystem::path const& path,
|
||||||
|
std::error_code& ec) const override {
|
||||||
|
auto rv = std::make_unique<file_output_stream>(path, ec);
|
||||||
|
if (ec) {
|
||||||
|
rv.reset();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<file_access const> create_file_access_generic() {
|
||||||
|
return std::make_unique<file_access_generic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dwarfs
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "dwarfs/file_access.h"
|
||||||
|
#include "dwarfs/file_access_generic.h"
|
||||||
#include "dwarfs/iolayer.h"
|
#include "dwarfs/iolayer.h"
|
||||||
#include "dwarfs/os_access_generic.h"
|
#include "dwarfs/os_access_generic.h"
|
||||||
#include "dwarfs/terminal.h"
|
#include "dwarfs/terminal.h"
|
||||||
@ -31,6 +33,7 @@ iolayer const& iolayer::system_default() {
|
|||||||
static iolayer const iol{
|
static iolayer const iol{
|
||||||
.os = std::make_shared<os_access_generic>(),
|
.os = std::make_shared<os_access_generic>(),
|
||||||
.term = terminal::create(),
|
.term = terminal::create(),
|
||||||
|
.file = create_file_access_generic(),
|
||||||
.in = std::cin,
|
.in = std::cin,
|
||||||
.out = std::cout,
|
.out = std::cout,
|
||||||
.err = std::cerr,
|
.err = std::cerr,
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -63,6 +64,7 @@
|
|||||||
#include "dwarfs/console_writer.h"
|
#include "dwarfs/console_writer.h"
|
||||||
#include "dwarfs/entry.h"
|
#include "dwarfs/entry.h"
|
||||||
#include "dwarfs/error.h"
|
#include "dwarfs/error.h"
|
||||||
|
#include "dwarfs/file_access.h"
|
||||||
#include "dwarfs/filesystem_block_category_resolver.h"
|
#include "dwarfs/filesystem_block_category_resolver.h"
|
||||||
#include "dwarfs/filesystem_v2.h"
|
#include "dwarfs/filesystem_v2.h"
|
||||||
#include "dwarfs/filesystem_writer.h"
|
#include "dwarfs/filesystem_writer.h"
|
||||||
@ -74,6 +76,7 @@
|
|||||||
#include "dwarfs/mmap.h"
|
#include "dwarfs/mmap.h"
|
||||||
#include "dwarfs/options.h"
|
#include "dwarfs/options.h"
|
||||||
#include "dwarfs/options_interface.h"
|
#include "dwarfs/options_interface.h"
|
||||||
|
#include "dwarfs/overloaded.h"
|
||||||
#include "dwarfs/program_options_helpers.h"
|
#include "dwarfs/program_options_helpers.h"
|
||||||
#include "dwarfs/progress.h"
|
#include "dwarfs/progress.h"
|
||||||
#include "dwarfs/scanner.h"
|
#include "dwarfs/scanner.h"
|
||||||
@ -1035,33 +1038,37 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
|
|
||||||
std::filesystem::path output(output_str);
|
std::filesystem::path output(output_str);
|
||||||
|
|
||||||
std::unique_ptr<std::ostream> os;
|
std::variant<std::monostate, std::unique_ptr<output_stream>,
|
||||||
|
std::ostringstream>
|
||||||
|
os;
|
||||||
|
|
||||||
if (!options.debug_filter_function) {
|
if (!options.debug_filter_function) {
|
||||||
if (output != "-") {
|
if (output != "-") {
|
||||||
if (std::filesystem::exists(output) && !force_overwrite) {
|
if (iol.file->exists(output) && !force_overwrite) {
|
||||||
iol.err
|
iol.err
|
||||||
<< "error: output file already exists, use --force to overwrite\n";
|
<< "error: output file already exists, use --force to overwrite\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ofs = std::make_unique<std::ofstream>(output, std::ios::binary |
|
std::error_code ec;
|
||||||
std::ios::trunc);
|
auto stream = iol.file->open_output_binary(output, ec);
|
||||||
|
|
||||||
if (ofs->bad() || !ofs->is_open()) {
|
if (ec) {
|
||||||
iol.err << "error: cannot open output file '" << output
|
iol.err << "error: cannot open output file '" << output
|
||||||
<< "': " << ::strerror(errno) << "\n";
|
<< "': " << ec.message() << "\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
os = std::move(ofs);
|
assert(stream);
|
||||||
|
|
||||||
|
os.emplace<std::unique_ptr<output_stream>>(std::move(stream));
|
||||||
} else {
|
} else {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
::_setmode(::_fileno(stdout), _O_BINARY);
|
::_setmode(::_fileno(stdout), _O_BINARY);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
os = std::make_unique<std::ostringstream>();
|
os.emplace<std::ostringstream>();
|
||||||
}
|
}
|
||||||
|
|
||||||
options.enable_history = !no_history;
|
options.enable_history = !no_history;
|
||||||
@ -1173,9 +1180,18 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
std::unique_ptr<filesystem_writer> fsw;
|
std::unique_ptr<filesystem_writer> fsw;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
std::ostream& fsw_os = std::visit(
|
||||||
|
overloaded(
|
||||||
|
[&](std::monostate) -> std::ostream& { return iol.out; },
|
||||||
|
[&](std::unique_ptr<output_stream>& os) -> std::ostream& {
|
||||||
|
return os->os();
|
||||||
|
},
|
||||||
|
[&](std::ostringstream& oss) -> std::ostream& { return oss; }),
|
||||||
|
os);
|
||||||
|
|
||||||
fsw = std::make_unique<filesystem_writer>(
|
fsw = std::make_unique<filesystem_writer>(
|
||||||
os ? *os : iol.out, lgr, wg_compress, prog, schema_bc, metadata_bc,
|
fsw_os, lgr, wg_compress, prog, schema_bc, metadata_bc, history_bc,
|
||||||
history_bc, fswopts, header_ifs.get());
|
fswopts, header_ifs.get());
|
||||||
|
|
||||||
categorized_option<block_compressor> compression_opt;
|
categorized_option<block_compressor> compression_opt;
|
||||||
contextual_option_parser cop("--compression", compression_opt, cp,
|
contextual_option_parser cop("--compression", compression_opt, cp,
|
||||||
@ -1245,21 +1261,34 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
if (!options.debug_filter_function) {
|
if (!options.debug_filter_function) {
|
||||||
LOG_INFO << "compression CPU time: "
|
LOG_INFO << "compression CPU time: "
|
||||||
<< time_with_unit(wg_compress.get_cpu_time());
|
<< time_with_unit(wg_compress.get_cpu_time());
|
||||||
|
|
||||||
if (os) {
|
|
||||||
if (auto ofs = dynamic_cast<std::ofstream*>(os.get())) {
|
|
||||||
ofs->close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (os->bad()) {
|
{
|
||||||
|
auto ec = std::visit(
|
||||||
|
overloaded([](std::monostate) -> int { return 0; },
|
||||||
|
[&](std::unique_ptr<output_stream>& os) -> int {
|
||||||
|
std::error_code ec;
|
||||||
|
os->close(ec);
|
||||||
|
if (ec) {
|
||||||
LOG_ERROR << "failed to close output file '" << output
|
LOG_ERROR << "failed to close output file '" << output
|
||||||
<< "': " << strerror(errno);
|
<< "': " << ec.message();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
os.reset();
|
os.reset();
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
[](std::ostringstream& oss [[maybe_unused]]) -> int {
|
||||||
|
assert(oss.str().empty());
|
||||||
|
return 0;
|
||||||
|
}),
|
||||||
|
os);
|
||||||
|
|
||||||
|
if (ec != 0) {
|
||||||
|
return ec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.debug_filter_function) {
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
|
|
||||||
if (prog.errors) {
|
if (prog.errors) {
|
||||||
@ -1273,11 +1302,6 @@ int mkdwarfs_main(int argc, sys_char** argv, iolayer const& iol) {
|
|||||||
|
|
||||||
ti << "filesystem " << (recompress ? "rewritten " : "created ")
|
ti << "filesystem " << (recompress ? "rewritten " : "created ")
|
||||||
<< err.str();
|
<< err.str();
|
||||||
} else {
|
|
||||||
assert(os);
|
|
||||||
auto oss [[maybe_unused]] = dynamic_cast<std::ostringstream*>(os.get());
|
|
||||||
assert(oss);
|
|
||||||
assert(oss->str().empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return prog.errors > 0;
|
return prog.errors > 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user