2009-11-01 Felix Zielcke <fzielcke@z-51.de>
[grub2/phcoder/solaris.git] / util / grub-probe.c
blob4e3f96451222cf955afad6c76a8ed90ee2af73ff
1 /* grub-probe.c - probe device information for a given path */
2 /*
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/>.
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>
25 #include <grub/file.h>
26 #include <grub/fs.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>
32 #include <grub/env.h>
33 #include <grub/raid.h>
35 #include <grub_probe_init.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <sys/stat.h>
43 #define _GNU_SOURCE 1
44 #include <getopt.h>
46 enum {
47 PRINT_FS,
48 PRINT_FS_UUID,
49 PRINT_DRIVE,
50 PRINT_DEVICE,
51 PRINT_PARTMAP,
52 PRINT_ABSTRACTION,
55 int print = PRINT_FS;
56 static unsigned int argument_is_device = 0;
58 void
59 grub_putchar (int c)
61 putchar (c);
64 int
65 grub_getkey (void)
67 return -1;
70 struct grub_handler_class grub_term_input_class;
71 struct grub_handler_class grub_term_output_class;
73 void
74 grub_refresh (void)
76 fflush (stdout);
79 static void
80 probe_partmap (grub_disk_t disk)
82 if (disk->partition == NULL)
84 grub_util_info ("No partition map found for %s", disk->name);
85 return;
88 printf ("%s\n", disk->partition->partmap->name);
91 static int
92 probe_raid_level (grub_disk_t disk)
94 if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID)
95 return -1;
97 return ((struct grub_raid_array *) disk->data)->level;
100 static void
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;
107 grub_fs_t fs;
109 if (path == 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);
114 #else
115 if (! grub_util_check_block_device (device_name))
116 grub_util_error ("%s is not a block device.\n", device_name);
117 #endif
119 else
120 device_name = grub_guess_root_device (path);
122 if (! device_name)
123 grub_util_error ("cannot find a device for %s.\n", path);
125 if (print == PRINT_DEVICE)
127 printf ("%s\n", device_name);
128 goto end;
131 drive_name = grub_util_get_grub_dev (device_name);
132 if (! drive_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);
138 goto end;
141 grub_util_info ("opening %s", drive_name);
142 dev = grub_device_open (drive_name);
143 if (! dev)
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);
150 int is_raid = 0;
151 int is_raid5 = 0;
152 int is_raid6 = 0;
153 int raid_level;
155 raid_level = probe_raid_level (dev->disk);
156 if (raid_level >= 0)
158 is_raid = 1;
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);
165 while (list)
167 raid_level = probe_raid_level (list->disk);
168 if (raid_level >= 0)
170 is_raid = 1;
171 is_raid5 |= (raid_level == 5);
172 is_raid6 |= (raid_level == 6);
175 tmp = list->next;
176 free (list);
177 list = tmp;
180 if (is_raid)
182 printf ("raid ");
183 if (is_raid5)
184 printf ("raid5rec ");
185 if (is_raid6)
186 printf ("raid6rec ");
187 printf ("mdraid ");
190 if (is_lvm)
191 printf ("lvm ");
193 printf ("\n");
195 goto end;
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);
208 while (list)
210 probe_partmap (list->disk);
211 /* LVM on RAID */
212 if (list->disk->dev->memberlist)
214 grub_disk_memberlist_t sub_list;
216 sub_list = list->disk->dev->memberlist (list->disk);
217 while (sub_list)
219 probe_partmap (sub_list->disk);
220 tmp = sub_list->next;
221 free (sub_list);
222 sub_list = tmp;
225 tmp = list->next;
226 free (list);
227 list = tmp;
229 goto end;
232 fs = grub_fs_probe (dev);
233 if (! fs)
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. */
240 #if 0
241 struct stat st;
243 stat (path, &st);
245 if (S_ISREG (st.st_mode))
247 /* Regular file. Verify that we can read it properly. */
249 grub_file_t file;
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");
264 #endif
266 printf ("%s\n", fs->name);
269 if (print == PRINT_FS_UUID)
271 char *uuid;
272 if (! fs->uuid)
273 grub_util_error ("%s does not support UUIDs", fs->name);
275 fs->uuid (dev, &uuid);
277 printf ("%s\n", uuid);
280 end:
281 if (dev)
282 grub_device_close (dev);
283 free (grub_path);
284 free (filebuf_via_grub);
285 free (filebuf_via_sys);
286 free (drive_name);
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'},
297 {0, 0, 0, 0}
300 static void
301 usage (int status)
303 if (status)
304 fprintf (stderr,
305 "Try ``grub-probe --help'' for more information.\n");
306 else
307 printf ("\
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);
324 exit (status);
328 main (int argc, char *argv[])
330 char *dev_map = 0;
331 char *argument;
333 progname = "grub-probe";
335 /* Check for options. */
336 while (1)
338 int c = getopt_long (argc, argv, "dm:t:hVv", options, 0);
340 if (c == -1)
341 break;
342 else
343 switch (c)
345 case 'd':
346 argument_is_device = 1;
347 break;
349 case 'm':
350 if (dev_map)
351 free (dev_map);
353 dev_map = xstrdup (optarg);
354 break;
356 case 't':
357 if (!strcmp (optarg, "fs"))
358 print = PRINT_FS;
359 else if (!strcmp (optarg, "fs_uuid"))
360 print = PRINT_FS_UUID;
361 else if (!strcmp (optarg, "drive"))
362 print = PRINT_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;
369 else
370 usage (1);
371 break;
373 case 'h':
374 usage (0);
375 break;
377 case 'V':
378 printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
379 return 0;
381 case 'v':
382 verbosity++;
383 break;
385 default:
386 usage (1);
387 break;
391 if (verbosity > 1)
392 grub_env_set ("debug", "all");
394 /* Obtain ARGUMENT. */
395 if (optind >= argc)
397 fprintf (stderr, "No path or device is specified.\n");
398 usage (1);
401 if (optind + 1 != argc)
403 fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
404 usage (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. */
413 grub_init_all ();
415 /* Do it. */
416 if (argument_is_device)
417 probe (NULL, argument);
418 else
419 probe (argument, NULL);
421 /* Free resources. */
422 grub_fini_all ();
423 grub_util_biosdisk_fini ();
425 free (dev_map);
427 return 0;