feat: allow disabling advanced features in dwarfs-fuse-extract

This commit is contained in:
Marcus Holland-Moritz 2025-04-13 22:14:57 +02:00
parent 3f82610e75
commit e6ae08475a
9 changed files with 75 additions and 7 deletions

View File

@ -171,6 +171,7 @@ case "-$BUILD_TYPE-" in
*-minimal-*)
CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_PERFMON=0 -DWITH_MAN_OPTION=0 -DENABLE_RICEPP=0"
CMAKE_ARGS="${CMAKE_ARGS} -DTRY_ENABLE_BROTLI=0 -DTRY_ENABLE_LZ4=0 -DTRY_ENABLE_FLAC=0"
CMAKE_ARGS="${CMAKE_ARGS} -DDWARFSEXTRACT_MINIMAL=1 -DDISABLE_FILESYSTEM_EXTRACTOR_FORMAT=1"
;;
esac

View File

@ -44,6 +44,8 @@ option(WITH_FUSE_EXTRACT_BINARY "build with fuse-extract binary" OFF)
option(WITH_PXATTR "build with pxattr binary" OFF)
option(WITH_EXAMPLE "build with example binary" OFF)
option(ENABLE_STACKTRACE "build with stack trace support" OFF)
option(DWARFSEXTRACT_MINIMAL "disable patterns support in dwarfsextract" OFF)
option(DISABLE_FILESYSTEM_EXTRACTOR_FORMAT "disable filesystem extractor format support" OFF)
if(APPLE)
option(USE_HOMEBREW_LIBARCHIVE "use libarchive from homebrew" ON)
endif()
@ -265,6 +267,7 @@ if(WITH_LIBDWARFS)
set(DWARFS_BUILTIN_MANPAGE ${WITH_MAN_OPTION})
set(DWARFS_PERFMON_ENABLED ${ENABLE_PERFMON})
set(DWARFS_STACKTRACE_ENABLED ${ENABLE_STACKTRACE})
set(DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT ${DISABLE_FILESYSTEM_EXTRACTOR_FORMAT})
configure_file(cmake/config.h.in include/dwarfs/config.h @ONLY)
else()
@ -297,6 +300,9 @@ if(WITH_TOOLS)
target_link_libraries(mkdwarfs_main PRIVATE dwarfs_reader dwarfs_writer dwarfs_rewrite)
target_link_libraries(dwarfsck_main PRIVATE dwarfs_reader)
target_link_libraries(dwarfsextract_main PRIVATE dwarfs_extractor)
target_compile_definitions(dwarfsextract_main PRIVATE
$<$<BOOL:${DWARFSEXTRACT_MINIMAL}>:DWARFSEXTRACT_MINIMAL>
)
if(WITH_UNIVERSAL_BINARY)
add_executable(dwarfsuniversal tools/src/universal.cpp)
@ -576,6 +582,9 @@ if(WITH_TESTS)
if(TARGET tool_main_test)
target_link_libraries(tool_main_test PRIVATE mkdwarfs_main dwarfsck_main dwarfsextract_main PkgConfig::LIBARCHIVE)
target_compile_definitions(tool_main_test PRIVATE
$<$<BOOL:${DWARFSEXTRACT_MINIMAL}>:DWARFSEXTRACT_MINIMAL>
)
endif()
if(TARGET manpage_test)
@ -587,6 +596,9 @@ if(WITH_TESTS)
target_compile_definitions(manpage_test PRIVATE DWARFS_WITH_FUSE_DRIVER)
target_link_libraries(manpage_test PRIVATE dwarfs_main)
endif()
target_compile_definitions(manpage_test PRIVATE
$<$<BOOL:${DWARFSEXTRACT_MINIMAL}>:DWARFSEXTRACT_MINIMAL>
)
endif()
if(TARGET tools_test)

View File

@ -11,4 +11,5 @@
#cmakedefine DWARFS_BUILTIN_MANPAGE 1
#cmakedefine DWARFS_PERFMON_ENABLED 1
#cmakedefine DWARFS_STACKTRACE_ENABLED 1
#cmakedefine DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT 1
// NOLINTEND(cppcoreguidelines-macro-to-enum)

View File

