Add metadata-as-JSON support to dwarfsck

This commit is contained in:
Marcus Holland-Moritz 2020-12-06 16:53:00 +01:00
parent a68657724a
commit 3f5c84a67a
5 changed files with 105 additions and 1 deletions

View File

@ -33,6 +33,7 @@
#include <sys/types.h>
#include <folly/dynamic.h>
#include <folly/Expected.h>
#include "dwarfs/metadata_types.h"
@ -69,6 +70,10 @@ class filesystem_v2 {
impl_->dump(os, detail_level);
}
folly::dynamic metadata_as_dynamic() const {
return impl_->metadata_as_dynamic();
}
void walk(std::function<void(entry_view)> const& func) const {
impl_->walk(func);
}
@ -128,6 +133,7 @@ class filesystem_v2 {
virtual ~impl() = default;
virtual void dump(std::ostream& os, int detail_level) const = 0;
virtual folly::dynamic metadata_as_dynamic() const = 0;
virtual void walk(std::function<void(entry_view)> const& func) const = 0;
virtual std::optional<entry_view> find(const char* path) const = 0;
virtual std::optional<entry_view> find(int inode) const = 0;

View File

@ -34,6 +34,7 @@
#include <sys/types.h>
#include <folly/dynamic.h>
#include <folly/Expected.h>
#include <folly/Range.h>
@ -68,6 +69,10 @@ class metadata_v2 {
impl_->dump(os, detail_level, icb);
}
folly::dynamic as_dynamic() const {
return impl_->as_dynamic();
}
static void get_stat_defaults(struct ::stat* defaults);
// TODO: check if this is needed
@ -138,6 +143,8 @@ class metadata_v2 {
std::ostream& os, int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const = 0;
virtual folly::dynamic as_dynamic() const = 0;
virtual size_t size() const = 0;
virtual bool empty() const = 0;

View File

@ -195,6 +195,7 @@ class filesystem_ : public filesystem_v2::impl {
const struct ::stat* stat_defaults, int inode_offset);
void dump(std::ostream& os, int detail_level) const override;
folly::dynamic metadata_as_dynamic() const override;
void walk(std::function<void(entry_view)> const& func) const override;
std::optional<entry_view> find(const char* path) const override;
std::optional<entry_view> find(int inode) const override;
@ -273,6 +274,11 @@ void filesystem_<LoggerPolicy>::dump(std::ostream& os, int detail_level) const {
});
}
template <typename LoggerPolicy>
folly::dynamic filesystem_<LoggerPolicy>::metadata_as_dynamic() const {
return meta_.as_dynamic();
}
template <typename LoggerPolicy>
void filesystem_<LoggerPolicy>::walk(
std::function<void(entry_view)> const& func) const {

View File

@ -158,6 +158,8 @@ class metadata_ : public metadata_v2::impl {
std::function<void(const std::string&, uint32_t)> const& icb)
const override;
folly::dynamic as_dynamic() const override;
size_t size() const override { return data_.size(); }
bool empty() const override { return data_.empty(); }
@ -275,6 +277,9 @@ class metadata_ : public metadata_v2::impl {
int detail_level,
std::function<void(const std::string&, uint32_t)> const& icb) const;
folly::dynamic as_dynamic(entry_view entry) const;
folly::dynamic as_dynamic(directory_view dir) const;
std::optional<entry_view>
find(directory_view dir, std::string_view name) const;
@ -439,6 +444,76 @@ void metadata_<LoggerPolicy>::dump(
}
}
template <typename LoggerPolicy>
folly::dynamic metadata_<LoggerPolicy>::as_dynamic(directory_view dir) const {
folly::dynamic obj = folly::dynamic::array;
auto count = dir.entry_count();
auto first = dir.first_entry();
for (size_t i = 0; i < count; ++i) {
obj.push_back(as_dynamic(make_entry_view(first + i)));
}
return obj;
}
template <typename LoggerPolicy>
folly::dynamic metadata_<LoggerPolicy>::as_dynamic(entry_view entry) const {
folly::dynamic obj = folly::dynamic::object;
auto mode = entry.mode();
auto inode = entry.inode();
obj["mode"] = mode;
obj["modestring"] = modestring(mode);
obj["inode"] = inode;
if (inode > 0) {
obj["name"] = std::string(entry.name());
}
if (S_ISREG(mode)) {
obj["type"] = "file";
obj["size"] = file_size(entry, mode);
} else if (S_ISDIR(mode)) {
obj["type"] = "directory";
obj["entries"] = as_dynamic(make_directory_view(entry));
} else if (S_ISLNK(mode)) {
obj["type"] = "link";
obj["target"] = std::string(link_value(entry));
} else if (S_ISBLK(mode)) {
obj["type"] = "blockdev";
obj["device_id"] = get_device_id(inode);
} else if (S_ISCHR(mode)) {
obj["type"] = "chardev";
obj["device_id"] = get_device_id(inode);
} else if (S_ISFIFO(mode)) {
obj["type"] = "fifo";
} else if (S_ISSOCK(mode)) {
obj["type"] = "socket";
}
return obj;
}
template <typename LoggerPolicy>
folly::dynamic metadata_<LoggerPolicy>::as_dynamic() const {
folly::dynamic obj = folly::dynamic::object;
struct ::statvfs stbuf;
statvfs(&stbuf);
obj["statvfs"] = folly::dynamic::object
("f_bsize", stbuf.f_bsize)
("f_files", stbuf.f_files)
("f_blocks", stbuf.f_blocks);
obj["root"] = as_dynamic(root_);
return obj;
}
template <typename LoggerPolicy>
std::string metadata_<LoggerPolicy>::modestring(uint16_t mode) const {
std::ostringstream oss;

View File

@ -24,6 +24,7 @@
#include <boost/program_options.hpp>
#include <folly/json.h>
#include <folly/String.h>
#include "dwarfs/filesystem_v2.h"
@ -38,6 +39,7 @@ namespace po = boost::program_options;
int dwarfsck(int argc, char** argv) {
std::string log_level, input;
int detail;
bool json;
// clang-format off
po::options_description opts("Command line options");
@ -48,6 +50,9 @@ int dwarfsck(int argc, char** argv) {
("detail,d",
po::value<int>(&detail)->default_value(1),
"detail level")
("json",
po::value<bool>(&json)->zero_tokens(),
"print metadata in JSON format")
("log-level",
po::value<std::string>(&log_level)->default_value("info"),
"log level (error, warn, info, debug, trace)")
@ -74,7 +79,12 @@ int dwarfsck(int argc, char** argv) {
auto mm = std::make_shared<dwarfs::mmap>(input);
if (json) {
dwarfs::filesystem_v2 fs(lgr, mm);
std::cout << folly::toPrettyJson(fs.metadata_as_dynamic()) << std::endl;
} else {
dwarfs::filesystem_v2::identify(lgr, mm, std::cout, detail);
}
return 0;
}