cgpt_find.c revision 3f806a2abf07d7b801852a4a6f3a9080a4b5c427
1a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Use of this source code is governed by a BSD-style license that can be 3a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// found in the LICENSE file. 4a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 5a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <string.h> 6a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <sys/stat.h> 7a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include <sys/types.h> 8f47291926afce3235421f73811a04324195f3e13Bill Richardson#include <unistd.h> 9a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 10f47291926afce3235421f73811a04324195f3e13Bill Richardson#include "cgpt.h" 11a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#include "cgpt_params.h" 12f47291926afce3235421f73811a04324195f3e13Bill Richardson#include "cgptlib_internal.h" 13a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 14a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define BUFSIZE 1024 15a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// FIXME: currently we only support 512-byte sectors. 16a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define LBA_SIZE 512 17a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 18a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 19a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// fill comparebuf with the data to be examined, returning true on success. 20250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic int FillBuffer(CgptFindParams *params, int fd, uint64_t pos, 21a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan uint64_t count) { 22a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan uint8_t *bufptr = params->comparebuf; 23a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 24a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (-1 == lseek(fd, pos, SEEK_SET)) 25a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 26a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 27a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // keep reading until done or error 28a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan while (count) { 29a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan ssize_t bytes_read = read(fd, bufptr, count); 30a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // negative means error, 0 means (unexpected) EOF 31a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (bytes_read <= 0) 32a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 33a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan count -= bytes_read; 34a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan bufptr += bytes_read; 35a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 36a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 37a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 1; 38a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 39a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 40a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// check partition data content. return true for match, 0 for no match or error 41250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic int match_content(CgptFindParams *params, struct drive *drive, 42a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan GptEntry *entry) { 43a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan uint64_t part_size; 44a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 45a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!params->matchlen) 46a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 1; 47a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 48a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // Ensure that the region we want to match against is inside the partition. 49a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1); 50a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (params->matchoffset + params->matchlen > part_size) { 51a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 52a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 53a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 54a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // Read the partition data. 55a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!FillBuffer(params, 56a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan drive->fd, 57a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan (LBA_SIZE * entry->starting_lba) + params->matchoffset, 58a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan params->matchlen)) { 59a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan Error("unable to read partition data\n"); 60a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 61a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 62a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 63a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // Compare it 64a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (0 == memcmp(params->matchbuf, params->comparebuf, params->matchlen)) { 65a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 1; 66a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 67a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 68a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // Nope. 69a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 70a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 71a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 72a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3, /dev/sda -> /dev/sda3 73250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasanstatic void showmatch(CgptFindParams *params, char *filename, 74a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int partnum, GptEntry *entry) { 75a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char * format = "%s%d\n"; 76a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (strncmp("/dev/mmcblk", filename, 11) == 0) 77a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan format = "%sp%d\n"; 78a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (params->numeric) 79a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan printf("%d\n", partnum); 80a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan else 81a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan printf(format, filename, partnum); 82a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (params->verbose > 0) 83a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan EntryDetails(entry, partnum - 1, params->numeric); 84a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 85a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 86a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This returns true if a GPT partition matches the search criteria. If a match 87a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// isn't found (or if the file doesn't contain a GPT), it returns false. The 88a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// filename and partition number that matched is left in a global, since we 89a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// could have multiple hits. 90a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic int do_search(CgptFindParams *params, char *fileName) { 91a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int retval = 0; 92a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int i; 93a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan struct drive drive; 94a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan GptEntry *entry; 95a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char partlabel[GPT_PARTNAME_LEN]; 96a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 9723429d3d782f7506fb4747356974294cce08ac47Bill Richardson if (CGPT_OK != DriveOpen(fileName, &drive, O_RDONLY)) 98a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 99a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 100a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (GPT_SUCCESS != GptSanityCheck(&drive.gpt)) { 101a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan (void) DriveClose(&drive, 0); 102a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 103a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 104a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 105a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan for (i = 0; i < GetNumberOfEntries(&drive.gpt); ++i) { 106a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan entry = GetEntry(&drive.gpt, ANY_VALID, i); 107a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 1083f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardson if (GuidIsZero(&entry->type)) 109a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 110a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 111a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int found = 0; 112a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if ((params->set_unique && GuidEqual(¶ms->unique_guid, &entry->unique)) 113a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan || (params->set_type && GuidEqual(¶ms->type_guid, &entry->type))) { 114a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan found = 1; 115a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } else if (params->set_label) { 116a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (CGPT_OK != UTF16ToUTF8(entry->name, 117a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan sizeof(entry->name) / sizeof(entry->name[0]), 118a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan (uint8_t *)partlabel, sizeof(partlabel))) { 119a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan Error("The label cannot be converted from UTF16, so abort.\n"); 120a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 121a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 122a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!strncmp(params->label, partlabel, sizeof(partlabel))) 123a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan found = 1; 124a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 125a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (found && match_content(params, &drive, entry)) { 126a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan params->hits++; 127a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan retval++; 128a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan showmatch(params, fileName, i+1, entry); 129a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!params->match_partnum) 130a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan params->match_partnum = i+1; 131a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 132a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 133a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 134a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan (void) DriveClose(&drive, 0); 135a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 136a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return retval; 137a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 138a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 139a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 140a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define PROC_PARTITIONS "/proc/partitions" 141a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define DEV_DIR "/dev" 142a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan#define SYS_BLOCK_DIR "/sys/block" 143a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 144a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic const char *devdirs[] = { "/dev", "/devices", "/devfs", 0 }; 145a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 146a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// Given basename "foo", see if we can find a whole, real device by that name. 147a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This is copied from the logic in the linux utility 'findfs', although that 148a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// does more exhaustive searching. 149a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic char *is_wholedev(const char *basename) { 150a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int i; 151a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan struct stat statbuf; 152a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan static char pathname[BUFSIZE]; // we'll return this. 153a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char tmpname[BUFSIZE]; 154a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 155a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // It should be a block device under /dev/, 156a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan for (i = 0; devdirs[i]; i++) { 157a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan sprintf(pathname, "%s/%s", devdirs[i], basename); 158a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 159a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (0 != stat(pathname, &statbuf)) 160a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 161a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 162a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!S_ISBLK(statbuf.st_mode)) 163a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 164a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 165a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // It should have a symlink called /sys/block/*/device 166a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename); 167a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 168a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (0 != lstat(tmpname, &statbuf)) 169a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 170a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 171a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!S_ISLNK(statbuf.st_mode)) 172a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 173a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 174a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan // found it 175a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return pathname; 176a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 177a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 178a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return 0; 179a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 180a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 181a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 182a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// This scans all the physical devices it can find, looking for a match. It 183a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan// returns true if any matches were found, false otherwise. 184a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasanstatic int scan_real_devs(CgptFindParams *params) { 185a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int found = 0; 186a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char line[BUFSIZE]; 187a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char partname[128]; // max size for /proc/partition lines? 188a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan FILE *fp; 189a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan char *pathname; 190a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 191a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan fp = fopen(PROC_PARTITIONS, "r"); 192a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (!fp) { 193a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan perror("can't read " PROC_PARTITIONS); 194a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return found; 195a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 196a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 197a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan while (fgets(line, sizeof(line), fp)) { 198a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan int ma, mi; 199a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan long long unsigned int sz; 200a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 201a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4) 202a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan continue; 203a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 204a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if ((pathname = is_wholedev(partname))) { 205a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (do_search(params, pathname)) { 206a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan found++; 207a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 208a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 209a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan } 210a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 211a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan fclose(fp); 212a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return found; 213a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 214a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 215a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 2163f806a2abf07d7b801852a4a6f3a9080a4b5c427Bill Richardsonvoid CgptFind(CgptFindParams *params) { 217a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan if (params == NULL) 218a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan return; 219a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan 220250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan if (params->drive_name != NULL) 221250549d3e742cddaf72b4f53d5739e54faf5db96Jay Srinivasan do_search(params, params->drive_name); 222a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan else 223a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan scan_real_devs(params); 224a05814398202c4147a5e3f28474830ec0a9a0a90Jay Srinivasan} 225