]> git.proxmox.com Git - grub2.git/blame - util/grub-probe.c
factor cryptodisk part out
[grub2.git] / util / grub-probe.c
CommitLineData
ddd5cee9 1/* grub-probe.c - probe device information for a given path */
8b5f3938 2/*
3 * GRUB -- GRand Unified Bootloader
2f1a3acf 4 * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
8b5f3938 5 *
5a79f472 6 * GRUB is free software: you can redistribute it and/or modify
8b5f3938 7 * it under the terms of the GNU General Public License as published by
5a79f472 8 * the Free Software Foundation, either version 3 of the License, or
8b5f3938 9 * (at your option) any later version.
10 *
5a79f472 11 * GRUB is distributed in the hope that it will be useful,
8b5f3938 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
5a79f472 17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
8b5f3938 18 */
19
20#include <config.h>
21#include <grub/types.h>
8c411768 22#include <grub/emu/misc.h>
8b5f3938 23#include <grub/util/misc.h>
8b5f3938 24#include <grub/util/misc.h>
25#include <grub/device.h>
26#include <grub/disk.h>
2a9525e6 27#include <grub/file.h>
8b5f3938 28#include <grub/fs.h>
29#include <grub/partition.h>
71acf5e5 30#include <grub/msdos_partition.h>
8c411768
BC
31#include <grub/emu/hostdisk.h>
32#include <grub/emu/getroot.h>
9cacaa17 33#include <grub/term.h>
0bf6d401 34#include <grub/env.h>
f45d6cfc 35#include <grub/raid.h>
8a4c07fd 36#include <grub/i18n.h>
50ad7d9c 37#include <grub/crypto.h>
8585e54b 38#include <grub/cryptodisk.h>
8b5f3938 39
40#include <stdio.h>
41#include <unistd.h>
42#include <string.h>
43#include <stdlib.h>
2a9525e6 44#include <sys/stat.h>
8b5f3938 45
46#define _GNU_SOURCE 1
47#include <getopt.h>
48
8a4c07fd
RM
49#include "progname.h"
50
1eb8c802 51enum {
52 PRINT_FS,
62191274 53 PRINT_FS_UUID,
0806b63c 54 PRINT_FS_LABEL,
1eb8c802 55 PRINT_DRIVE,
56 PRINT_DEVICE,
57 PRINT_PARTMAP,
58 PRINT_ABSTRACTION,
9d647e4e 59 PRINT_LUKS_UUID
1eb8c802 60};
ddd5cee9 61
62int print = PRINT_FS;
79ca2d78 63static unsigned int argument_is_device = 0;
ddd5cee9 64
b92f0c18 65static void
66probe_partmap (grub_disk_t disk)
67{
15cb7d43 68 grub_partition_t part;
50ad7d9c 69 grub_disk_memberlist_t list = NULL, tmp;
15cb7d43 70
b92f0c18 71 if (disk->partition == NULL)
72 {
70a14d3d 73 grub_util_info ("no partition map found for %s", disk->name);
b92f0c18 74 }
b39f9d20 75
15cb7d43 76 for (part = disk->partition; part; part = part->parent)
50ad7d9c
VS
77 printf ("%s ", part->partmap->name);
78
79 /* In case of LVM/RAID, check the member devices as well. */
80 if (disk->dev->memberlist)
81 {
82 list = disk->dev->memberlist (disk);
83 }
84 while (list)
85 {
86 probe_partmap (list->disk);
87 tmp = list->next;
88 free (list);
89 list = tmp;
90 }
b92f0c18 91}
92
9d647e4e
VS
93static void
94probe_luks_uuid (grub_disk_t disk)
95{
96 grub_disk_memberlist_t list = NULL, tmp;
97
98 /* In case of LVM/RAID, check the member devices as well. */
99 if (disk->dev->memberlist)
100 {
101 list = disk->dev->memberlist (disk);
102 }
103 while (list)
104 {
105 probe_luks_uuid (list->disk);
106 tmp = list->next;
107 free (list);
108 list = tmp;
109 }
8585e54b
VS
110 /* FIXME: support non-LUKS. */
111 if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
9d647e4e
VS
112 grub_util_luks_print_uuid (disk);
113}
114
f45d6cfc 115static int
116probe_raid_level (grub_disk_t disk)
117{
917dd370
CW
118 /* disk might be NULL in the case of a LVM physical volume with no LVM
119 signature. Ignore such cases here. */
120 if (!disk)
121 return -1;
122
f45d6cfc 123 if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID)
124 return -1;
125
126 return ((struct grub_raid_array *) disk->data)->level;
127}
128
50ad7d9c
VS
129static void
130probe_abstraction (grub_disk_t disk)
131{
132 grub_disk_memberlist_t list = NULL, tmp;
133 int raid_level;
134
135 if (disk->dev->memberlist)
136 list = disk->dev->memberlist (disk);
137 while (list)
138 {
139 probe_abstraction (list->disk);
140
141 tmp = list->next;
142 free (list);
143 list = tmp;
144 }
145
146 if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID)
147 printf ("lvm ");
148
8585e54b
VS
149 if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID)
150 grub_util_cryptodisk_print_abstraction (disk);
50ad7d9c
VS
151
152 raid_level = probe_raid_level (disk);
153 if (raid_level >= 0)
154 {
155 printf ("raid ");
156 if (disk->dev->raidname)
157 printf ("%s ", disk->dev->raidname (disk));
158 }
159 if (raid_level == 5)
160 printf ("raid5rec ");
161 if (raid_level == 6)
162 printf ("raid6rec ");
163}
164
8b5f3938 165static void
79ca2d78 166probe (const char *path, char *device_name)
8b5f3938 167{
0215dcbf 168 char *drive_name = NULL;
2a9525e6 169 char *grub_path = NULL;
170 char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
2a9525e6 171 grub_device_t dev = NULL;
62191274 172 grub_fs_t fs;
b39f9d20 173
79ca2d78 174 if (path == NULL)
175 {
e0fc9e78 176#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
b1ac8644 177 if (! grub_util_check_char_device (device_name))
70a14d3d 178 grub_util_error ("%s is not a character device", device_name);
b1ac8644 179#else
79ca2d78 180 if (! grub_util_check_block_device (device_name))
70a14d3d 181 grub_util_error ("%s is not a block device", device_name);
b1ac8644 182#endif
79ca2d78 183 }
184 else
185 device_name = grub_guess_root_device (path);
186
8b5f3938 187 if (! device_name)
70a14d3d 188 grub_util_error ("cannot find a device for %s (is /dev mounted?)", path);
ddd5cee9 189
190 if (print == PRINT_DEVICE)
191 {
192 printf ("%s\n", device_name);
e0994b8b 193 goto end;
ddd5cee9 194 }
195
849d55d3 196 drive_name = grub_util_get_grub_dev (device_name);
197 if (! drive_name)
70a14d3d 198 grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name);
b39f9d20 199
ddd5cee9 200 if (print == PRINT_DRIVE)
201 {
202 printf ("(%s)\n", drive_name);
e0994b8b 203 goto end;
8b5f3938 204 }
205
e0994b8b 206 grub_util_info ("opening %s", drive_name);
207 dev = grub_device_open (drive_name);
8b5f3938 208 if (! dev)
209 grub_util_error ("%s", grub_errmsg);
210
f45d6cfc 211 if (print == PRINT_ABSTRACTION)
212 {
50ad7d9c 213 probe_abstraction (dev->disk);
f45d6cfc 214 printf ("\n");
f45d6cfc 215 goto end;
216 }
217
9d647e4e
VS
218 if (print == PRINT_LUKS_UUID)
219 {
220 probe_luks_uuid (dev->disk);
221 printf ("\n");
222 goto end;
223 }
224
75f396cc 225 if (print == PRINT_PARTMAP)
226 {
b92f0c18 227 /* Check if dev->disk itself is contained in a partmap. */
228 probe_partmap (dev->disk);
50ad7d9c 229 printf ("\n");
75f396cc 230 goto end;
231 }
232
62191274 233 fs = grub_fs_probe (dev);
234 if (! fs)
235 grub_util_error ("%s", grub_errmsg);
236
2a9525e6 237 if (print == PRINT_FS)
238 {
2a9525e6 239 printf ("%s\n", fs->name);
240 }
92f2aef0 241 else if (print == PRINT_FS_UUID)
62191274 242 {
243 char *uuid;
244 if (! fs->uuid)
245 grub_util_error ("%s does not support UUIDs", fs->name);
246
7bf45fdd
RM
247 if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE)
248 grub_util_error ("%s", grub_errmsg);
62191274 249
250 printf ("%s\n", uuid);
251 }
0806b63c
RM
252 else if (print == PRINT_FS_LABEL)
253 {
254 char *label;
255 if (! fs->label)
256 grub_util_error ("%s does not support labels", fs->name);
257
7bf45fdd
RM
258 if (fs->label (dev, &label) != GRUB_ERR_NONE)
259 grub_util_error ("%s", grub_errmsg);
0806b63c
RM
260
261 printf ("%s\n", label);
262 }
62191274 263
e0994b8b 264 end:
2a9525e6 265 if (dev)
266 grub_device_close (dev);
267 free (grub_path);
268 free (filebuf_via_grub);
269 free (filebuf_via_sys);
e0994b8b 270 free (drive_name);
8b5f3938 271}
272
273static struct option options[] =
274 {
79ca2d78 275 {"device", no_argument, 0, 'd'},
8b5f3938 276 {"device-map", required_argument, 0, 'm'},
ddd5cee9 277 {"target", required_argument, 0, 't'},
8b5f3938 278 {"help", no_argument, 0, 'h'},
279 {"version", no_argument, 0, 'V'},
280 {"verbose", no_argument, 0, 'v'},
281 {0, 0, 0, 0}
282 };
283
284static void
285usage (int status)
286{
287 if (status)
288 fprintf (stderr,
70a14d3d 289 "Try `%s --help' for more information.\n", program_name);
8b5f3938 290 else
291 printf ("\
8a4c07fd 292Usage: %s [OPTION]... [PATH|DEVICE]\n\
8b5f3938 293\n\
79ca2d78 294Probe device information for a given path (or device, if the -d option is given).\n\
8b5f3938 295\n\
79ca2d78 296 -d, --device given argument is a system device, not a path\n\
8b5f3938 297 -m, --device-map=FILE use FILE as the device map [default=%s]\n\
9d647e4e
VS
298 -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|luks_uuid)\n\
299 print filesystem module, GRUB drive, system device, partition map module, abstraction module or LUKS UUID [default=fs]\n\
8b5f3938 300 -h, --help display this message and exit\n\
301 -V, --version print version information and exit\n\
302 -v, --verbose print verbose messages\n\
303\n\
304Report bugs to <%s>.\n\
8a4c07fd 305", program_name,
8b5f3938 306 DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
b39f9d20 307
8b5f3938 308 exit (status);
309}
310
311int
312main (int argc, char *argv[])
313{
314 char *dev_map = 0;
79ca2d78 315 char *argument;
b39f9d20 316
8a4c07fd 317 set_program_name (argv[0]);
2f1a3acf
YB
318
319 grub_util_init_nls ();
b39f9d20 320
8b5f3938 321 /* Check for options. */
322 while (1)
323 {
79ca2d78 324 int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
b39f9d20 325
8b5f3938 326 if (c == -1)
327 break;
328 else
329 switch (c)
330 {
79ca2d78 331 case 'd':
332 argument_is_device = 1;
333 break;
334
8b5f3938 335 case 'm':
336 if (dev_map)
337 free (dev_map);
338
339 dev_map = xstrdup (optarg);
340 break;
341
ddd5cee9 342 case 't':
343 if (!strcmp (optarg, "fs"))
344 print = PRINT_FS;
62191274 345 else if (!strcmp (optarg, "fs_uuid"))
346 print = PRINT_FS_UUID;
0806b63c
RM
347 else if (!strcmp (optarg, "fs_label"))
348 print = PRINT_FS_LABEL;
ddd5cee9 349 else if (!strcmp (optarg, "drive"))
350 print = PRINT_DRIVE;
351 else if (!strcmp (optarg, "device"))
352 print = PRINT_DEVICE;
75f396cc 353 else if (!strcmp (optarg, "partmap"))
354 print = PRINT_PARTMAP;
1eb8c802 355 else if (!strcmp (optarg, "abstraction"))
356 print = PRINT_ABSTRACTION;
9d647e4e
VS
357 else if (!strcmp (optarg, "luks_uuid"))
358 print = PRINT_LUKS_UUID;
ddd5cee9 359 else
360 usage (1);
361 break;
362
8b5f3938 363 case 'h':
364 usage (0);
365 break;
366
367 case 'V':
8a4c07fd 368 printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
8b5f3938 369 return 0;
370
371 case 'v':
372 verbosity++;
373 break;
374
375 default:
376 usage (1);
377 break;
378 }
379 }
380
91a4bf68 381 if (verbosity > 1)
382 grub_env_set ("debug", "all");
383
79ca2d78 384 /* Obtain ARGUMENT. */
8b5f3938 385 if (optind >= argc)
386 {
79ca2d78 387 fprintf (stderr, "No path or device is specified.\n");
8b5f3938 388 usage (1);
389 }
390
391 if (optind + 1 != argc)
392 {
393 fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
394 usage (1);
395 }
396
79ca2d78 397 argument = argv[optind];
b39f9d20 398
8b5f3938 399 /* Initialize the emulated biosdisk driver. */
400 grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
b39f9d20 401
daf0f0ba 402 /* Initialize all modules. */
403 grub_init_all ();
dcd73ec0 404 grub_gcry_init_all ();
8b5f3938 405
88b87c93 406 grub_lvm_fini ();
1e8d555b
VS
407 grub_mdraid09_fini ();
408 grub_mdraid1x_fini ();
88b87c93
VS
409 grub_raid_fini ();
410 grub_raid_init ();
1e8d555b
VS
411 grub_mdraid09_init ();
412 grub_mdraid1x_init ();
88b87c93
VS
413 grub_lvm_init ();
414
8b5f3938 415 /* Do it. */
79ca2d78 416 if (argument_is_device)
417 probe (NULL, argument);
418 else
419 probe (argument, NULL);
b39f9d20 420
8b5f3938 421 /* Free resources. */
dcd73ec0 422 grub_gcry_fini_all ();
daf0f0ba 423 grub_fini_all ();
8b5f3938 424 grub_util_biosdisk_fini ();
b39f9d20 425
8b5f3938 426 free (dev_map);
b39f9d20 427
8b5f3938 428 return 0;
429}