]> git.proxmox.com Git - grub2.git/blame - util/grub-probe.c
* commands/parttool.c (grub_cmd_parttool): Fix #if !GRUB_NO_MODULES
[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>
22#include <grub/util/misc.h>
23#include <grub/device.h>
24#include <grub/disk.h>
2a9525e6 25#include <grub/file.h>
8b5f3938 26#include <grub/fs.h>
27#include <grub/partition.h>
71acf5e5 28#include <grub/msdos_partition.h>
ddbf5556 29#include <grub/util/hostdisk.h>
8b5f3938 30#include <grub/util/getroot.h>
9cacaa17 31#include <grub/term.h>
0bf6d401 32#include <grub/env.h>
f45d6cfc 33#include <grub/raid.h>
8a4c07fd 34#include <grub/i18n.h>
8b5f3938 35
daf0f0ba 36#include <grub_probe_init.h>
37
8b5f3938 38#include <stdio.h>
39#include <unistd.h>
40#include <string.h>
41#include <stdlib.h>
2a9525e6 42#include <sys/stat.h>
8b5f3938 43
44#define _GNU_SOURCE 1
45#include <getopt.h>
46
8a4c07fd
RM
47#include "progname.h"
48
1eb8c802 49enum {
50 PRINT_FS,
62191274 51 PRINT_FS_UUID,
1eb8c802 52 PRINT_DRIVE,
53 PRINT_DEVICE,
54 PRINT_PARTMAP,
55 PRINT_ABSTRACTION,
56};
ddd5cee9 57
58int print = PRINT_FS;
79ca2d78 59static unsigned int argument_is_device = 0;
ddd5cee9 60
8b5f3938 61void
62grub_putchar (int c)
63{
64 putchar (c);
65}
66
9cacaa17 67int
68grub_getkey (void)
69{
70 return -1;
71}
72
71b9f361 73struct grub_handler_class grub_term_input_class;
74struct grub_handler_class grub_term_output_class;
9cacaa17 75
8b5f3938 76void
77grub_refresh (void)
78{
6cf12cbd 79 fflush (stdout);
8b5f3938 80}
81
b92f0c18 82static void
83probe_partmap (grub_disk_t disk)
84{
15cb7d43
VS
85 grub_partition_t part;
86
b92f0c18 87 if (disk->partition == NULL)
88 {
70a14d3d 89 grub_util_info ("no partition map found for %s", disk->name);
b92f0c18 90 return;
91 }
b39f9d20 92
15cb7d43
VS
93 for (part = disk->partition; part; part = part->parent)
94 printf ("%s\n", part->partmap->name);
b92f0c18 95}
96
f45d6cfc 97static int
98probe_raid_level (grub_disk_t disk)
99{
917dd370
CW
100 /* disk might be NULL in the case of a LVM physical volume with no LVM
101 signature. Ignore such cases here. */
102 if (!disk)
103 return -1;
104
f45d6cfc 105 if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID)
106 return -1;
107
108 return ((struct grub_raid_array *) disk->data)->level;
109}
110
8b5f3938 111static void
79ca2d78 112probe (const char *path, char *device_name)
8b5f3938 113{
0215dcbf 114 char *drive_name = NULL;
2a9525e6 115 char *grub_path = NULL;
116 char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
2a9525e6 117 grub_device_t dev = NULL;
62191274 118 grub_fs_t fs;
b39f9d20 119
79ca2d78 120 if (path == NULL)
121 {
e0fc9e78 122#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
b1ac8644 123 if (! grub_util_check_char_device (device_name))
70a14d3d 124 grub_util_error ("%s is not a character device", device_name);
b1ac8644 125#else
79ca2d78 126 if (! grub_util_check_block_device (device_name))
70a14d3d 127 grub_util_error ("%s is not a block device", device_name);
b1ac8644 128#endif
79ca2d78 129 }
130 else
131 device_name = grub_guess_root_device (path);
132
8b5f3938 133 if (! device_name)
70a14d3d 134 grub_util_error ("cannot find a device for %s (is /dev mounted?)", path);
ddd5cee9 135
136 if (print == PRINT_DEVICE)
137 {
138 printf ("%s\n", device_name);
e0994b8b 139 goto end;
ddd5cee9 140 }
141
849d55d3 142 drive_name = grub_util_get_grub_dev (device_name);
143 if (! drive_name)
70a14d3d 144 grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name);
b39f9d20 145
ddd5cee9 146 if (print == PRINT_DRIVE)
147 {
148 printf ("(%s)\n", drive_name);
e0994b8b 149 goto end;
8b5f3938 150 }
151
e0994b8b 152 grub_util_info ("opening %s", drive_name);
153 dev = grub_device_open (drive_name);
8b5f3938 154 if (! dev)
155 grub_util_error ("%s", grub_errmsg);
156
f45d6cfc 157 if (print == PRINT_ABSTRACTION)
158 {
159 grub_disk_memberlist_t list = NULL, tmp;
160 const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID);
161 int is_raid = 0;
162 int is_raid5 = 0;
163 int is_raid6 = 0;
164 int raid_level;
165
166 raid_level = probe_raid_level (dev->disk);
167 if (raid_level >= 0)
168 {
169 is_raid = 1;
170 is_raid5 |= (raid_level == 5);
171 is_raid6 |= (raid_level == 6);
172 }
173
174 if ((is_lvm) && (dev->disk->dev->memberlist))
175 list = dev->disk->dev->memberlist (dev->disk);
176 while (list)
177 {
178 raid_level = probe_raid_level (list->disk);
179 if (raid_level >= 0)
180 {
181 is_raid = 1;
182 is_raid5 |= (raid_level == 5);
183 is_raid6 |= (raid_level == 6);
184 }
185
186 tmp = list->next;
187 free (list);
188 list = tmp;
189 }
190
191 if (is_raid)
192 {
193 printf ("raid ");
194 if (is_raid5)
195 printf ("raid5rec ");
196 if (is_raid6)
197 printf ("raid6rec ");
198 printf ("mdraid ");
199 }
200
201 if (is_lvm)
202 printf ("lvm ");
203
204 printf ("\n");
205
206 goto end;
207 }
208
75f396cc 209 if (print == PRINT_PARTMAP)
210 {
b92f0c18 211 grub_disk_memberlist_t list = NULL, tmp;
212
213 /* Check if dev->disk itself is contained in a partmap. */
214 probe_partmap (dev->disk);
215
216 /* In case of LVM/RAID, check the member devices as well. */
217 if (dev->disk->dev->memberlist)
218 list = dev->disk->dev->memberlist (dev->disk);
219 while (list)
220 {
221 probe_partmap (list->disk);
f45d6cfc 222 /* LVM on RAID */
223 if (list->disk->dev->memberlist)
224 {
225 grub_disk_memberlist_t sub_list;
226
227 sub_list = list->disk->dev->memberlist (list->disk);
228 while (sub_list)
229 {
230 probe_partmap (sub_list->disk);
231 tmp = sub_list->next;
232 free (sub_list);
233 sub_list = tmp;
234 }
235 }
b92f0c18 236 tmp = list->next;
237 free (list);
238 list = tmp;
239 }
75f396cc 240 goto end;
241 }
242
62191274 243 fs = grub_fs_probe (dev);
244 if (! fs)
245 grub_util_error ("%s", grub_errmsg);
246
2a9525e6 247 if (print == PRINT_FS)
248 {
dc9837ea
ST
249 if (path)
250 {
251 struct stat st;
8b5f3938 252
dc9837ea 253 stat (path, &st);
2a9525e6 254
dc9837ea
ST
255 if (S_ISREG (st.st_mode))
256 {
257 /* Regular file. Verify that we can read it properly. */
258
259 grub_file_t file;
260 char *rel_path;
261 grub_util_info ("reading %s via OS facilities", path);
262 filebuf_via_sys = grub_util_read_image (path);
263
264 rel_path = make_system_path_relative_to_its_root (path);
d6ceebf1 265 grub_path = xasprintf ("(%s)%s", drive_name, rel_path);
dc9837ea
ST
266 free (rel_path);
267 grub_util_info ("reading %s via GRUB facilities", grub_path);
268 file = grub_file_open (grub_path);
269 if (! file)
61ba42be 270 grub_util_error ("cannot open %s via GRUB facilities", grub_path);
dc9837ea
ST
271 filebuf_via_grub = xmalloc (file->size);
272 grub_file_read (file, filebuf_via_grub, file->size);
273
274 grub_util_info ("comparing");
275
276 if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size))
277 grub_util_error ("files differ");
278 }
2a9525e6 279 }
7f26d466 280
2a9525e6 281 printf ("%s\n", fs->name);
282 }
e0994b8b 283
62191274 284 if (print == PRINT_FS_UUID)
285 {
286 char *uuid;
287 if (! fs->uuid)
288 grub_util_error ("%s does not support UUIDs", fs->name);
289
290 fs->uuid (dev, &uuid);
291
292 printf ("%s\n", uuid);
293 }
294
e0994b8b 295 end:
2a9525e6 296 if (dev)
297 grub_device_close (dev);
298 free (grub_path);
299 free (filebuf_via_grub);
300 free (filebuf_via_sys);
e0994b8b 301 free (drive_name);
8b5f3938 302}
303
304static struct option options[] =
305 {
79ca2d78 306 {"device", no_argument, 0, 'd'},
8b5f3938 307 {"device-map", required_argument, 0, 'm'},
ddd5cee9 308 {"target", required_argument, 0, 't'},
8b5f3938 309 {"help", no_argument, 0, 'h'},
310 {"version", no_argument, 0, 'V'},
311 {"verbose", no_argument, 0, 'v'},
312 {0, 0, 0, 0}
313 };
314
315static void
316usage (int status)
317{
318 if (status)
319 fprintf (stderr,
70a14d3d 320 "Try `%s --help' for more information.\n", program_name);
8b5f3938 321 else
322 printf ("\
8a4c07fd 323Usage: %s [OPTION]... [PATH|DEVICE]\n\
8b5f3938 324\n\
79ca2d78 325Probe device information for a given path (or device, if the -d option is given).\n\
8b5f3938 326\n\
79ca2d78 327 -d, --device given argument is a system device, not a path\n\
8b5f3938 328 -m, --device-map=FILE use FILE as the device map [default=%s]\n\
62191274 329 -t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\
1eb8c802 330 print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
8b5f3938 331 -h, --help display this message and exit\n\
332 -V, --version print version information and exit\n\
333 -v, --verbose print verbose messages\n\
334\n\
335Report bugs to <%s>.\n\
8a4c07fd 336", program_name,
8b5f3938 337 DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
b39f9d20 338
8b5f3938 339 exit (status);
340}
341
342int
343main (int argc, char *argv[])
344{
345 char *dev_map = 0;
79ca2d78 346 char *argument;
b39f9d20 347
8a4c07fd 348 set_program_name (argv[0]);
2f1a3acf
YB
349
350 grub_util_init_nls ();
b39f9d20 351
8b5f3938 352 /* Check for options. */
353 while (1)
354 {
79ca2d78 355 int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
b39f9d20 356
8b5f3938 357 if (c == -1)
358 break;
359 else
360 switch (c)
361 {
79ca2d78 362 case 'd':
363 argument_is_device = 1;
364 break;
365
8b5f3938 366 case 'm':
367 if (dev_map)
368 free (dev_map);
369
370 dev_map = xstrdup (optarg);
371 break;
372
ddd5cee9 373 case 't':
374 if (!strcmp (optarg, "fs"))
375 print = PRINT_FS;
62191274 376 else if (!strcmp (optarg, "fs_uuid"))
377 print = PRINT_FS_UUID;
ddd5cee9 378 else if (!strcmp (optarg, "drive"))
379 print = PRINT_DRIVE;
380 else if (!strcmp (optarg, "device"))
381 print = PRINT_DEVICE;
75f396cc 382 else if (!strcmp (optarg, "partmap"))
383 print = PRINT_PARTMAP;
1eb8c802 384 else if (!strcmp (optarg, "abstraction"))
385 print = PRINT_ABSTRACTION;
ddd5cee9 386 else
387 usage (1);
388 break;
389
8b5f3938 390 case 'h':
391 usage (0);
392 break;
393
394 case 'V':
8a4c07fd 395 printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION);
8b5f3938 396 return 0;
397
398 case 'v':
399 verbosity++;
400 break;
401
402 default:
403 usage (1);
404 break;
405 }
406 }
407
91a4bf68 408 if (verbosity > 1)
409 grub_env_set ("debug", "all");
410
79ca2d78 411 /* Obtain ARGUMENT. */
8b5f3938 412 if (optind >= argc)
413 {
79ca2d78 414 fprintf (stderr, "No path or device is specified.\n");
8b5f3938 415 usage (1);
416 }
417
418 if (optind + 1 != argc)
419 {
420 fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
421 usage (1);
422 }
423
79ca2d78 424 argument = argv[optind];
b39f9d20 425
8b5f3938 426 /* Initialize the emulated biosdisk driver. */
427 grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
b39f9d20 428
daf0f0ba 429 /* Initialize all modules. */
430 grub_init_all ();
8b5f3938 431
432 /* Do it. */
79ca2d78 433 if (argument_is_device)
434 probe (NULL, argument);
435 else
436 probe (argument, NULL);
b39f9d20 437
8b5f3938 438 /* Free resources. */
daf0f0ba 439 grub_fini_all ();
8b5f3938 440 grub_util_biosdisk_fini ();
b39f9d20 441
8b5f3938 442 free (dev_map);
b39f9d20 443
8b5f3938 444 return 0;
445}