]>
Commit | Line | Data |
---|---|---|
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 | 51 | enum { |
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 | |
62 | int print = PRINT_FS; | |
79ca2d78 | 63 | static unsigned int argument_is_device = 0; |
ddd5cee9 | 64 | |
b92f0c18 | 65 | static void |
66 | probe_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 |
93 | static void |
94 | probe_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 | 115 | static int |
116 | probe_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 |
129 | static void |
130 | probe_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 | 165 | static void |
79ca2d78 | 166 | probe (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 | ||
273 | static 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 | ||
284 | static void | |
285 | usage (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 | 292 | Usage: %s [OPTION]... [PATH|DEVICE]\n\ |
8b5f3938 | 293 | \n\ |
79ca2d78 | 294 | Probe 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\ | |
304 | Report bugs to <%s>.\n\ | |
8a4c07fd | 305 | ", program_name, |
8b5f3938 | 306 | DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); |
b39f9d20 | 307 | |
8b5f3938 | 308 | exit (status); |
309 | } | |
310 | ||
311 | int | |
312 | main (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 | } |