diff options
Diffstat (limited to '')
-rw-r--r-- | src/archive_manager.cc | 73 |
1 files changed, 51 insertions, 22 deletions
diff --git a/src/archive_manager.cc b/src/archive_manager.cc index 705842e..0f33cba 100644 --- a/src/archive_manager.cc +++ b/src/archive_manager.cc @@ -29,6 +29,8 @@ * @file archive_manager.cc */ +#include <future> + #include <unistd.h> #include "config.h" @@ -48,7 +50,7 @@ #include "base/lnav_log.hh" #include "base/paths.hh" #include "fmt/format.h" -#include "lnav_util.hh" +#include "hasher.hh" namespace fs = ghc::filesystem; @@ -72,10 +74,13 @@ enable_desired_archive_formats(archive* arc) } #endif -bool -is_archive(const fs::path& filename) +Result<describe_result, std::string> +describe(const fs::path& filename) { #if HAVE_ARCHIVE_H + static const auto RAW_FORMAT_NAME = string_fragment::from_const("raw"); + static const auto GZ_FILTER_NAME = string_fragment::from_const("gzip"); + auto_mem<archive> arc(archive_read_free); arc = archive_read_new(); @@ -94,39 +99,56 @@ is_archive(const fs::path& filename) if (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { log_debug("read next done %s", filename.c_str()); - static const auto RAW_FORMAT_NAME = string_fragment("raw"); - static const auto GZ_FILTER_NAME = string_fragment("gzip"); - format_name = archive_format_name(arc); - if (RAW_FORMAT_NAME == format_name) { auto filter_count = archive_filter_count(arc); if (filter_count == 1) { - return false; + return Ok(describe_result{unknown_file{}}); } const auto* first_filter_name = archive_filter_name(arc, 0); if (filter_count == 2 && GZ_FILTER_NAME == first_filter_name) { - return false; + return Ok(describe_result{unknown_file{}}); } } log_info( "detected archive: %s -- %s", filename.c_str(), format_name); - return true; + auto ai = archive_info{ + format_name, + }; + + do { + ai.ai_entries.emplace_back(archive_info::entry{ + archive_entry_pathname_utf8(entry), + archive_entry_strmode(entry), + archive_entry_mtime(entry), + archive_entry_size_is_set(entry) + ? nonstd::make_optional(archive_entry_size(entry)) + : nonstd::nullopt, + }); + } while (archive_read_next_header(arc, &entry) == ARCHIVE_OK); + + return Ok(describe_result{ai}); } - log_info("archive read header failed: %s -- %s", - filename.c_str(), - archive_error_string(arc)); + const auto* errstr = archive_error_string(arc); + log_info( + "archive read header failed: %s -- %s", filename.c_str(), errstr); + return Err( + fmt::format(FMT_STRING("unable to read archive header: {} -- {}"), + filename, + errstr ? errstr : "not an archive")); } else { - log_info("archive open failed: %s -- %s", - filename.c_str(), - archive_error_string(arc)); + const auto* errstr = archive_error_string(arc); + log_info("archive open failed: %s -- %s", filename.c_str(), errstr); + return Err(fmt::format(FMT_STRING("unable to open file: {} -- {}"), + filename, + errstr ? errstr : "unknown")); } #endif - return false; + return Ok(describe_result{unknown_file{}}); } static fs::path @@ -143,7 +165,7 @@ filename_to_tmp_path(const std::string& filename) hasher h; h.update(basename); - auto fd = auto_fd(lnav::filesystem::openp(filename, O_RDONLY)); + auto fd = auto_fd(lnav::filesystem::openp(filename, O_RDONLY | O_CLOEXEC)); if (fd != -1) { char buffer[1024]; int rc; @@ -226,9 +248,10 @@ extract(const std::string& filename, const extract_cb& cb) fs::create_directories(tmp_path.parent_path(), ec); if (ec) { - return Err(fmt::format("unable to create directory: {} -- {}", - tmp_path.parent_path().string(), - ec.message())); + return Err( + fmt::format(FMT_STRING("unable to create directory: {} -- {}"), + tmp_path.parent_path().string(), + ec.message())); } auto arc_lock = lnav::filesystem::file_lock(tmp_path); @@ -352,13 +375,19 @@ walk_archive_files( return result; } - for (const auto& entry : fs::recursive_directory_iterator(tmp_path)) { + std::error_code ec; + for (const auto& entry : fs::recursive_directory_iterator(tmp_path, ec)) { if (!entry.is_regular_file()) { continue; } callback(tmp_path, entry); } + if (ec) { + return Err(fmt::format(FMT_STRING("failed to walk temp dir: {} -- {}"), + tmp_path.string(), + ec.message())); + } return Ok(); #else |