Merge "libsnapshot: Allow inspect_cow to show failed blocks"
diff --git a/fs_mgr/libsnapshot/inspect_cow.cpp b/fs_mgr/libsnapshot/inspect_cow.cpp
index 453b5c6..4a84fba 100644
--- a/fs_mgr/libsnapshot/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/inspect_cow.cpp
@@ -38,7 +38,8 @@
 static void usage(void) {
     LOG(ERROR) << "Usage: inspect_cow [-sd] <COW_FILE>";
     LOG(ERROR) << "\t -s Run Silent";
-    LOG(ERROR) << "\t -d Attempt to decompress\n";
+    LOG(ERROR) << "\t -d Attempt to decompress";
+    LOG(ERROR) << "\t -b Show data for failed decompress\n";
 }
 
 // Sink that always appends to the end of a string.
@@ -59,7 +60,25 @@
     std::string stream_;
 };
 
-static bool Inspect(const std::string& path, bool silent, bool decompress) {
+static void ShowBad(CowReader& reader, const struct CowOperation& op) {
+    size_t count;
+    auto buffer = std::make_unique<uint8_t[]>(op.data_length);
+
+    if (!reader.GetRawBytes(op.source, buffer.get(), op.data_length, &count)) {
+        std::cerr << "Failed to read at all!\n";
+    } else {
+        std::cout << "The Block data is:\n";
+        for (int i = 0; i < op.data_length; i++) {
+            std::cout << std::hex << (int)buffer[i];
+        }
+        std::cout << std::dec << "\n\n";
+        if (op.data_length >= sizeof(CowOperation)) {
+            std::cout << "The start, as an op, would be " << *(CowOperation*)buffer.get() << "\n";
+        }
+    }
+}
+
+static bool Inspect(const std::string& path, bool silent, bool decompress, bool show_bad) {
     android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
     if (fd < 0) {
         PLOG(ERROR) << "open failed: " << path;
@@ -107,6 +126,7 @@
             if (!reader.ReadData(op, &sink)) {
                 std::cerr << "Failed to decompress for :" << op << "\n";
                 success = false;
+                if (show_bad) ShowBad(reader, op);
             }
             sink.Reset();
         }
@@ -124,7 +144,8 @@
     int ch;
     bool silent = false;
     bool decompress = false;
-    while ((ch = getopt(argc, argv, "sd")) != -1) {
+    bool show_bad = false;
+    while ((ch = getopt(argc, argv, "sdb")) != -1) {
         switch (ch) {
             case 's':
                 silent = true;
@@ -132,6 +153,9 @@
             case 'd':
                 decompress = true;
                 break;
+            case 'b':
+                show_bad = true;
+                break;
             default:
                 android::snapshot::usage();
         }
@@ -143,7 +167,7 @@
         return 1;
     }
 
-    if (!android::snapshot::Inspect(argv[optind], silent, decompress)) {
+    if (!android::snapshot::Inspect(argv[optind], silent, decompress, show_bad)) {
         return 1;
     }
     return 0;