From 819547eceebcf850e7e7f6f14f467ea955b91bbd Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Tue, 19 Dec 2023 15:54:41 +0100 Subject: [PATCH] feat(dwarfsck): first part of dwarfsck json output --- include/dwarfs/filesystem_v2.h | 5 +++ include/dwarfs/history.h | 3 ++ include/dwarfs/metadata_v2.h | 6 ++++ src/dwarfs/filesystem_v2.cpp | 23 +++++++++++++- src/dwarfs/history.cpp | 58 ++++++++++++++++++++++++++++++++++ src/dwarfs/metadata_v2.cpp | 12 +++++++ src/dwarfsck_main.cpp | 9 ++++-- 7 files changed, 112 insertions(+), 4 deletions(-) diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index c82e2592..36b24b38 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -82,6 +82,10 @@ class filesystem_v2 { impl_->dump(os, detail_level); } + folly::dynamic info_as_dynamic(int detail_level) const { + return impl_->info_as_dynamic(detail_level); + } + folly::dynamic metadata_as_dynamic() const { return impl_->metadata_as_dynamic(); } @@ -191,6 +195,7 @@ class filesystem_v2 { virtual ~impl() = default; virtual void dump(std::ostream& os, int detail_level) const = 0; + virtual folly::dynamic info_as_dynamic(int detail_level) const = 0; virtual folly::dynamic metadata_as_dynamic() const = 0; virtual std::string serialize_metadata_as_json(bool simple) const = 0; virtual void diff --git a/include/dwarfs/history.h b/include/dwarfs/history.h index f2033974..5dec61fe 100644 --- a/include/dwarfs/history.h +++ b/include/dwarfs/history.h @@ -27,6 +27,8 @@ #include #include +#include + #include "dwarfs/options.h" #include "dwarfs/gen-cpp2/history_types.h" @@ -43,6 +45,7 @@ class history { void append(std::optional> args); std::vector serialize() const; void dump(std::ostream& os) const; + folly::dynamic as_dynamic() const; private: thrift::history::history history_; diff --git a/include/dwarfs/metadata_v2.h b/include/dwarfs/metadata_v2.h index 649f3468..5dc7cf00 100644 --- a/include/dwarfs/metadata_v2.h +++ b/include/dwarfs/metadata_v2.h @@ -66,6 +66,10 @@ class metadata_v2 { impl_->dump(os, detail_level, fsinfo, icb); } + folly::dynamic info_as_dynamic(int detail_level) const { + return impl_->info_as_dynamic(detail_level); + } + folly::dynamic as_dynamic() const { return impl_->as_dynamic(); } std::string serialize_as_json(bool simple) const { @@ -157,6 +161,8 @@ class metadata_v2 { std::ostream& os, int detail_level, filesystem_info const& fsinfo, std::function const& icb) const = 0; + virtual folly::dynamic info_as_dynamic(int detail_level) const = 0; + virtual folly::dynamic as_dynamic() const = 0; virtual std::string serialize_as_json(bool simple) const = 0; diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index 4c216e9d..b1da1c13 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -225,6 +225,10 @@ class filesystem_parser { return fmt::format("{0}.{1} [{2}]", major_, minor_, version_); } + int major_version() const { return major_; } + int minor_version() const { return minor_; } + int header_version() const { return version_; } + file_off_t image_offset() const { return image_offset_; } bool has_checksums() const { return version_ >= 2; } @@ -355,6 +359,7 @@ class filesystem_ final : public filesystem_v2::impl { std::shared_ptr perfmon); void dump(std::ostream& os, int detail_level) const override; + folly::dynamic info_as_dynamic(int detail_level) const override; folly::dynamic metadata_as_dynamic() const override; std::string serialize_metadata_as_json(bool simple) const override; void walk(std::function const& func) const override; @@ -503,7 +508,8 @@ filesystem_::filesystem_( PERFMON_CLS_TIMER_INIT(open) PERFMON_CLS_TIMER_INIT(read) PERFMON_CLS_TIMER_INIT(readv_iovec) - PERFMON_CLS_TIMER_INIT(readv_future) { // clang-format on + PERFMON_CLS_TIMER_INIT(readv_future) // clang-format on +{ block_cache cache(lgr, mm_, options.block_cache); if (parser_.has_index()) { @@ -730,6 +736,21 @@ void filesystem_::dump(std::ostream& os, int detail_level) const { }); } +template +folly::dynamic +filesystem_::info_as_dynamic(int detail_level) const { + folly::dynamic info = folly::dynamic::object; + + info["version"] = folly::dynamic::object("major", parser_.major_version())( + "minor", parser_.minor_version())("header", parser_.header_version()); + info["image_offset"] = parser_.image_offset(); + info["history"] = history_.as_dynamic(); + + info.update(meta_.info_as_dynamic(detail_level)); + + return info; +} + template folly::dynamic filesystem_::metadata_as_dynamic() const { return meta_.as_dynamic(); diff --git a/src/dwarfs/history.cpp b/src/dwarfs/history.cpp index 386c9691..0bf873d0 100644 --- a/src/dwarfs/history.cpp +++ b/src/dwarfs/history.cpp @@ -111,4 +111,62 @@ void history::dump(std::ostream& os) const { } } +folly::dynamic history::as_dynamic() const { + folly::dynamic dyn = folly::dynamic::array; + + for (auto const& histent : *history_.entries()) { + folly::dynamic entry = folly::dynamic::object; + + auto const& version = histent.version().value(); + + entry["libdwarfs_version"] = folly::dynamic::object + // clang-format off + ("major", version.major().value()) + ("minor", version.minor().value()) + ("patch", version.patch().value()) + ("is_release", version.is_release().value()) + // clang-format on + ; + + auto& version_dyn = entry["libdwarfs_version"]; + + if (version.git_rev().has_value()) { + version_dyn["git_rev"] = version.git_rev().value(); + } + + if (version.git_branch().has_value()) { + version_dyn["git_branch"] = version.git_branch().value(); + } + + if (version.git_desc().has_value()) { + version_dyn["git_desc"] = version.git_desc().value(); + } + + entry["system_id"] = histent.system_id().value(); + entry["compiler_id"] = histent.compiler_id().value(); + + if (histent.arguments().has_value()) { + folly::dynamic args = folly::dynamic::array; + for (auto const& arg : histent.arguments().value()) { + args.push_back(arg); + } + entry["arguments"] = std::move(args); + } + + if (histent.timestamp().has_value()) { + entry["timestamp"] = folly::dynamic::object + // clang-format off + ("epoch", histent.timestamp().value()) + ("local", fmt::format("{:%Y-%m-%dT%H:%M:%S}", + fmt::localtime(histent.timestamp().value()))) + // clang-format on + ; + } + + dyn.push_back(std::move(entry)); + } + + return dyn; +} + } // namespace dwarfs diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index 3536dbae..e794f254 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -413,6 +413,8 @@ class metadata_ final : public metadata_v2::impl { std::function const& icb) const override; + folly::dynamic info_as_dynamic(int detail_level) const override; + folly::dynamic as_dynamic() const override; std::string serialize_as_json(bool simple) const override; @@ -917,6 +919,16 @@ void metadata_::dump( } } +template +folly::dynamic +metadata_::info_as_dynamic(int detail_level) const { + folly::dynamic info = folly::dynamic::object; + if (detail_level > 2) { + info["metadata"] = as_dynamic(); + } + return info; +} + // TODO: can we move this to dir_entry_view? template void metadata_::dump( diff --git a/src/dwarfsck_main.cpp b/src/dwarfsck_main.cpp index 1da4212d..ebe68376 100644 --- a/src/dwarfsck_main.cpp +++ b/src/dwarfsck_main.cpp @@ -77,9 +77,12 @@ int dwarfsck_main(int argc, sys_char** argv) { ("check-integrity", po::value(&check_integrity)->zero_tokens(), "check integrity of each block") - ("json", + ("fast", + po::value(&check_integrity)->zero_tokens(), + "don't even verify block checksums") + ("json,j", po::value(&json)->zero_tokens(), - "print metadata in JSON format") + "print information in JSON format") ("export-metadata", po::value(&export_metadata), "export raw metadata as JSON to file") @@ -138,7 +141,7 @@ int dwarfsck_main(int argc, sys_char** argv) { of.close(); } else if (json) { filesystem_v2 fs(lgr, mm, fsopts); - std::cout << folly::toPrettyJson(fs.metadata_as_dynamic()) << "\n"; + std::cout << folly::toPrettyJson(fs.info_as_dynamic(detail)) << "\n"; } else if (print_header) { if (auto hdr = filesystem_v2::header(mm, fsopts.image_offset)) { #ifdef _WIN32