mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
MTD search commands: show & find
BUG=chromium:221745 TEST=MTD version of run_cgpt_tests.sh passes BRANCH=none Change-Id: I8a5c1afab238eb10f38d865405ea2828715685d8 Original-Change-Id: I3d72fecbb3ef95252aa35d56885288340537b1c5 Reviewed-on: https://gerrit.chromium.org/gerrit/47175 Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Albert Chaulk <achaulk@chromium.org> Tested-by: Albert Chaulk <achaulk@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49794 Reviewed-by: Albert Chaulk <achaulk@chromium.org>
This commit is contained in:
113
cgpt/cgpt_find.c
113
cgpt/cgpt_find.c
@@ -83,27 +83,37 @@ static void showmatch(CgptFindParams *params, char *filename,
|
||||
EntryDetails(entry, partnum - 1, params->numeric);
|
||||
}
|
||||
|
||||
// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
|
||||
static void mtd_showmatch(CgptFindParams *params, char *filename,
|
||||
int partnum, MtdDiskPartition *entry) {
|
||||
char * format = "%s%d\n";
|
||||
if (strncmp("/dev/mmcblk", filename, 11) == 0)
|
||||
format = "%sp%d\n";
|
||||
if (params->numeric)
|
||||
printf("%d\n", partnum);
|
||||
else
|
||||
printf(format, filename, partnum);
|
||||
if (params->verbose > 0)
|
||||
MtdEntryDetails(entry, partnum - 1, params->numeric);
|
||||
}
|
||||
|
||||
// This returns true if a GPT partition matches the search criteria. If a match
|
||||
// isn't found (or if the file doesn't contain a GPT), it returns false. The
|
||||
// filename and partition number that matched is left in a global, since we
|
||||
// could have multiple hits.
|
||||
static int do_search(CgptFindParams *params, char *fileName) {
|
||||
int retval = 0;
|
||||
static int gpt_search(CgptFindParams *params, struct drive *drive,
|
||||
char *filename) {
|
||||
int i;
|
||||
struct drive drive;
|
||||
GptEntry *entry;
|
||||
int retval = 0;
|
||||
char partlabel[GPT_PARTNAME_LEN];
|
||||
|
||||
if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY))
|
||||
return 0;
|
||||
|
||||
if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
|
||||
(void) DriveClose(&drive, 0);
|
||||
if (GPT_SUCCESS != GptSanityCheck(&drive->gpt)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < GetNumberOfEntries(&drive); ++i) {
|
||||
entry = GetEntry(&drive.gpt, ANY_VALID, i);
|
||||
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||
entry = GetEntry(&drive->gpt, ANY_VALID, i);
|
||||
|
||||
if (GuidIsZero(&entry->type))
|
||||
continue;
|
||||
@@ -122,15 +132,94 @@ static int do_search(CgptFindParams *params, char *fileName) {
|
||||
if (!strncmp(params->label, partlabel, sizeof(partlabel)))
|
||||
found = 1;
|
||||
}
|
||||
if (found && match_content(params, &drive, entry)) {
|
||||
if (found && match_content(params, drive, entry)) {
|
||||
params->hits++;
|
||||
retval++;
|
||||
showmatch(params, fileName, i+1, entry);
|
||||
showmatch(params, filename, i+1, entry);
|
||||
if (!params->match_partnum)
|
||||
params->match_partnum = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int mtd_match_type_to_guid(const MtdDiskPartition *e, const Guid *guid) {
|
||||
return LookupMtdTypeForGuid(guid) == MtdGetEntryType(e);
|
||||
}
|
||||
|
||||
static int mtd_match_content(CgptFindParams *params, struct drive *drive,
|
||||
MtdDiskPartition *entry) {
|
||||
uint64_t part_size;
|
||||
|
||||
if (!params->matchlen)
|
||||
return 1;
|
||||
|
||||
// Ensure that the region we want to match against is inside the partition.
|
||||
part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
|
||||
if (params->matchoffset + params->matchlen > part_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the partition data.
|
||||
if (!FillBuffer(params,
|
||||
drive->fd,
|
||||
(LBA_SIZE * entry->starting_lba) + params->matchoffset,
|
||||
params->matchlen)) {
|
||||
Error("unable to read partition data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare it
|
||||
if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Nope.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtd_search(CgptFindParams *params, struct drive *drive,
|
||||
char *filename) {
|
||||
int i;
|
||||
int retval = 0;
|
||||
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||
MtdDiskPartition *e = MtdGetEntry(&drive->mtd, ANY_VALID, i);
|
||||
|
||||
if (IsUnused(drive, ANY_VALID, i))
|
||||
continue;
|
||||
|
||||
int found = 0;
|
||||
|
||||
// Only searches by type are possible right now
|
||||
if (params->set_type && mtd_match_type_to_guid(e, ¶ms->type_guid)) {
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if (found && mtd_match_content(params, drive, e)) {
|
||||
params->hits++;
|
||||
retval++;
|
||||
mtd_showmatch(params, filename, i+1, e);
|
||||
if (!params->match_partnum)
|
||||
params->match_partnum = i+1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int do_search(CgptFindParams *params, char *fileName) {
|
||||
int retval;
|
||||
struct drive drive;
|
||||
|
||||
if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY))
|
||||
return 0;
|
||||
|
||||
if (drive.is_mtd) {
|
||||
retval = mtd_search(params, &drive, fileName);
|
||||
} else {
|
||||
retval = gpt_search(params, &drive, fileName);
|
||||
}
|
||||
|
||||
(void) DriveClose(&drive, 0);
|
||||
|
||||
return retval;
|
||||
|
||||
235
cgpt/cgpt_show.c
235
cgpt/cgpt_show.c
@@ -49,22 +49,37 @@ static void RawDump(const uint8_t *memory, const int size,
|
||||
#define PARTITION_FMT "%12d%12d%8d %s\n"
|
||||
#define PARTITION_MORE "%12s%12s%8s %s%s\n", "", "", ""
|
||||
|
||||
static void HeaderDetails(GptHeader *header, GptEntry *entries,
|
||||
const char *indent, int raw) {
|
||||
int i;
|
||||
|
||||
void PrintSignature(const char *indent, const char *sig, size_t n, int raw) {
|
||||
size_t i;
|
||||
printf("%sSig: ", indent);
|
||||
if (!raw) {
|
||||
printf("[");
|
||||
for (i = 0; i < sizeof(header->signature); ++i)
|
||||
printf("%c", header->signature[i]);
|
||||
for (i = 0; i < n; ++i)
|
||||
printf("%c", sig[i]);
|
||||
printf("]");
|
||||
} else {
|
||||
char buf[BUFFER_SIZE(sizeof(header->signature))];
|
||||
RawDump((uint8_t *)header->signature, sizeof(header->signature), buf, 1);
|
||||
char *buf = malloc(BUFFER_SIZE(n));
|
||||
RawDump((uint8_t *)sig, n, buf, 1);
|
||||
printf("%s", buf);
|
||||
free(buf);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void MtdHeaderDetails(MtdDiskLayout *header, const char *indent, int raw) {
|
||||
PrintSignature(indent, (char*)header->signature, sizeof(header->signature),
|
||||
raw);
|
||||
|
||||
printf("%sSize: %d\n", indent, header->size);
|
||||
printf("%sCRC: 0x%08x %s\n", indent, header->crc32,
|
||||
(MtdHeaderCrc(header) != header->crc32) ? "(INVALID)" : "");
|
||||
printf("%sFirst LBA: %u\n", indent, header->first_lba);
|
||||
printf("%sLast LBA: %u\n", indent, header->last_lba);
|
||||
}
|
||||
|
||||
static void HeaderDetails(GptHeader *header, GptEntry *entries,
|
||||
const char *indent, int raw) {
|
||||
PrintSignature(indent, header->signature, sizeof(header->signature), raw);
|
||||
|
||||
printf("%sRev: 0x%08x\n", indent, header->revision);
|
||||
printf("%sSize: %d\n", indent, header->size);
|
||||
@@ -92,6 +107,26 @@ static void HeaderDetails(GptHeader *header, GptEntry *entries,
|
||||
);
|
||||
}
|
||||
|
||||
void MtdEntryDetails(MtdDiskPartition *entry, uint32_t index, int raw) {
|
||||
const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
|
||||
char buf[256]; // scratch buffer for formatting output
|
||||
if (guid) {
|
||||
ResolveType(guid, buf);
|
||||
} else {
|
||||
snprintf(buf, sizeof(buf), "MTD partition type %d", MtdGetEntryType(entry));
|
||||
}
|
||||
|
||||
if (!raw) {
|
||||
printf(PARTITION_FMT, (int)entry->starting_lba,
|
||||
(int)(entry->ending_lba - entry->starting_lba + 1),
|
||||
index+1, buf);
|
||||
} else {
|
||||
printf(PARTITION_FMT, (int)entry->starting_lba,
|
||||
(int)(entry->ending_lba - entry->starting_lba + 1),
|
||||
index+1, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
|
||||
char contents[256]; // scratch buffer for formatting output
|
||||
uint8_t label[GPT_PARTNAME_LEN];
|
||||
@@ -149,6 +184,17 @@ void EntryDetails(GptEntry *entry, uint32_t index, int raw) {
|
||||
}
|
||||
}
|
||||
|
||||
void MtdEntriesDetails(struct drive *drive, int secondary, int raw) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||
MtdDiskPartition *entry;
|
||||
entry = MtdGetEntry(&drive->mtd, secondary, i);
|
||||
if (IsUnused(drive, secondary, i))
|
||||
continue;
|
||||
MtdEntryDetails(entry, i, raw);
|
||||
}
|
||||
}
|
||||
|
||||
void EntriesDetails(struct drive *drive, const int secondary, int raw) {
|
||||
uint32_t i;
|
||||
@@ -200,17 +246,86 @@ done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
int CgptShow(CgptShowParams *params) {
|
||||
struct drive drive;
|
||||
int MtdShow(struct drive *drive, CgptShowParams *params) {
|
||||
if (params->partition) { // show single partition
|
||||
if (params->partition > GetNumberOfEntries(drive)) {
|
||||
Error("invalid partition number: %d\n", params->partition);
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
uint32_t index = params->partition - 1;
|
||||
MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, index);
|
||||
char buf[256]; // scratch buffer for string conversion
|
||||
const Guid *guid;
|
||||
|
||||
if (params->single_item) {
|
||||
switch(params->single_item) {
|
||||
case 'b':
|
||||
printf("%u\n", entry->starting_lba);
|
||||
break;
|
||||
case 's':
|
||||
printf("%u\n", entry->ending_lba - entry->starting_lba + 1);
|
||||
break;
|
||||
case 't':
|
||||
guid = LookupGuidForMtdType(MtdGetEntryType(entry));
|
||||
GuidToStr(guid, buf, sizeof(buf));
|
||||
printf("%s\n", buf);
|
||||
break;
|
||||
case 'S':
|
||||
printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'T':
|
||||
printf("%d\n", GetTries(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'P':
|
||||
printf("%d\n", GetPriority(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'A':
|
||||
printf("0x%x\n", entry->flags);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf(TITLE_FMT, "start", "size", "part", "contents");
|
||||
MtdEntryDetails(entry, index, params->numeric);
|
||||
}
|
||||
} else if (params->quick) { // show all partitions, quickly
|
||||
uint32_t i;
|
||||
char type[GUID_STRLEN];
|
||||
|
||||
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||
MtdDiskPartition *entry = MtdGetEntry(&drive->mtd, ANY_VALID, i);
|
||||
const Guid *guid = LookupGuidForMtdType(MtdGetEntryType(entry));
|
||||
|
||||
if (IsUnused(drive, ANY_VALID, i))
|
||||
continue;
|
||||
|
||||
if (!params->numeric && guid) {
|
||||
ResolveType(guid, type);
|
||||
} else {
|
||||
snprintf(type, sizeof(type), "MTD partition type %d",
|
||||
MtdGetEntryType(entry));
|
||||
}
|
||||
printf(PARTITION_FMT, (int)entry->starting_lba,
|
||||
(int)(entry->ending_lba - entry->starting_lba + 1),
|
||||
i+1, type);
|
||||
}
|
||||
} else { // show all partitions
|
||||
if (params->debug || params->verbose) {
|
||||
char indent[64];
|
||||
|
||||
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
|
||||
MtdHeaderDetails(&drive->mtd.primary, indent, 0);
|
||||
}
|
||||
|
||||
MtdEntriesDetails(drive, PRIMARY, params->numeric);
|
||||
}
|
||||
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
int GptShow(struct drive *drive, CgptShowParams *params) {
|
||||
int gpt_retval;
|
||||
|
||||
if (params == NULL)
|
||||
return CGPT_FAILED;
|
||||
|
||||
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
|
||||
return CGPT_FAILED;
|
||||
|
||||
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive.gpt))) {
|
||||
if (GPT_SUCCESS != (gpt_retval = GptSanityCheck(&drive->gpt))) {
|
||||
Error("GptSanityCheck() returned %d: %s\n",
|
||||
gpt_retval, GptError(gpt_retval));
|
||||
return CGPT_FAILED;
|
||||
@@ -218,13 +333,13 @@ int CgptShow(CgptShowParams *params) {
|
||||
|
||||
if (params->partition) { // show single partition
|
||||
|
||||
if (params->partition > GetNumberOfEntries(&drive)) {
|
||||
if (params->partition > GetNumberOfEntries(drive)) {
|
||||
Error("invalid partition number: %d\n", params->partition);
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
uint32_t index = params->partition - 1;
|
||||
GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
|
||||
GptEntry *entry = GetEntry(&drive->gpt, ANY_VALID, index);
|
||||
char buf[256]; // scratch buffer for string conversion
|
||||
|
||||
if (params->single_item) {
|
||||
@@ -254,13 +369,13 @@ int CgptShow(CgptShowParams *params) {
|
||||
printf("%s\n", buf);
|
||||
break;
|
||||
case 'S':
|
||||
printf("%d\n", GetSuccessful(&drive, ANY_VALID, index));
|
||||
printf("%d\n", GetSuccessful(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'T':
|
||||
printf("%d\n", GetTries(&drive, ANY_VALID, index));
|
||||
printf("%d\n", GetTries(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'P':
|
||||
printf("%d\n", GetPriority(&drive, ANY_VALID, index));
|
||||
printf("%d\n", GetPriority(drive, ANY_VALID, index));
|
||||
break;
|
||||
case 'A':
|
||||
printf("0x%x\n", entry->attrs.fields.gpt_att);
|
||||
@@ -276,8 +391,8 @@ int CgptShow(CgptShowParams *params) {
|
||||
GptEntry *entry;
|
||||
char type[GUID_STRLEN];
|
||||
|
||||
for (i = 0; i < GetNumberOfEntries(&drive); ++i) {
|
||||
entry = GetEntry(&drive.gpt, ANY_VALID, i);
|
||||
for (i = 0; i < GetNumberOfEntries(drive); ++i) {
|
||||
entry = GetEntry(&drive->gpt, ANY_VALID, i);
|
||||
|
||||
if (GuidIsZero(&entry->type))
|
||||
continue;
|
||||
@@ -293,17 +408,17 @@ int CgptShow(CgptShowParams *params) {
|
||||
} else { // show all partitions
|
||||
GptEntry *entries;
|
||||
|
||||
if (CGPT_OK != ReadPMBR(&drive)) {
|
||||
if (CGPT_OK != ReadPMBR(drive)) {
|
||||
Error("Unable to read PMBR\n");
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
printf(TITLE_FMT, "start", "size", "part", "contents");
|
||||
char buf[256]; // buffer for formatted PMBR content
|
||||
PMBRToStr(&drive.pmbr, buf, sizeof(buf)); // will exit if buf is too small
|
||||
PMBRToStr(&drive->pmbr, buf, sizeof(buf)); // will exit if buf is too small
|
||||
printf(GPT_FMT, 0, GPT_PMBR_SECTOR, "", buf);
|
||||
|
||||
if (drive.gpt.valid_headers & MASK_PRIMARY) {
|
||||
if (drive->gpt.valid_headers & MASK_PRIMARY) {
|
||||
printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
|
||||
(int)GPT_HEADER_SECTOR, "", "Pri GPT header");
|
||||
} else {
|
||||
@@ -312,30 +427,30 @@ int CgptShow(CgptShowParams *params) {
|
||||
}
|
||||
|
||||
if (params->debug ||
|
||||
((drive.gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
|
||||
((drive->gpt.valid_headers & MASK_PRIMARY) && params->verbose)) {
|
||||
GptHeader *header;
|
||||
char indent[64];
|
||||
|
||||
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
|
||||
header = (GptHeader*)drive.gpt.primary_header;
|
||||
entries = (GptEntry*)drive.gpt.primary_entries;
|
||||
header = (GptHeader*)drive->gpt.primary_header;
|
||||
entries = (GptEntry*)drive->gpt.primary_entries;
|
||||
HeaderDetails(header, entries, indent, params->numeric);
|
||||
}
|
||||
|
||||
printf(GPT_FMT, (int)(GPT_PMBR_SECTOR + GPT_HEADER_SECTOR),
|
||||
(int)GPT_ENTRIES_SECTORS,
|
||||
drive.gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
|
||||
drive->gpt.valid_entries & MASK_PRIMARY ? "" : "INVALID",
|
||||
"Pri GPT table");
|
||||
|
||||
if (params->debug ||
|
||||
(drive.gpt.valid_entries & MASK_PRIMARY))
|
||||
EntriesDetails(&drive, PRIMARY, params->numeric);
|
||||
(drive->gpt.valid_entries & MASK_PRIMARY))
|
||||
EntriesDetails(drive, PRIMARY, params->numeric);
|
||||
|
||||
/****************************** Secondary *************************/
|
||||
printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR -
|
||||
printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
|
||||
GPT_ENTRIES_SECTORS),
|
||||
(int)GPT_ENTRIES_SECTORS,
|
||||
drive.gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
|
||||
drive->gpt.valid_entries & MASK_SECONDARY ? "" : "INVALID",
|
||||
"Sec GPT table");
|
||||
/* We show secondary table details if any of following is true.
|
||||
* 1. in debug mode.
|
||||
@@ -343,15 +458,15 @@ int CgptShow(CgptShowParams *params) {
|
||||
* 3. secondary is not identical to promary.
|
||||
*/
|
||||
if (params->debug ||
|
||||
((drive.gpt.valid_entries & MASK_SECONDARY) &&
|
||||
(!(drive.gpt.valid_entries & MASK_PRIMARY) ||
|
||||
memcmp(drive.gpt.primary_entries, drive.gpt.secondary_entries,
|
||||
((drive->gpt.valid_entries & MASK_SECONDARY) &&
|
||||
(!(drive->gpt.valid_entries & MASK_PRIMARY) ||
|
||||
memcmp(drive->gpt.primary_entries, drive->gpt.secondary_entries,
|
||||
TOTAL_ENTRIES_SIZE)))) {
|
||||
EntriesDetails(&drive, SECONDARY, params->numeric);
|
||||
EntriesDetails(drive, SECONDARY, params->numeric);
|
||||
}
|
||||
|
||||
if (drive.gpt.valid_headers & MASK_SECONDARY)
|
||||
printf(GPT_FMT, (int)(drive.gpt.drive_sectors - GPT_HEADER_SECTOR),
|
||||
if (drive->gpt.valid_headers & MASK_SECONDARY)
|
||||
printf(GPT_FMT, (int)(drive->gpt.drive_sectors - GPT_HEADER_SECTOR),
|
||||
(int)GPT_HEADER_SECTOR, "", "Sec GPT header");
|
||||
else
|
||||
printf(GPT_FMT, (int)GPT_PMBR_SECTOR,
|
||||
@@ -362,23 +477,43 @@ int CgptShow(CgptShowParams *params) {
|
||||
* 3. secondary is not synonymous to primary.
|
||||
*/
|
||||
if (params->debug ||
|
||||
((drive.gpt.valid_headers & MASK_SECONDARY) &&
|
||||
(!(drive.gpt.valid_headers & MASK_PRIMARY) ||
|
||||
!IsSynonymous((GptHeader*)drive.gpt.primary_header,
|
||||
(GptHeader*)drive.gpt.secondary_header)) &&
|
||||
((drive->gpt.valid_headers & MASK_SECONDARY) &&
|
||||
(!(drive->gpt.valid_headers & MASK_PRIMARY) ||
|
||||
!IsSynonymous((GptHeader*)drive->gpt.primary_header,
|
||||
(GptHeader*)drive->gpt.secondary_header)) &&
|
||||
params->verbose)) {
|
||||
GptHeader *header;
|
||||
char indent[64];
|
||||
|
||||
require(snprintf(indent, sizeof(indent), GPT_MORE) < sizeof(indent));
|
||||
header = (GptHeader*)drive.gpt.secondary_header;
|
||||
entries = (GptEntry*)drive.gpt.secondary_entries;
|
||||
header = (GptHeader*)drive->gpt.secondary_header;
|
||||
entries = (GptEntry*)drive->gpt.secondary_entries;
|
||||
HeaderDetails(header, entries, indent, params->numeric);
|
||||
}
|
||||
}
|
||||
|
||||
CheckValid(&drive);
|
||||
DriveClose(&drive, 0);
|
||||
CheckValid(drive);
|
||||
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
int CgptShow(CgptShowParams *params) {
|
||||
struct drive drive;
|
||||
|
||||
if (params == NULL)
|
||||
return CGPT_FAILED;
|
||||
|
||||
if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY))
|
||||
return CGPT_FAILED;
|
||||
|
||||
if (drive.is_mtd) {
|
||||
if (MtdShow(&drive, params))
|
||||
return CGPT_FAILED;
|
||||
} else {
|
||||
if (GptShow(&drive, params))
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
DriveClose(&drive, 0);
|
||||
return CGPT_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user