summaryrefslogtreecommitdiff
path: root/cgpt/cmd_find.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgpt/cmd_find.c')
-rw-r--r--cgpt/cmd_find.c283
1 files changed, 29 insertions, 254 deletions
diff --git a/cgpt/cmd_find.c b/cgpt/cmd_find.c
index 7a0523ff..9b945465 100644
--- a/cgpt/cmd_find.c
+++ b/cgpt/cmd_find.c
@@ -1,20 +1,13 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium OS 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 "cgpt.h"
#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-
-#include "cgptlib_internal.h"
+#include "cgpt_params.h"
static void Usage(void)
{
@@ -36,34 +29,6 @@ static void Usage(void)
PrintTypes();
}
-
-// globals
-static int verbose = 0;
-static int set_unique = 0;
-static int set_type = 0;
-static int set_label = 0;
-static int oneonly = 0;
-static int numeric = 0;
-static uint8_t *matchbuf = NULL;
-static uint64_t matchlen = 0;
-static uint64_t matchoffset = 0;
-static uint8_t *comparebuf = NULL;
-
-static Guid unique_guid;
-static Guid type_guid;
-static char *label;
-static int hits = 0;
-
-#define BUFSIZE 1024
-// FIXME: currently we only support 512-byte sectors.
-#define LBA_SIZE 512
-
-
-// remember one of the possibly many hits
-static int match_partnum = 0; // 0 for no match, 1-N for match
-static char match_filename[BUFSIZE]; // matching filename
-
-
// read a file into a buffer, return buffer and update size
static uint8_t *ReadFile(const char *filename, uint64_t *size) {
FILE *f;
@@ -94,203 +59,11 @@ static uint8_t *ReadFile(const char *filename, uint64_t *size) {
return buf;
}
-// fill comparebuf with the data to be examined, returning true on success.
-static int FillBuffer(int fd, uint64_t pos, uint64_t count) {
- uint8_t *bufptr = comparebuf;
-
- if (-1 == lseek(fd, pos, SEEK_SET))
- return 0;
-
- // keep reading until done or error
- while (count) {
- ssize_t bytes_read = read(fd, bufptr, count);
- // negative means error, 0 means (unexpected) EOF
- if (bytes_read <= 0)
- return 0;
- count -= bytes_read;
- bufptr += bytes_read;
- }
-
- return 1;
-}
-
-// check partition data content. return true for match, 0 for no match or error
-static int match_content(struct drive *drive, GptEntry *entry) {
- uint64_t part_size;
-
- if (!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 (matchoffset + matchlen > part_size) {
- return 0;
- }
-
- // Read the partition data.
- if (!FillBuffer(drive->fd,
- (LBA_SIZE * entry->starting_lba) + matchoffset,
- matchlen)) {
- Error("unable to read partition data\n");
- return 0;
- }
-
- // Compare it
- if (0 == memcmp(matchbuf, comparebuf, matchlen)) {
- return 1;
- }
-
- // Nope.
- return 0;
-}
-
-// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3
-static void showmatch(char *filename, int partnum, GptEntry *entry) {
- char * format = "%s%d\n";
- if (strncmp("/dev/mmcblk", filename, 11) == 0)
- format = "%sp%d\n";
- if (numeric)
- printf("%d\n", partnum);
- else
- printf(format, filename, partnum);
- if (verbose > 0)
- EntryDetails(entry, partnum - 1, 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(char *filename) {
- int retval = 0;
- int i;
- struct drive drive;
- GptEntry *entry;
- char partlabel[GPT_PARTNAME_LEN];
-
- if (CGPT_OK != DriveOpen(filename, &drive))
- return 0;
-
- if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) {
- (void) DriveClose(&drive, 0);
- return 0;
- }
-
- for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) {
- entry = GetEntry(&drive.gpt, ANY_VALID, i);
-
- if (IsZero(&entry->type))
- continue;
-
- int found = 0;
- if ((set_unique && GuidEqual(&unique_guid, &entry->unique)) ||
- (set_type && GuidEqual(&type_guid, &entry->type))) {
- found = 1;
- } else if (set_label) {
- if (CGPT_OK != UTF16ToUTF8(entry->name,
- sizeof(entry->name) / sizeof(entry->name[0]),
- (uint8_t *)partlabel, sizeof(partlabel))) {
- Error("The label cannot be converted from UTF16, so abort.\n");
- return 0;
- }
- if (!strncmp(label, partlabel, sizeof(partlabel))) {
- found = 1;
- }
- }
- if (found && match_content(&drive, entry)) {
- hits++;
- retval++;
- showmatch(filename, i+1, entry);
- if (!match_partnum) {
- match_partnum = i+1;
- strcpy(match_filename, filename);
- }
- }
- }
-
- (void) DriveClose(&drive, 0);
-
- return retval;
-}
-
-
-#define PROC_PARTITIONS "/proc/partitions"
-#define DEV_DIR "/dev"
-#define SYS_BLOCK_DIR "/sys/block"
-
-static const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 };
-
-// Given basename "foo", see if we can find a whole, real device by that name.
-// This is copied from the logic in the linux utility 'findfs', although that
-// does more exhaustive searching.
-static char *is_wholedev(const char *basename) {
- int i;
- struct stat statbuf;
- static char pathname[BUFSIZE]; // we'll return this.
- char tmpname[BUFSIZE];
-
- // It should be a block device under /dev/,
- for (i = 0; devdirs[i]; i++) {
- sprintf(pathname, "%s/%s", devdirs[i], basename);
-
- if (0 != stat(pathname, &statbuf))
- continue;
-
- if (!S_ISBLK(statbuf.st_mode))
- continue;
-
- // It should have a symlink called /sys/block/*/device
- sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
-
- if (0 != lstat(tmpname, &statbuf))
- continue;
-
- if (!S_ISLNK(statbuf.st_mode))
- continue;
-
- // found it
- return pathname;
- }
-
- return 0;
-}
-
-
-// This scans all the physical devices it can find, looking for a match. It
-// returns true if any matches were found, false otherwise.
-static int scan_real_devs(void) {
- int found = 0;
- char line[BUFSIZE];
- char partname[128]; // max size for /proc/partition lines?
- FILE *fp;
- char *pathname;
-
- fp = fopen(PROC_PARTITIONS, "r");
- if (!fp) {
- perror("can't read " PROC_PARTITIONS);
- return found;
- }
-
- while (fgets(line, sizeof(line), fp)) {
- int ma, mi;
- long long unsigned int sz;
-
- if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4)
- continue;
-
- if ((pathname = is_wholedev(partname))) {
- if (do_search(pathname)) {
- found++;
- }
- }
- }
-
- fclose(fp);
- return found;
-}
+int cmd_find(int argc, char *argv[]) {
+ CgptFindParams params;
+ memset(&params, 0, sizeof(params));
-int cmd_find(int argc, char *argv[]) {
int i;
int errorcnt = 0;
char *e = 0;
@@ -302,49 +75,49 @@ int cmd_find(int argc, char *argv[]) {
switch (c)
{
case 'v':
- verbose++;
+ params.verbose++;
break;
case 'n':
- numeric = 1;
+ params.numeric = 1;
break;
case '1':
- oneonly = 1;
+ params.oneonly = 1;
break;
case 'l':
- set_label = 1;
- label = optarg;
+ params.set_label = 1;
+ params.label = optarg;
break;
case 't':
- set_type = 1;
- if (CGPT_OK != SupportedType(optarg, &type_guid) &&
- CGPT_OK != StrToGuid(optarg, &type_guid)) {
+ params.set_type = 1;
+ if (CGPT_OK != SupportedType(optarg, &params.type_guid) &&
+ CGPT_OK != StrToGuid(optarg, &params.type_guid)) {
Error("invalid argument to -%c: %s\n", c, optarg);
errorcnt++;
}
break;
case 'u':
- set_unique = 1;
- if (CGPT_OK != StrToGuid(optarg, &unique_guid)) {
+ params.set_unique = 1;
+ if (CGPT_OK != StrToGuid(optarg, &params.unique_guid)) {
Error("invalid argument to -%c: %s\n", c, optarg);
errorcnt++;
}
break;
case 'M':
- matchbuf = ReadFile(optarg, &matchlen);
- if (!matchbuf || !matchlen) {
+ params.matchbuf = ReadFile(optarg, &params.matchlen);
+ if (!params.matchbuf || !params.matchlen) {
Error("Unable to read from %s\n", optarg);
errorcnt++;
}
// Go ahead and allocate space for the comparison too
- comparebuf = (uint8_t *)malloc(matchlen);
- if (!comparebuf) {
+ params.comparebuf = (uint8_t *)malloc(params.matchlen);
+ if (!params.comparebuf) {
Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
- matchlen);
+ params.matchlen);
errorcnt++;
}
break;
case 'O':
- matchoffset = strtoull(optarg, &e, 0);
+ params.matchoffset = strtoull(optarg, &e, 0);
if (!*optarg || (e && *e)) {
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
errorcnt++;
@@ -367,7 +140,7 @@ int cmd_find(int argc, char *argv[]) {
break;
}
}
- if (!set_unique && !set_type && !set_label) {
+ if (!params.set_unique && !params.set_type && !params.set_label) {
Error("You must specify at least one of -t, -u, or -l\n");
errorcnt++;
}
@@ -378,17 +151,19 @@ int cmd_find(int argc, char *argv[]) {
}
if (optind < argc) {
- for (i=optind; i<argc; i++)
- do_search(argv[i]);
+ for (i=optind; i<argc; i++) {
+ params.driveName = argv[i];
+ cgpt_find(&params);
+ }
} else {
- scan_real_devs();
+ cgpt_find(&params);
}
- if (oneonly && hits != 1) {
+ if (params.oneonly && params.hits != 1) {
return CGPT_FAILED;
}
- if (match_partnum) {
+ if (params.match_partnum) {
return CGPT_OK;
}