summaryrefslogtreecommitdiff
path: root/partition_tools
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2019-09-05 17:57:20 -0700
committerDavid Anderson <dvander@google.com>2019-09-05 18:55:53 -0700
commit674ae9ee88a487f18ec400add8c3d50a1db779e2 (patch)
treeb59efa389a0818eaa942139cf4cc37690cae1ca4 /partition_tools
parent3342738e82b07afeccf0bc9962ff047093335a1f (diff)
downloadextras-674ae9ee88a487f18ec400add8c3d50a1db779e2.tar.gz
lpdump: Refactor how lpdump reads metadata.
This patch prepares lpdump for the addition of an "--all" option to dump all metadata slots. - The slot and super partition name are now determined ahead of time, rather than as part of reading metadata. - The custom IPartitionOpener has been removed as it served no purpose. - The -e option has been removed in favor of IsEmptySuperImage(). - Metadata spew has been factored into a separate function. Bug: 140204341 Test: manual test Change-Id: I810a5f042870f7e072a8939bebe99b8707235f43
Diffstat (limited to 'partition_tools')
-rw-r--r--partition_tools/lpdump.cc181
1 files changed, 98 insertions, 83 deletions
diff --git a/partition_tools/lpdump.cc b/partition_tools/lpdump.cc
index 302e2840..26923edf 100644
--- a/partition_tools/lpdump.cc
+++ b/partition_tools/lpdump.cc
@@ -56,8 +56,6 @@ static int usage(int /* argc */, char* argv[], std::ostream& cerr) {
"Options:\n"
" -s, --slot=N Slot number or suffix.\n"
" -j, --json Print in JSON format.\n"
- " -e, --is-super-empty\n"
- " The given file is a super_empty.img.\n"
" -d, --dump-metadata-size\n"
" Print the space reserved for metadata to stdout\n"
" in bytes.\n";
@@ -88,11 +86,6 @@ static std::string BuildBlockDeviceFlagString(uint32_t flags) {
return BuildFlagString(strings);
}
-static bool IsBlockDevice(const char* file) {
- struct stat s;
- return !stat(file, &s) && S_ISBLK(s.st_mode);
-}
-
// Reimplementation of fs_mgr_get_slot_suffix() without reading
// kernel commandline.
static std::string GetSlotSuffix() {
@@ -101,7 +94,7 @@ static std::string GetSlotSuffix() {
// Reimplementation of fs_mgr_get_super_partition_name() without reading
// kernel commandline. Always return the super partition at current slot.
-static std::string GetSuperPartionName() {
+static std::string GetSuperPartitionName() {
std::string super_partition = base::GetProperty("ro.boot.super_partition", "");
if (super_partition.empty()) {
return LP_METADATA_DEFAULT_PARTITION_NAME;
@@ -253,8 +246,8 @@ static int PrintJson(const LpMetadata* metadata, std::ostream& cout,
return EX_OK;
}
-static int DumpMetadataSize(const LpMetadata* metadata, std::ostream& cout) {
- auto super_device = GetMetadataSuperBlockDevice(*metadata);
+static int DumpMetadataSize(const LpMetadata& metadata, std::ostream& cout) {
+ auto super_device = GetMetadataSuperBlockDevice(metadata);
uint64_t metadata_size = super_device->first_logical_sector * LP_SECTOR_SIZE;
cout << metadata_size << std::endl;
return EX_OK;
@@ -277,6 +270,69 @@ public:
}
};
+static void PrintMetadata(const LpMetadata& pt, std::ostream& cout) {
+ cout << "Metadata version: " << pt.header.major_version << "." << pt.header.minor_version
+ << "\n";
+ cout << "Metadata size: " << (pt.header.header_size + pt.header.tables_size) << " bytes\n";
+ cout << "Metadata max size: " << pt.geometry.metadata_max_size << " bytes\n";
+ cout << "Metadata slot count: " << pt.geometry.metadata_slot_count << "\n";
+ cout << "Partition table:\n";
+ cout << "------------------------\n";
+
+ for (const auto& partition : pt.partitions) {
+ std::string name = GetPartitionName(partition);
+ std::string group_name = GetPartitionGroupName(pt.groups[partition.group_index]);
+ cout << " Name: " << name << "\n";
+ cout << " Group: " << group_name << "\n";
+ cout << " Attributes: " << BuildAttributeString(partition.attributes) << "\n";
+ cout << " Extents:\n";
+ uint64_t first_sector = 0;
+ for (size_t i = 0; i < partition.num_extents; i++) {
+ const LpMetadataExtent& extent = pt.extents[partition.first_extent_index + i];
+ cout << " " << first_sector << " .. " << (first_sector + extent.num_sectors - 1)
+ << " ";
+ first_sector += extent.num_sectors;
+ if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
+ const auto& block_device = pt.block_devices[extent.target_source];
+ std::string device_name = GetBlockDevicePartitionName(block_device);
+ cout << "linear " << device_name.c_str() << " " << extent.target_data;
+ } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
+ cout << "zero";
+ }
+ cout << "\n";
+ }
+ cout << "------------------------\n";
+ }
+
+ cout << "Block device table:\n";
+ cout << "------------------------\n";
+ for (const auto& block_device : pt.block_devices) {
+ std::string partition_name = GetBlockDevicePartitionName(block_device);
+ cout << " Partition name: " << partition_name << "\n";
+ cout << " First sector: " << block_device.first_logical_sector << "\n";
+ cout << " Size: " << block_device.size << " bytes\n";
+ cout << " Flags: " << BuildBlockDeviceFlagString(block_device.flags) << "\n";
+ cout << "------------------------\n";
+ }
+
+ cout << "Group table:\n";
+ cout << "------------------------\n";
+ for (const auto& group : pt.groups) {
+ std::string group_name = GetPartitionGroupName(group);
+ cout << " Name: " << group_name << "\n";
+ cout << " Maximum size: " << group.maximum_size << " bytes\n";
+ cout << " Flags: " << BuildGroupFlagString(group.flags) << "\n";
+ cout << "------------------------\n";
+ }
+}
+
+static std::unique_ptr<LpMetadata> ReadDeviceOrFile(const std::string& path, uint32_t slot) {
+ if (IsEmptySuperImage(path)) {
+ return ReadFromImageFile(path);
+ }
+ return ReadMetadata(path, slot);
+}
+
int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) {
// clang-format off
struct option options[] = {
@@ -294,22 +350,25 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) {
int rv;
int index;
- uint32_t slot = 0;
bool json = false;
- bool is_empty = false;
bool dump_metadata_size = false;
+ std::optional<uint32_t> slot;
while ((rv = getopt_long_only(argc, argv, "s:jhde", options, &index)) != -1) {
switch (rv) {
case 'h':
usage(argc, argv, cerr);
return EX_OK;
- case 's':
- if (!android::base::ParseUint(optarg, &slot)) {
+ case 's': {
+ uint32_t slot_arg;
+ if (android::base::ParseUint(optarg, &slot_arg)) {
+ slot = slot_arg;
+ } else {
slot = SlotNumberForSlotSuffix(optarg);
}
break;
+ }
case 'e':
- is_empty = true;
+ // This is ignored, we now derive whether it's empty automatically.
break;
case 'd':
dump_metadata_size = true;
@@ -323,28 +382,34 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) {
}
}
- std::unique_ptr<LpMetadata> pt;
+#ifdef __ANDROID__
+ // Use the current slot as a default for A/B devices.
+ auto slot_suffix = GetSlotSuffix();
+ if (!slot.has_value() && !slot_suffix.empty()) {
+ slot = SlotNumberForSlotSuffix(slot_suffix);
+ }
+#endif
+
+ // If we still haven't determined a slot yet, use the first one.
+ if (!slot.has_value()) {
+ slot = 0;
+ }
+
+ // Determine the path to the super partition (or image).
+ std::string super_path;
if (optind < argc) {
- FileOrBlockDeviceOpener opener;
- const char* file = argv[optind++];
- if (!is_empty) {
- pt = ReadMetadata(opener, file, slot);
- }
- if (!pt && !IsBlockDevice(file)) {
- pt = ReadFromImageFile(file);
- }
+ super_path = argv[optind++];
} else {
#ifdef __ANDROID__
- if (is_empty) {
- return usage(argc, argv, cerr);
- }
- auto slot_number = SlotNumberForSlotSuffix(GetSlotSuffix());
- pt = ReadMetadata(GetSuperPartionName(), slot_number);
+ super_path = GetSuperPartitionName();
#else
+ cerr << "Must specify a super partition image.\n";
return usage(argc, argv, cerr);
#endif
}
+ auto pt = ReadDeviceOrFile(super_path, slot.value());
+
// --json option doesn't require metadata to be present.
if (json) {
return PrintJson(pt.get(), cout, cerr);
@@ -356,63 +421,13 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) {
}
if (dump_metadata_size) {
- return DumpMetadataSize(pt.get(), cout);
- }
-
- cout << "Metadata version: " << pt->header.major_version << "." << pt->header.minor_version
- << "\n";
- cout << "Metadata size: " << (pt->header.header_size + pt->header.tables_size) << " bytes\n";
- cout << "Metadata max size: " << pt->geometry.metadata_max_size << " bytes\n";
- cout << "Metadata slot count: " << pt->geometry.metadata_slot_count << "\n";
- cout << "Partition table:\n";
- cout << "------------------------\n";
-
- for (const auto& partition : pt->partitions) {
- std::string name = GetPartitionName(partition);
- std::string group_name = GetPartitionGroupName(pt->groups[partition.group_index]);
- cout << " Name: " << name << "\n";
- cout << " Group: " << group_name << "\n";
- cout << " Attributes: " << BuildAttributeString(partition.attributes) << "\n";
- cout << " Extents:\n";
- uint64_t first_sector = 0;
- for (size_t i = 0; i < partition.num_extents; i++) {
- const LpMetadataExtent& extent = pt->extents[partition.first_extent_index + i];
- cout << " " << first_sector << " .. " << (first_sector + extent.num_sectors - 1)
- << " ";
- first_sector += extent.num_sectors;
- if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
- const auto& block_device = pt->block_devices[extent.target_source];
- std::string device_name = GetBlockDevicePartitionName(block_device);
- cout << "linear " << device_name.c_str() << " " << extent.target_data;
- } else if (extent.target_type == LP_TARGET_TYPE_ZERO) {
- cout << "zero";
- }
- cout << "\n";
- }
- cout << "------------------------\n";
- }
-
- cout << "Block device table:\n";
- cout << "------------------------\n";
- for (const auto& block_device : pt->block_devices) {
- std::string partition_name = GetBlockDevicePartitionName(block_device);
- cout << " Partition name: " << partition_name << "\n";
- cout << " First sector: " << block_device.first_logical_sector << "\n";
- cout << " Size: " << block_device.size << " bytes\n";
- cout << " Flags: " << BuildBlockDeviceFlagString(block_device.flags) << "\n";
- cout << "------------------------\n";
+ return DumpMetadataSize(*pt.get(), cout);
}
- cout << "Group table:\n";
- cout << "------------------------\n";
- for (const auto& group : pt->groups) {
- std::string group_name = GetPartitionGroupName(group);
- cout << " Name: " << group_name << "\n";
- cout << " Maximum size: " << group.maximum_size << " bytes\n";
- cout << " Flags: " << BuildGroupFlagString(group.flags) << "\n";
- cout << "------------------------\n";
+ if (!IsEmptySuperImage(super_path)) {
+ cout << "Slot " << slot.value() << ":\n";
}
-
+ PrintMetadata(*pt.get(), cout);
return EX_OK;
}