| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <getopt.h> |
| #include <inttypes.h> |
| #include <stdio.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <sysexits.h> |
| #include <unistd.h> |
| |
| #include <string> |
| |
| #include <android-base/parseint.h> |
| #include <liblp/reader.h> |
| |
| using namespace android; |
| using namespace android::fs_mgr; |
| |
| static int usage(int /* argc */, char* argv[]) { |
| fprintf(stderr, |
| "%s - command-line tool for dumping Android Logical Partition images.\n" |
| "\n" |
| "Usage:\n" |
| " %s [-s,--slot] file-or-device\n" |
| "\n" |
| "Options:\n" |
| " -s, --slot=N Slot number or suffix.\n", |
| argv[0], argv[0]); |
| return EX_USAGE; |
| } |
| |
| static std::string BuildAttributeString(uint32_t attrs) { |
| return (attrs & LP_PARTITION_ATTR_READONLY) ? "readonly" : "none"; |
| } |
| |
| static bool IsBlockDevice(const char* file) { |
| struct stat s; |
| return !stat(file, &s) && S_ISBLK(s.st_mode); |
| } |
| |
| int main(int argc, char* argv[]) { |
| struct option options[] = { |
| { "slot", required_argument, nullptr, 's' }, |
| { "help", no_argument, nullptr, 'h' }, |
| { nullptr, 0, nullptr, 0 }, |
| }; |
| |
| int rv; |
| int index; |
| uint32_t slot = 0; |
| while ((rv = getopt_long_only(argc, argv, "s:h", options, &index)) != -1) { |
| switch (rv) { |
| case 'h': |
| return usage(argc, argv); |
| case 's': |
| if (!android::base::ParseUint(optarg, &slot)) { |
| slot = SlotNumberForSlotSuffix(optarg); |
| } |
| break; |
| } |
| } |
| |
| if (optind >= argc) { |
| return usage(argc, argv); |
| } |
| const char* file = argv[optind++]; |
| |
| std::unique_ptr<LpMetadata> pt; |
| if (IsBlockDevice(file)) { |
| pt = ReadMetadata(file, slot); |
| } else { |
| pt = ReadFromImageFile(file); |
| } |
| if (!pt) { |
| fprintf(stderr, "Failed to read metadata.\n"); |
| return EX_NOINPUT; |
| } |
| |
| printf("Metadata version: %u.%u\n", pt->header.major_version, pt->header.minor_version); |
| printf("Metadata size: %u bytes\n", pt->header.header_size + pt->header.tables_size); |
| printf("Metadata max size: %u bytes\n", pt->geometry.metadata_max_size); |
| printf("Metadata slot count: %u\n", pt->geometry.metadata_slot_count); |
| printf("First logical sector: %" PRIu64 "\n", pt->geometry.first_logical_sector); |
| printf("Last logical sector: %" PRIu64 "\n", pt->geometry.last_logical_sector); |
| printf("Partition table:\n"); |
| printf("------------------------\n"); |
| |
| for (const auto& partition : pt->partitions) { |
| std::string name = GetPartitionName(partition); |
| std::string guid = GetPartitionGuid(partition); |
| printf(" Name: %s\n", name.c_str()); |
| printf(" GUID: %s\n", guid.c_str()); |
| printf(" Attributes: %s\n", BuildAttributeString(partition.attributes).c_str()); |
| printf(" 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]; |
| printf(" %" PRIu64 " .. %" PRIu64 " ", first_sector, |
| (first_sector + extent.num_sectors - 1)); |
| first_sector += extent.num_sectors; |
| if (extent.target_type == LP_TARGET_TYPE_LINEAR) { |
| printf("linear %" PRIu64, extent.target_data); |
| } else if (extent.target_type == LP_TARGET_TYPE_ZERO) { |
| printf("zero"); |
| } |
| printf("\n"); |
| } |
| printf("------------------------\n"); |
| } |
| |
| return EX_OK; |
| } |