From 0e405ecb15f7be33a1b042aed3aafff5425d5649 Mon Sep 17 00:00:00 2001
From: Manali Bhutiyani <manalib@google.com>
Date: Mon, 13 May 2019 22:46:16 +0000
Subject: [PATCH] [minfs] disk-inspector Part 3: CmdLine/Uapp application to
 consume the disk-interface

This change implements a very simple command line tool/uapp application to consume the
disk objects for minfs and recursively iterate over all of them.
Please note that this is not interactive at the time being, but is implemented
as a first implementation of the disk-inspector tool. It is a good way to
test the different apis of the disk-inpector library.

Testing: The application itself is pretty dumb and doesn't need unit tests.
          The unit tests for minfs backend are already added as part of the change:
          https://fuchsia-review.googlesource.com/c/fuchsia/+/277175
Change-Id: Icd211c30bdb2c82c9f242447d8fddc5d7620c323
---
 zircon/system/uapp/BUILD.gn              |  1 +
 zircon/system/uapp/disk-inspect/BUILD.gn | 13 ++++
 zircon/system/uapp/disk-inspect/main.cpp | 98 ++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 zircon/system/uapp/disk-inspect/BUILD.gn
 create mode 100644 zircon/system/uapp/disk-inspect/main.cpp

diff --git a/zircon/system/uapp/BUILD.gn b/zircon/system/uapp/BUILD.gn
index 201716f53c1..6d0771b26f4 100644
--- a/zircon/system/uapp/BUILD.gn
+++ b/zircon/system/uapp/BUILD.gn
@@ -20,6 +20,7 @@ group("uapp") {
     "crasher",
     "dd",
     "df",
+    "disk-inspect",
     "disk-pave",
     "display-test",
     "dlog",
diff --git a/zircon/system/uapp/disk-inspect/BUILD.gn b/zircon/system/uapp/disk-inspect/BUILD.gn
new file mode 100644
index 00000000000..a63d2cdb187
--- /dev/null
+++ b/zircon/system/uapp/disk-inspect/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+executable("disk-inspect") {
+  sources = [
+    "main.cpp",
+  ]
+  deps = [
+    "$zx/system/ulib/disk-inspector",
+    "$zx/system/ulib/minfs",
+  ]
+}
diff --git a/zircon/system/uapp/disk-inspect/main.cpp b/zircon/system/uapp/disk-inspect/main.cpp
new file mode 100644
index 00000000000..b92daf2e751
--- /dev/null
+++ b/zircon/system/uapp/disk-inspect/main.cpp
@@ -0,0 +1,98 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <fbl/unique_fd.h>
+#include <lib/disk-inspector/disk-inspector.h>
+#include <minfs/inspector.h>
+#include <zircon/status.h>
+
+namespace {
+
+// Processes various disk objects recursively starting from root object
+// and prints values/elements of the objects.
+void ProcessDiskObjects(std::unique_ptr<disk_inspector::DiskObject> obj, uint32_t num_tabs) {
+    if (obj == nullptr) return;
+
+    printf("\n");
+    for (uint32_t i = 0; i < num_tabs; i++) {
+        printf("\t");
+    }
+
+    printf("Name: %s", obj->GetName());
+    size_t num_elements = obj->GetNumElements();
+
+    // Non scalar types.
+    if (num_elements != 0) {
+        for (uint32_t i = 0; i < num_elements; i++) {
+            std::unique_ptr<disk_inspector::DiskObject> element = obj->GetElementAt(i);
+            ProcessDiskObjects(std::move(element), num_tabs + 1);
+        }
+        return;
+    }
+
+    const void* buffer;
+    size_t size;
+    obj->GetValue(&buffer,&size);
+
+    switch (size) {
+        case sizeof(uint64_t): {
+            const uint64_t *val = reinterpret_cast <const uint64_t*> (buffer);
+            printf(" Value:0x%lx\n", *val);
+        }
+        break;
+
+        case sizeof(uint32_t): {
+            const uint32_t *val = reinterpret_cast <const uint32_t*> (buffer);
+            printf(" Value:0x%x\n", *val);
+        }
+        break;
+
+        case sizeof(uint16_t): {
+            const uint16_t *val = reinterpret_cast <const uint16_t*> (buffer);
+            printf(" Value:0x%x\n", *val);
+        }
+        break;
+
+        case sizeof(uint8_t): {
+            const char *val = reinterpret_cast <const char*> (buffer);
+            printf(" Value:%c\n", *val);
+        }
+        break;
+
+        default:
+            ZX_ASSERT_MSG(false, "Unknown object size: %lu", size);
+    }
+}
+
+int Inspect(fbl::unique_fd fd) {
+    minfs::Inspector inspector = minfs::Inspector(std::move(fd));
+    std::unique_ptr<disk_inspector::DiskObject> root;
+
+    if (inspector.GetRoot(&root) == ZX_OK) {
+         ProcessDiskObjects(std::move(root), 0);
+         printf("\n");
+         return 0;
+    }
+    fprintf(stderr, "ERROR: GetRoot failed\n");
+    return -1;
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+    if (argc < 2) {
+        fprintf(stderr, "usage: %s <device path>\n", argv[0]);
+        return -1;
+    }
+
+    fbl::unique_fd fd(open(argv[1], O_RDONLY));
+     if (fd.get() < 0) {
+        fprintf(stderr, "ERROR: Failed to open device: %d\n", fd.get());
+        return -1;
+    }
+    return Inspect(std::move(fd));
+}
-- 
GitLab