Search hints support.

* commands/search.c (FUNC_NAME): New arguments hints and nhints.
	All users updated.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-13 13:01:41 +02:00
commit 53f0eb1f64
4 changed files with 104 additions and 13 deletions

View file

@ -1,3 +1,10 @@
2010-09-13 Vladimir Serbinenko <phcoder@gmail.com>
Search hints support.
* commands/search.c (FUNC_NAME): New arguments hints and nhints.
All users updated.
2010-09-13 Yves Blusseau <blusseau@zetam.org>
Bash completion script for util commands

View file

@ -28,9 +28,12 @@
#include <grub/command.h>
#include <grub/search.h>
#include <grub/i18n.h>
#include <grub/disk.h>
#include <grub/partition.h>
void
FUNC_NAME (const char *key, const char *var, int no_floppy)
FUNC_NAME (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints)
{
int count = 0;
grub_fs_autoload_hook_t saved_autoload;
@ -114,22 +117,86 @@ FUNC_NAME (const char *key, const char *var, int no_floppy)
return (found && var);
}
auto int part_hook (grub_disk_t disk, const grub_partition_t partition);
int part_hook (grub_disk_t disk, const grub_partition_t partition)
{
char *partition_name, *devname;
int ret;
partition_name = grub_partition_get_name (partition);
if (! partition_name)
return 1;
devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
grub_free (partition_name);
if (!devname)
return 1;
ret = iterate_device (devname);
grub_free (devname);
return ret;
}
auto void try (void);
void try (void)
{
unsigned i;
for (i = 0; i < nhints; i++)
{
char *end;
if (!hints[i][0])
continue;
end = hints[i] + grub_strlen (hints[i]) - 1;
if (*end == ',')
*end = 0;
if (iterate_device (hints[i]))
{
if (!*end)
*end = ',';
return;
}
if (!*end)
{
grub_device_t dev;
int ret;
dev = grub_device_open (hints[i]);
if (!dev)
{
*end = ',';
continue;
}
if (!dev->disk)
{
grub_device_close (dev);
*end = ',';
continue;
}
ret = grub_partition_iterate (dev->disk, part_hook);
*end = ',';
grub_device_close (dev);
if (ret)
return;
}
}
grub_device_iterate (iterate_device);
}
/* First try without autoloading if we're setting variable. */
if (var)
{
saved_autoload = grub_fs_autoload_hook;
grub_fs_autoload_hook = 0;
grub_device_iterate (iterate_device);
try ();
/* Restore autoload hook. */
grub_fs_autoload_hook = saved_autoload;
/* Retry with autoload if nothing found. */
if (grub_errno == GRUB_ERR_NONE && count == 0)
grub_device_iterate (iterate_device);
try ();
}
else
grub_device_iterate (iterate_device);
try ();
if (grub_errno == GRUB_ERR_NONE && count == 0)
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
@ -142,7 +209,8 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0);
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
argc > 2 ? argc - 2 : 0);
return grub_errno;
}
@ -159,7 +227,7 @@ GRUB_MOD_INIT(search_label)
{
cmd =
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
N_("NAME [VARIABLE]"),
N_("NAME [VARIABLE] [HINTS]"),
HELP_MESSAGE);
}

View file

@ -37,6 +37,9 @@ static const struct grub_arg_option options[] =
{"set", 's', GRUB_ARG_OPTION_OPTIONAL,
N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING},
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@ -47,6 +50,7 @@ enum options
SEARCH_FS_UUID,
SEARCH_SET,
SEARCH_NO_FLOPPY,
SEARCH_HINT
};
static grub_err_t
@ -54,6 +58,11 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
const char *var = 0;
int nhints = 0;
if (state[SEARCH_HINT].set)
while (state[SEARCH_HINT].args[nhints])
nhints++;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
@ -62,11 +71,14 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
if (state[SEARCH_LABEL].set)
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else if (state[SEARCH_FS_UUID].set)
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else if (state[SEARCH_FILE].set)
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
@ -80,7 +92,8 @@ GRUB_MOD_INIT(search)
cmd =
grub_register_extcmd ("search", grub_cmd_search,
GRUB_COMMAND_FLAG_BOTH,
N_("search [-f|-l|-u|-s|-n] NAME"),
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
" NAME"),
N_("Search devices by file, filesystem label"
" or filesystem UUID."
" If --set is specified, the first device found is"

View file

@ -19,8 +19,11 @@
#ifndef GRUB_SEARCH_HEADER
#define GRUB_SEARCH_HEADER 1
void grub_search_fs_file (const char *key, const char *var, int no_floppy);
void grub_search_fs_uuid (const char *key, const char *var, int no_floppy);
void grub_search_label (const char *key, const char *var, int no_floppy);
void grub_search_fs_file (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints);
void grub_search_fs_uuid (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints);
void grub_search_label (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints);
#endif