Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17421a93 authored by David Anderson's avatar David Anderson
Browse files

inspect_cow: Add --show_raw_ops.

This bypasses CowReader and shows ops directly from CowParserV2. This
will come in handy once CowOperation is versioned and CowReader will be
translating from older versions to new versions.

Bug: 280529365
Test: inspect_cow
Change-Id: Icaeba86105c31c4dfe2812309a4028dd1d0248c0
parent 691b78a0
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <android-base/unique_fd.h>
#include <gflags/gflags.h>
#include <libsnapshot/cow_reader.h>
#include "parser_v2.h"

DEFINE_bool(silent, false, "Run silently");
DEFINE_bool(decompress, false, "Attempt to decompress data ops");
@@ -36,10 +37,13 @@ DEFINE_bool(show_merged, false,
            "If show_ops is true, and order is merge or reverse-merge, include merged ops");
DEFINE_bool(verify_merge_sequence, false, "Verify merge order sequencing");
DEFINE_bool(show_merge_sequence, false, "Show merge order sequence");
DEFINE_bool(show_raw_ops, false, "Show raw ops directly from the underlying parser");

namespace android {
namespace snapshot {

using android::base::borrowed_fd;

void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
              unsigned int, const char* message) {
    if (severity == android::base::ERROR) {
@@ -67,6 +71,38 @@ static void ShowBad(CowReader& reader, const struct CowOperation* op) {
    }
}

static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) {
    CowParserV2 parser;
    if (!parser.Parse(fd, header)) {
        LOG(ERROR) << "v2 parser failed";
        return false;
    }
    for (const auto& op : *parser.ops()) {
        std::cout << op << "\n";
        if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) {
            std::cout << "    data loc: " << iter->second << "\n";
        }
    }
    return true;
}

static bool ShowRawOpStream(borrowed_fd fd) {
    CowHeader header;
    if (!ReadCowHeader(fd, &header)) {
        LOG(ERROR) << "parse header failed";
        return false;
    }

    switch (header.prefix.major_version) {
        case 1:
        case 2:
            return ShowRawOpStreamV2(fd, header);
        default:
            LOG(ERROR) << "unknown COW version: " << header.prefix.major_version;
            return false;
    }
}

static bool Inspect(const std::string& path) {
    android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
    if (fd < 0) {
@@ -128,6 +164,21 @@ static bool Inspect(const std::string& path) {

    std::string buffer(header.block_size, '\0');

    if (!FLAGS_silent && FLAGS_show_raw_ops) {
        std::cout << "\n";
        std::cout << "Listing raw op stream:\n";
        std::cout << "----------------------\n";
        if (!ShowRawOpStream(fd)) {
            return false;
        }
    }

    if (!FLAGS_silent && FLAGS_show_ops) {
        std::cout << "\n";
        std::cout << "Listing op stream:\n";
        std::cout << "------------------\n";
    }

    bool success = true;
    uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0;
    while (!iter->AtEnd()) {