1 /* grub-probe.c - probe device information for a given path */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
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.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/util/misc.h>
23 #include <grub/device.h>
24 #include <grub/disk.h>
25 #include <grub/file.h>
27 #include <grub/partition.h>
28 #include <grub/msdos_partition.h>
29 #include <grub/util/hostdisk.h>
30 #include <grub/util/getroot.h>
31 #include <grub/term.h>
33 #include <grub/raid.h>
35 #include <grub_probe_init.h>
56 static unsigned int argument_is_device
= 0;
70 struct grub_handler_class grub_term_input_class
;
71 struct grub_handler_class grub_term_output_class
;
80 probe_partmap (grub_disk_t disk
)
82 if (disk
->partition
== NULL
)
84 grub_util_info ("No partition map found for %s", disk
->name
);
88 printf ("%s\n", disk
->partition
->partmap
->name
);
92 probe_raid_level (grub_disk_t disk
)
94 if (disk
->dev
->id
!= GRUB_DISK_DEVICE_RAID_ID
)
97 return ((struct grub_raid_array
*) disk
->data
)->level
;
101 probe (const char *path
, char *device_name
)
103 char *drive_name
= NULL
;
104 char *grub_path
= NULL
;
105 char *filebuf_via_grub
= NULL
, *filebuf_via_sys
= NULL
;
106 grub_device_t dev
= NULL
;
111 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
112 if (! grub_util_check_char_device (device_name
))
113 grub_util_error ("%s is not a character device.\n", device_name
);
115 if (! grub_util_check_block_device (device_name
))
116 grub_util_error ("%s is not a block device.\n", device_name
);
120 device_name
= grub_guess_root_device (path
);
123 grub_util_error ("cannot find a device for %s.\n", path
);
125 if (print
== PRINT_DEVICE
)
127 printf ("%s\n", device_name
);
131 drive_name
= grub_util_get_grub_dev (device_name
);
133 grub_util_error ("Cannot find a GRUB drive for %s. Check your device.map.\n", device_name
);
135 if (print
== PRINT_DRIVE
)
137 printf ("(%s)\n", drive_name
);
141 grub_util_info ("opening %s", drive_name
);
142 dev
= grub_device_open (drive_name
);
144 grub_util_error ("%s", grub_errmsg
);
146 if (print
== PRINT_ABSTRACTION
)
148 grub_disk_memberlist_t list
= NULL
, tmp
;
149 const int is_lvm
= (dev
->disk
->dev
->id
== GRUB_DISK_DEVICE_LVM_ID
);
155 raid_level
= probe_raid_level (dev
->disk
);
159 is_raid5
|= (raid_level
== 5);
160 is_raid6
|= (raid_level
== 6);
163 if ((is_lvm
) && (dev
->disk
->dev
->memberlist
))
164 list
= dev
->disk
->dev
->memberlist (dev
->disk
);
167 raid_level
= probe_raid_level (list
->disk
);
171 is_raid5
|= (raid_level
== 5);
172 is_raid6
|= (raid_level
== 6);
184 printf ("raid5rec ");
186 printf ("raid6rec ");
198 if (print
== PRINT_PARTMAP
)
200 grub_disk_memberlist_t list
= NULL
, tmp
;
202 /* Check if dev->disk itself is contained in a partmap. */
203 probe_partmap (dev
->disk
);
205 /* In case of LVM/RAID, check the member devices as well. */
206 if (dev
->disk
->dev
->memberlist
)
207 list
= dev
->disk
->dev
->memberlist (dev
->disk
);
210 probe_partmap (list
->disk
);
212 if (list
->disk
->dev
->memberlist
)
214 grub_disk_memberlist_t sub_list
;
216 sub_list
= list
->disk
->dev
->memberlist (list
->disk
);
219 probe_partmap (sub_list
->disk
);
220 tmp
= sub_list
->next
;
232 fs
= grub_fs_probe (dev
);
234 grub_util_error ("%s", grub_errmsg
);
236 if (print
== PRINT_FS
)
238 /* FIXME: `path' can't be used to read a file via GRUB facilities,
239 because it's not relative to its root. */
245 if (S_ISREG (st
.st_mode
))
247 /* Regular file. Verify that we can read it properly. */
250 grub_util_info ("reading %s via OS facilities", path
);
251 filebuf_via_sys
= grub_util_read_image (path
);
253 grub_util_info ("reading %s via GRUB facilities", path
);
254 asprintf (&grub_path
, "(%s)%s", drive_name
, path
);
255 file
= grub_file_open (grub_path
);
256 filebuf_via_grub
= xmalloc (file
->size
);
257 grub_file_read (file
, filebuf_via_grub
, file
->size
);
259 grub_util_info ("comparing");
261 if (memcmp (filebuf_via_grub
, filebuf_via_sys
, file
->size
))
262 grub_util_error ("files differ");
266 printf ("%s\n", fs
->name
);
269 if (print
== PRINT_FS_UUID
)
273 grub_util_error ("%s does not support UUIDs", fs
->name
);
275 fs
->uuid (dev
, &uuid
);
277 printf ("%s\n", uuid
);
282 grub_device_close (dev
);
284 free (filebuf_via_grub
);
285 free (filebuf_via_sys
);
289 static struct option options
[] =
291 {"device", no_argument
, 0, 'd'},
292 {"device-map", required_argument
, 0, 'm'},
293 {"target", required_argument
, 0, 't'},
294 {"help", no_argument
, 0, 'h'},
295 {"version", no_argument
, 0, 'V'},
296 {"verbose", no_argument
, 0, 'v'},
305 "Try ``grub-probe --help'' for more information.\n");
308 Usage: grub-probe [OPTION]... [PATH|DEVICE]\n\
310 Probe device information for a given path (or device, if the -d option is given).\n\
312 -d, --device given argument is a system device, not a path\n\
313 -m, --device-map=FILE use FILE as the device map [default=%s]\n\
314 -t, --target=(fs|fs_uuid|drive|device|partmap|abstraction)\n\
315 print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\
316 -h, --help display this message and exit\n\
317 -V, --version print version information and exit\n\
318 -v, --verbose print verbose messages\n\
320 Report bugs to <%s>.\n\
322 DEFAULT_DEVICE_MAP
, PACKAGE_BUGREPORT
);
328 main (int argc
, char *argv
[])
333 progname
= "grub-probe";
335 /* Check for options. */
338 int c
= getopt_long (argc
, argv
, "dm:t:hVv", options
, 0);
346 argument_is_device
= 1;
353 dev_map
= xstrdup (optarg
);
357 if (!strcmp (optarg
, "fs"))
359 else if (!strcmp (optarg
, "fs_uuid"))
360 print
= PRINT_FS_UUID
;
361 else if (!strcmp (optarg
, "drive"))
363 else if (!strcmp (optarg
, "device"))
364 print
= PRINT_DEVICE
;
365 else if (!strcmp (optarg
, "partmap"))
366 print
= PRINT_PARTMAP
;
367 else if (!strcmp (optarg
, "abstraction"))
368 print
= PRINT_ABSTRACTION
;
378 printf ("%s (%s) %s\n", progname
, PACKAGE_NAME
, PACKAGE_VERSION
);
392 grub_env_set ("debug", "all");
394 /* Obtain ARGUMENT. */
397 fprintf (stderr
, "No path or device is specified.\n");
401 if (optind
+ 1 != argc
)
403 fprintf (stderr
, "Unknown extra argument `%s'.\n", argv
[optind
+ 1]);
407 argument
= argv
[optind
];
409 /* Initialize the emulated biosdisk driver. */
410 grub_util_biosdisk_init (dev_map
? : DEFAULT_DEVICE_MAP
);
412 /* Initialize all modules. */
416 if (argument_is_device
)
417 probe (NULL
, argument
);
419 probe (argument
, NULL
);
421 /* Free resources. */
423 grub_util_biosdisk_fini ();