@ -47,6 +47,7 @@
#include <folly/portability/Unistd.h>
#include <folly/system/ThreadName.h>
#include <dwarfs/config.h>
#include <dwarfs/file_stat.h>
#include <dwarfs/fstypes.h>
#include <dwarfs/glob_matcher.h>
@ -121,8 +122,11 @@ class filesystem_extractor_ final : public filesystem_extractor::impl {
}
}
void open_archive(std::filesystem::path const& output,
std::string const& format) override {
void open_archive(std::filesystem::path const& output [[maybe_unused]],
std::string const& format [[maybe_unused]]) override {
#ifdef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
DWARFS_THROW(runtime_error, "open_archive() not supported in this build");
#else
LOG_DEBUG << "opening archive file in " << format << " format";
a_ = ::archive_write_new();
@ -136,10 +140,15 @@ class filesystem_extractor_ final : public filesystem_extractor::impl {
#else
check_result(::archive_write_open_filename(
a_, output.empty() ? nullptr : output.string().c_str()));
#endif
#endif
}
void open_stream(std::ostream& os, std::string const& format) override {
void open_stream(std::ostream& os [[maybe_unused]],
std::string const& format [[maybe_unused]]) override {
#ifdef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
DWARFS_THROW(runtime_error, "open_stream() not supported in this build");
#else
#ifdef _WIN32
if (::_pipe(pipefd_.data(), 8192, _O_BINARY) != 0) {
DWARFS_THROW(system_error, "_pipe()");
@ -160,6 +169,7 @@ class filesystem_extractor_ final : public filesystem_extractor::impl {
check_result(::archive_write_set_format_by_name(a_, format.c_str()));
check_result(::archive_write_set_bytes_in_last_block(a_, 1));
check_result(::archive_write_open_fd(a_, pipefd_[1]));
#endif
}
void open_disk(std::filesystem::path const& output) override {

View File

@ -39,6 +39,7 @@
#include <folly/String.h>
#include <dwarfs/block_compressor.h>
#include <dwarfs/config.h>
#include <dwarfs/file_stat.h>
#include <dwarfs/logger.h>
#include <dwarfs/mmap.h>
@ -869,7 +870,7 @@ void walk_tree(reader::filesystem_v2 const& fs, T& cb,
}
}
void check_compat(logger& lgr, reader::filesystem_v2 const& fs,
void check_compat(logger& lgr [[maybe_unused]], reader::filesystem_v2 const& fs,
std::string const& version, bool enable_nlink) {
bool const has_devices = not(version == "0.2.0" or version == "0.2.3");
bool const has_ac_time = version == "0.2.0" or version == "0.2.3";
@ -1079,6 +1080,7 @@ void check_compat(logger& lgr, reader::filesystem_v2 const& fs,
}
}
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
test::os_access_mock os;
utility::filesystem_extractor ext(lgr, os);
std::ostringstream oss;
@ -1111,6 +1113,7 @@ void check_compat(logger& lgr, reader::filesystem_v2 const& fs,
}
EXPECT_EQ(ref_entries.size(), mtree.size());
#endif
std::map<std::string, std::vector<std::string>> testdirs{
{"empty", {"empty/alsoempty"}},

View File

@ -35,6 +35,7 @@
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/map.hpp>
#include <dwarfs/config.h>
#include <dwarfs/tool/main_adapter.h>
#include <dwarfs/tool/pager.h>
#include <dwarfs/tool/render_manpage.h>
@ -190,6 +191,15 @@ TEST_P(manpage_coverage_test, options) {
}
}
if (tool_name == "dwarfsextract") {
#ifdef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
man_opts.erase("format");
#endif
#ifdef DWARFSEXTRACT_MINIMAL
man_opts.erase("pattern");
#endif
}
for (auto const& [opt, short_opt] : man_opts) {
auto it = help_opts.find(opt);
if (it == help_opts.end()) {

View File

@ -571,7 +571,8 @@ TEST_F(dwarfsextract_main_test, cmdline_help_arg) {
EXPECT_THAT(out(), ::testing::HasSubstr("Usage: dwarfsextract"));
}
#if DWARFS_PERFMON_ENABLED
#if DWARFS_PERFMON_ENABLED && \
!defined(DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT)
TEST(dwarfsextract_test, perfmon) {
auto t = dwarfsextract_tester::create_with_image();
ASSERT_EQ(0, t.run({"-i", "image.dwarfs", "-f", "mtree", "--perfmon",
@ -2148,6 +2149,7 @@ constexpr std::array const progress_modes{
INSTANTIATE_TEST_SUITE_P(dwarfs, mkdwarfs_progress_test,
::testing::ValuesIn(progress_modes));
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
TEST(dwarfsextract_test, mtree) {
auto t = dwarfsextract_tester::create_with_image();
ASSERT_EQ(0, t.run({"-i", "image.dwarfs", "-f", "mtree"})) << t.err();
@ -2157,6 +2159,7 @@ TEST(dwarfsextract_test, mtree) {
EXPECT_THAT(out, ::testing::HasSubstr("type=file"));
}
#ifndef DWARFSEXTRACT_MINIMAL
TEST(dwarfsextract_test, patterns) {
auto mkdt = mkdwarfs_tester::create_empty();
mkdt.add_test_file_tree();
@ -2187,6 +2190,7 @@ TEST(dwarfsextract_test, patterns) {
}
EXPECT_EQ(expected, actual);
}
#endif
TEST(dwarfsextract_test, stdout_progress_error) {
auto t = dwarfsextract_tester::create_with_image();
@ -2326,6 +2330,8 @@ TEST_P(dwarfsextract_format_test, basic) {
INSTANTIATE_TEST_SUITE_P(dwarfs, dwarfsextract_format_test,
::testing::ValuesIn(libarchive_formats));
#endif
TEST(dwarfsck_test, check_exclusive) {
auto t = dwarfsck_tester::create_with_image();
EXPECT_NE(0, t.run({"image.dwarfs", "--no-check", "--check-integrity"}))

View File

@ -1813,14 +1813,20 @@ INSTANTIATE_TEST_SUITE_P(
TEST(tools_test, dwarfsextract_progress) {
dwarfs::temporary_directory tempdir("dwarfs");
auto td = tempdir.path();
#ifdef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
auto out = subprocess::check_run(dwarfsextract_bin, "-i", test_catdata_dwarfs,
"-o", td.string(), "--stdout-progress");
EXPECT_TRUE(fs::exists(td / "pcmaudio" / "test12.aiff"));
#else
auto tarfile = td / "output.tar";
auto out =
subprocess::check_run(dwarfsextract_bin, "-i", test_catdata_dwarfs, "-o",
tarfile, "-f", "gnutar", "--stdout-progress");
ASSERT_TRUE(out);
EXPECT_TRUE(fs::exists(tarfile));
#endif
ASSERT_TRUE(out);
EXPECT_GT(out->size(), 100) << *out;
#ifdef _WIN32
EXPECT_THAT(*out, ::testing::EndsWith("100%\r\n"));
@ -1830,6 +1836,7 @@ TEST(tools_test, dwarfsextract_progress) {
#endif
}
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
TEST(tools_test, dwarfsextract_stdout) {
dwarfs::temporary_directory tempdir("dwarfs");
auto td = tempdir.path();
@ -1862,6 +1869,7 @@ TEST(tools_test, dwarfsextract_file_out) {
EXPECT_THAT(mtree, ::testing::StartsWith("#mtree\n"));
EXPECT_THAT(mtree, ::testing::HasSubstr("type=file"));
}
#endif
#ifdef _WIN32
TEST(tools_test, mkdwarfs_invalid_utf8_filename) {

View File

@ -57,18 +57,23 @@ namespace dwarfs::tool {
namespace {
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
#ifdef _WIN32
constexpr std::wstring_view kDash{L"-"};
#else
constexpr std::string_view kDash{"-"};
#endif
#endif
} // namespace
int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
sys_string fs_image, output, trace_file;
std::string format, cache_size_str, image_offset;
std::string cache_size_str, image_offset;
logger_options logopts;
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
std::string format;
#endif
#if DWARFS_PERFMON_ENABLED
std::string perfmon_str;
#endif
@ -85,15 +90,19 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
("output,o",
po_sys_value<sys_string>(&output),
"output file or directory")
#ifndef DWARFSEXTRACT_MINIMAL
("pattern",
po::value<std::vector<std::string>>(),
"only extract files matching these patterns")
#endif
("image-offset,O",
po::value<std::string>(&image_offset)->default_value("auto"),
"filesystem image offset in bytes")
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
("format,f",
po::value<std::string>(&format),
"output format")
#endif
("continue-on-error",
po::value<bool>(&continue_on_error)->zero_tokens(),
"continue if errors are encountered")
@ -123,7 +132,9 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
tool::add_common_options(opts, logopts);
po::positional_options_description pos;
#ifndef DWARFSEXTRACT_MINIMAL
pos.add("pattern", -1);
#endif
po::variables_map vm;
@ -161,10 +172,12 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
std::unique_ptr<glob_matcher> matcher;
#ifndef DWARFSEXTRACT_MINIMAL
if (vm.contains("pattern")) {
matcher = std::make_unique<glob_matcher>(
vm["pattern"].as<std::vector<std::string>>());
}
#endif
int rv = 0;
@ -194,8 +207,11 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
reader::filesystem_v2_lite fs(lgr, *iol.os, fs_image, fsopts, perfmon);
utility::filesystem_extractor fsx(lgr, *iol.os);
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
if (format.empty()) {
#endif
fsx.open_disk(iol.os->canonical(output));
#ifndef DWARFS_FILESYSTEM_EXTRACTOR_NO_OPEN_FORMAT
} else {
std::ostream* stream{nullptr};
@ -218,6 +234,7 @@ int dwarfsextract_main(int argc, sys_char** argv, iolayer const& iol) {
fsx.open_archive(iol.os->canonical(output), format);
}
}
#endif
utility::filesystem_extractor_options fsx_opts;