Remove nested functions from device iterators.
authorColin Watson <cjwatson@ubuntu.com>
Sun, 20 Jan 2013 15:52:15 +0000 (15:52 +0000)
committerColin Watson <cjwatson@ubuntu.com>
Sun, 20 Jan 2013 15:52:15 +0000 (15:52 +0000)
* include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type.
(grub_arc_iterate_devs): Add hook_data argument.
* include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type.
(struct grub_ata_dev.iterate): Add hook_data argument.
* include/grub/device.h (grub_device_iterate_hook_t): New type.
(grub_device_iterate): Add hook_data argument.
* include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type.
(struct grub_disk_dev.iterate): Add hook_data argument.
(grub_disk_dev_iterate): Likewise.
* include/grub/gpt_partition.h (grub_gpt_partition_map_iterate):
Likewise.
* include/grub/msdos_partition.h (grub_partition_msdos_iterate):
Likewise.
* include/grub/partition.h (grub_partition_iterate_hook_t): New
type.
(struct grub_partition_map.iterate): Add hook_data argument.
(grub_partition_iterate): Likewise.
* include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type.
(struct grub_scsi_dev.iterate): Add hook_data argument.

Update all callers.

50 files changed:
ChangeLog
grub-core/commands/arc/lsdev.c
grub-core/commands/ls.c
grub-core/commands/search.c
grub-core/commands/wildcard.c
grub-core/disk/ahci.c
grub-core/disk/arc/arcdisk.c
grub-core/disk/ata.c
grub-core/disk/cryptodisk.c
grub-core/disk/diskfilter.c
grub-core/disk/efi/efidisk.c
grub-core/disk/host.c
grub-core/disk/i386/pc/biosdisk.c
grub-core/disk/ieee1275/nand.c
grub-core/disk/ieee1275/ofdisk.c
grub-core/disk/ldm.c
grub-core/disk/loopback.c
grub-core/disk/memdisk.c
grub-core/disk/pata.c
grub-core/disk/scsi.c
grub-core/disk/usbms.c
grub-core/fs/btrfs.c
grub-core/fs/zfs/zfs.c
grub-core/kern/corecmd.c
grub-core/kern/device.c
grub-core/kern/emu/hostdisk.c
grub-core/kern/mips/arc/init.c
grub-core/kern/partition.c
grub-core/loader/i386/pc/plan9.c
grub-core/normal/completion.c
grub-core/partmap/acorn.c
grub-core/partmap/amiga.c
grub-core/partmap/apple.c
grub-core/partmap/bsdlabel.c
grub-core/partmap/dvh.c
grub-core/partmap/gpt.c
grub-core/partmap/msdos.c
grub-core/partmap/plan.c
grub-core/partmap/sun.c
grub-core/partmap/sunpc.c
include/grub/arc/arc.h
include/grub/ata.h
include/grub/device.h
include/grub/disk.h
include/grub/gpt_partition.h
include/grub/msdos_partition.h
include/grub/partition.h
include/grub/scsi.h
util/getroot.c
util/grub-setup.c

index 1c816d6..733b212 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2013-01-20  Colin Watson  <cjwatson@ubuntu.com>
+
+       Remove nested functions from device iterators.
+
+       * include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type.
+       (grub_arc_iterate_devs): Add hook_data argument.
+       * include/grub/ata.h (grub_ata_dev_iterate_hook_t): New type.
+       (struct grub_ata_dev.iterate): Add hook_data argument.
+       * include/grub/device.h (grub_device_iterate_hook_t): New type.
+       (grub_device_iterate): Add hook_data argument.
+       * include/grub/disk.h (grub_disk_dev_iterate_hook_t): New type.
+       (struct grub_disk_dev.iterate): Add hook_data argument.
+       (grub_disk_dev_iterate): Likewise.
+       * include/grub/gpt_partition.h (grub_gpt_partition_map_iterate):
+       Likewise.
+       * include/grub/msdos_partition.h (grub_partition_msdos_iterate):
+       Likewise.
+       * include/grub/partition.h (grub_partition_iterate_hook_t): New
+       type.
+       (struct grub_partition_map.iterate): Add hook_data argument.
+       (grub_partition_iterate): Likewise.
+       * include/grub/scsi.h (grub_scsi_dev_iterate_hook_t): New type.
+       (struct grub_scsi_dev.iterate): Add hook_data argument.
+
+       Update all callers.
+
 2013-01-20  Colin Watson  <cjwatson@ubuntu.com>
 
        Fix typos for "developer" and "development".
index 5d4b0cd..27ed0a2 100644 (file)
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+/* Helper for grub_cmd_lsdev.  */
+static int
+grub_cmd_lsdev_iter (const char *name,
+                    const struct grub_arc_component *comp __attribute__ ((unused)),
+                    void *data __attribute__ ((unused)))
+{
+  grub_printf ("%s\n", name);
+  return 0;
+}
+
 static grub_err_t
 grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)),
                int argc __attribute__ ((unused)),
                char **args __attribute__ ((unused)))
 {
-  auto int hook (const char *name, const struct grub_arc_component *comp);
-  int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused)))
-  {
-    grub_printf ("%s\n", name);
-    return 0;
-  }
-  grub_arc_iterate_devs (hook, 0);
+  grub_arc_iterate_devs (grub_cmd_lsdev_iter, 0, 0);
   return 0;
 }
 
index 913bb65..7929747 100644 (file)
@@ -45,21 +45,24 @@ static const struct grub_arg_option options[] =
 
 static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
 
-static grub_err_t
-grub_ls_list_devices (int longlist)
+/* Helper for grub_ls_list_devices.  */
+static int
+grub_ls_print_devices (const char *name, void *data)
 {
-  auto int grub_ls_print_devices (const char *name);
-  int grub_ls_print_devices (const char *name)
-    {
-      if (longlist)
-       grub_normal_print_device_info (name);
-      else
-       grub_printf ("(%s) ", name);
+  int *longlist = data;
 
-      return 0;
-    }
+  if (longlist)
+    grub_normal_print_device_info (name);
+  else
+    grub_printf ("(%s) ", name);
+
+  return 0;
+}
 
-  grub_device_iterate (grub_ls_print_devices);
+static grub_err_t
+grub_ls_list_devices (int longlist)
+{
+  grub_device_iterate (grub_ls_print_devices, &longlist);
   grub_xputs ("\n");
 
 #if 0
index 5e9b7e3..16143a3 100644 (file)
@@ -42,23 +42,29 @@ struct cache_entry
 
 static struct cache_entry *cache;
 
-void
-FUNC_NAME (const char *key, const char *var, int no_floppy,
-          char **hints, unsigned nhints)
+/* Context for FUNC_NAME.  */
+struct search_ctx
 {
-  int count = 0;
-  int is_cache = 0;
-  grub_fs_autoload_hook_t saved_autoload;
+  const char *key;
+  const char *var;
+  int no_floppy;
+  char **hints;
+  unsigned nhints;
+  int count;
+  int is_cache;
+};
 
-  auto int iterate_device (const char *name);
-  int iterate_device (const char *name)
-  {
-    int found = 0;
+/* Helper for FUNC_NAME.  */
+static int
+iterate_device (const char *name, void *data)
+{
+  struct search_ctx *ctx = data;
+  int found = 0;
 
-    /* Skip floppy drives when requested.  */
-    if (no_floppy &&
-       name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
-      return 0;
+  /* Skip floppy drives when requested.  */
+  if (ctx->no_floppy &&
+      name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
+    return 0;
 
 #ifdef DO_SEARCH_FS_UUID
 #define compare_fn grub_strcasecmp
@@ -67,34 +73,34 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
 #endif
 
 #ifdef DO_SEARCH_FILE
-      {
-       char *buf;
-       grub_file_t file;
-
-       buf = grub_xasprintf ("(%s)%s", name, key);
-       if (! buf)
-         return 1;
-
-       grub_file_filter_disable_compression ();
-       file = grub_file_open (buf);
-       if (file)
-         {
-           found = 1;
-           grub_file_close (file);
-         }
-       grub_free (buf);
-      }
+    {
+      char *buf;
+      grub_file_t file;
+
+      buf = grub_xasprintf ("(%s)%s", name, ctx->key);
+      if (! buf)
+       return 1;
+
+      grub_file_filter_disable_compression ();
+      file = grub_file_open (buf);
+      if (file)
+       {
+         found = 1;
+         grub_file_close (file);
+       }
+      grub_free (buf);
+    }
 #else
-      {
-       /* SEARCH_FS_UUID or SEARCH_LABEL */
-       grub_device_t dev;
-       grub_fs_t fs;
-       char *quid;
+    {
+      /* SEARCH_FS_UUID or SEARCH_LABEL */
+      grub_device_t dev;
+      grub_fs_t fs;
+      char *quid;
 
-       dev = grub_device_open (name);
-       if (dev)
-         {
-           fs = grub_fs_probe (dev);
+      dev = grub_device_open (name);
+      if (dev)
+       {
+         fs = grub_fs_probe (dev);
 
 #ifdef DO_SEARCH_FS_UUID
 #define read_fn uuid
@@ -102,173 +108,191 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
 #define read_fn label
 #endif
 
-           if (fs && fs->read_fn)
-             {
-               fs->read_fn (dev, &quid);
+         if (fs && fs->read_fn)
+           {
+             fs->read_fn (dev, &quid);
 
-               if (grub_errno == GRUB_ERR_NONE && quid)
-                 {
-                   if (compare_fn (quid, key) == 0)
-                     found = 1;
+             if (grub_errno == GRUB_ERR_NONE && quid)
+               {
+                 if (compare_fn (quid, ctx->key) == 0)
+                   found = 1;
 
-                   grub_free (quid);
-                 }
-             }
+                 grub_free (quid);
+               }
+           }
 
-           grub_device_close (dev);
-         }
-      }
+         grub_device_close (dev);
+       }
+    }
 #endif
 
-    if (!is_cache && found && count == 0)
-      {
-       struct cache_entry *cache_ent;
-       cache_ent = grub_malloc (sizeof (*cache_ent));
-       if (cache_ent)
-         {
-           cache_ent->key = grub_strdup (key);
-           cache_ent->value = grub_strdup (name);
-           if (cache_ent->value && cache_ent->key)
-             {
-               cache_ent->next = cache;
-               cache = cache_ent;
-             }
-           else
-             {
-               grub_free (cache_ent->value);
-               grub_free (cache_ent->key);
-               grub_free (cache_ent);
-               grub_errno = GRUB_ERR_NONE;
-             }
-         }
-       else
-         grub_errno = GRUB_ERR_NONE;
-      }
-
-    if (found)
-      {
-       count++;
-       if (var)
-         grub_env_set (var, name);
-       else
-         grub_printf (" %s", name);
-      }
-
-    grub_errno = GRUB_ERR_NONE;
-    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;
-    struct cache_entry **prev;
-    struct cache_entry *cache_ent;
-
-    for (prev = &cache, cache_ent = *prev; cache_ent;
-        prev = &cache_ent->next, cache_ent = *prev)
-      if (compare_fn (cache_ent->key, key) == 0)
-       break;
-    if (cache_ent)
-      {
-       is_cache = 1;
-       if (iterate_device (cache_ent->value))
-         {
-           is_cache = 0;
-           return;
-         }
-       is_cache = 0;
-       /* Cache entry was outdated. Remove it.  */
-       if (!count)
-         {
-           grub_free (cache_ent->key);
-           grub_free (cache_ent->value);
-           grub_free (cache_ent);
-           *prev = cache_ent->next;
-         }
-      }
-
-    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 = ',';
+  if (!ctx->is_cache && found && ctx->count == 0)
+    {
+      struct cache_entry *cache_ent;
+      cache_ent = grub_malloc (sizeof (*cache_ent));
+      if (cache_ent)
+       {
+         cache_ent->key = grub_strdup (ctx->key);
+         cache_ent->value = grub_strdup (name);
+         if (cache_ent->value && cache_ent->key)
+           {
+             cache_ent->next = cache;
+             cache = cache_ent;
+           }
+         else
+           {
+             grub_free (cache_ent->value);
+             grub_free (cache_ent->key);
+             grub_free (cache_ent);
+             grub_errno = GRUB_ERR_NONE;
+           }
+       }
+      else
+       grub_errno = GRUB_ERR_NONE;
+    }
+
+  if (found)
+    {
+      ctx->count++;
+      if (ctx->var)
+       grub_env_set (ctx->var, name);
+      else
+       grub_printf (" %s", name);
+    }
+
+  grub_errno = GRUB_ERR_NONE;
+  return (found && ctx->var);
+}
+
+/* Helper for FUNC_NAME.  */
+static int
+part_hook (grub_disk_t disk, const grub_partition_t partition, void *data)
+{
+  struct search_ctx *ctx = data;
+  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, ctx);
+  grub_free (devname);    
+
+  return ret;
+}
+
+/* Helper for FUNC_NAME.  */
+static void
+try (struct search_ctx *ctx)    
+{
+  unsigned i;
+  struct cache_entry **prev;
+  struct cache_entry *cache_ent;
+
+  for (prev = &cache, cache_ent = *prev; cache_ent;
+       prev = &cache_ent->next, cache_ent = *prev)
+    if (compare_fn (cache_ent->key, ctx->key) == 0)
+      break;
+  if (cache_ent)
+    {
+      ctx->is_cache = 1;
+      if (iterate_device (cache_ent->value, ctx))
+       {
+         ctx->is_cache = 0;
+         return;
+       }
+      ctx->is_cache = 0;
+      /* Cache entry was outdated. Remove it.  */
+      if (!ctx->count)
+       {
+         grub_free (cache_ent->key);
+         grub_free (cache_ent->value);
+         grub_free (cache_ent);
+         *prev = cache_ent->next;
+       }
+    }
+
+  for (i = 0; i < ctx->nhints; i++)
+    {
+      char *end;
+      if (!ctx->hints[i][0])
+       continue;
+      end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1;
+      if (*end == ',')
+       *end = 0;
+      if (iterate_device (ctx->hints[i], ctx))
+       {
+         if (!*end)
+           *end = ',';
+         return;
+       }
+      if (!*end)
+       {
+         grub_device_t dev;
+         int ret;
+         dev = grub_device_open (ctx->hints[i]);
+         if (!dev)
+           {
+             if (!*end)
+               *end = ',';
+             continue;
+           }
+         if (!dev->disk)
+           {
+             grub_device_close (dev);
+             if (!*end)
+               *end = ',';
+             continue;
+           }
+         ret = grub_partition_iterate (dev->disk, part_hook, ctx);
+         if (!*end)
+           *end = ',';
+         grub_device_close (dev);
+         if (ret)
            return;
-         }
-       if (!*end)
-         {
-           grub_device_t dev;
-           int ret;
-           dev = grub_device_open (hints[i]);
-           if (!dev)
-             {
-               if (!*end)
-                 *end = ',';
-               continue;
-             }
-           if (!dev->disk)
-             {
-               grub_device_close (dev);
-               if (!*end)
-                 *end = ',';
-               continue;
-             }
-           ret = grub_partition_iterate (dev->disk, part_hook);
-           if (!*end)
-             *end = ',';
-           grub_device_close (dev);
-           if (ret)
-             return;
-         }
-      }
-    grub_device_iterate (iterate_device);
-  }
+       }
+    }
+  grub_device_iterate (iterate_device, ctx);
+}
+
+void
+FUNC_NAME (const char *key, const char *var, int no_floppy,
+          char **hints, unsigned nhints)
+{
+  struct search_ctx ctx = {
+    .key = key,
+    .var = var,
+    .no_floppy = no_floppy,
+    .hints = hints,
+    .nhints = nhints,
+    .count = 0,
+    .is_cache = 0
+  };
+  grub_fs_autoload_hook_t saved_autoload;
 
   /* First try without autoloading if we're setting variable. */
   if (var)
     {
       saved_autoload = grub_fs_autoload_hook;
       grub_fs_autoload_hook = 0;
-      try ();
+      try (&ctx);
 
       /* Restore autoload hook.  */
       grub_fs_autoload_hook = saved_autoload;
 
       /* Retry with autoload if nothing found.  */
-      if (grub_errno == GRUB_ERR_NONE && count == 0)
-       try ();
+      if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
+       try (&ctx);
     }
   else
-    try ();
+    try (&ctx);
 
-  if (grub_errno == GRUB_ERR_NONE && count == 0)
+  if (grub_errno == GRUB_ERR_NONE && ctx.count == 0)
     grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
 }
 
index 2b73d9a..633de51 100644 (file)
@@ -210,59 +210,71 @@ split_path (const char *str, const char **noregexop, const char **regexop)
     *noregexop = split;
 }
 
-static char **
-match_devices (const regex_t *regexp, int noparts)
+/* Context for match_devices.  */
+struct match_devices_ctx
 {
-  int i;
+  const regex_t *regexp;
+  int noparts;
   int ndev;
   char **devs;
+};
 
-  auto int match (const char *name);
-  int match (const char *name)
-  {
-    char **t;
-    char *buffer;
+/* Helper for match_devices.  */
+static int
+match_devices_iter (const char *name, void *data)
+{
+  struct match_devices_ctx *ctx = data;
+  char **t;
+  char *buffer;
 
-    /* skip partitions if asked to. */
-    if (noparts && grub_strchr(name, ','))
-      return 0;
+  /* skip partitions if asked to. */
+  if (ctx->noparts && grub_strchr (name, ','))
+    return 0;
 
-    buffer = grub_xasprintf ("(%s)", name);
-    if (! buffer)
-      return 1;
+  buffer = grub_xasprintf ("(%s)", name);
+  if (! buffer)
+    return 1;
 
-    grub_dprintf ("expand", "matching: %s\n", buffer);
-    if (regexec (regexp, buffer, 0, 0, 0))
-      {
-       grub_dprintf ("expand", "not matched\n");
-       grub_free (buffer);
-       return 0;
-      }
+  grub_dprintf ("expand", "matching: %s\n", buffer);
+  if (regexec (ctx->regexp, buffer, 0, 0, 0))
+    {
+      grub_dprintf ("expand", "not matched\n");
+      grub_free (buffer);
+      return 0;
+    }
 
-    t = grub_realloc (devs, sizeof (char*) * (ndev + 2));
-    if (! t)
-      return 1;
+  t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2));
+  if (! t)
+    return 1;
 
-    devs = t;
-    devs[ndev++] = buffer;
-    devs[ndev] = 0;
-    return 0;
-  }
+  ctx->devs = t;
+  ctx->devs[ctx->ndev++] = buffer;
+  ctx->devs[ctx->ndev] = 0;
+  return 0;
+}
 
-  ndev = 0;
-  devs = 0;
+static char **
+match_devices (const regex_t *regexp, int noparts)
+{
+  struct match_devices_ctx ctx = {
+    .regexp = regexp,
+    .noparts = noparts,
+    .ndev = 0,
+    .devs = 0
+  };
+  int i;
 
-  if (grub_device_iterate (match))
+  if (grub_device_iterate (match_devices_iter, &ctx))
     goto fail;
 
-  return devs;
+  return ctx.devs;
 
  fail:
 
-  for (i = 0; devs && devs[i]; i++)
-    grub_free (devs[i]);
+  for (i = 0; ctx.devs && ctx.devs[i]; i++)
+    grub_free (ctx.devs[i]);
 
-  grub_free (devs);
+  grub_free (ctx.devs);
 
   return 0;
 }
index f229ff1..f9258fd 100644 (file)
@@ -455,8 +455,8 @@ grub_ahci_restore_hw (void)
 \f
 
 static int
-grub_ahci_iterate (int (*hook) (int id, int bus),
-                 grub_disk_pull_t pull)
+grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data,
+                  grub_disk_pull_t pull)
 {
   struct grub_ahci_device *dev;
 
@@ -464,7 +464,7 @@ grub_ahci_iterate (int (*hook) (int id, int bus),
     return 0;
 
   FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
-    if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
+    if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num, hook_data))
       return 1;
 
   return 0;
index 10cbc87..37c0ac3 100644 (file)
@@ -80,23 +80,37 @@ arcdisk_hash_add (char *devpath)
 }
 
 
+/* Context for grub_arcdisk_iterate.  */
+struct grub_arcdisk_iterate_ctx
+{
+  grub_disk_dev_iterate_hook_t hook;
+  void *hook_data;
+};
+
+/* Helper for grub_arcdisk_iterate.  */
+static int
+grub_arcdisk_iterate_iter (const char *name,
+                          const struct grub_arc_component *comp, void *data)
+{
+  struct grub_arcdisk_iterate_ctx *ctx = data;
+
+  if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
+       || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
+       || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
+    return 0;
+  return ctx->hook (name, ctx->hook_data);
+}
+
 static int
 grub_arcdisk_iterate (int (*hook_in) (const char *name),
                      grub_disk_pull_t pull)
 {
-  auto int hook (const char *name, const struct grub_arc_component *comp);
-  int hook (const char *name, const struct grub_arc_component *comp)
-  {
-    if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
-         || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
-         || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
-      return 0;
-    return hook_in (name);
-  }
+  struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data };
+
   if (pull != GRUB_DISK_PULL_NONE)
     return 0;
 
-  return grub_arc_iterate_devs (hook, 1);
+  return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1);
 }
 
 #define RAW_SUFFIX "partition(10)"
index c0d378c..c84d316 100644 (file)
@@ -392,40 +392,50 @@ grub_ata_real_open (int id, int bus)
   return NULL;
 }
 
+/* Context for grub_ata_iterate.  */
+struct grub_ata_iterate_ctx
+{
+  grub_disk_dev_iterate_hook_t hook;
+  void *hook_data;
+};
+
+/* Helper for grub_ata_iterate.  */
 static int
-grub_ata_iterate (int (*hook_in) (const char *name),
-                 grub_disk_pull_t pull)
+grub_ata_iterate_iter (int id, int bus, void *data)
 {
-  auto int hook (int id, int bus);
-  int hook (int id, int bus)
-  {
-    struct grub_ata *ata;
-    int ret;
-    char devname[40];
+  struct grub_ata_iterate_ctx *ctx = data;
+  struct grub_ata *ata;
+  int ret;
+  char devname[40];
 
-    ata = grub_ata_real_open (id, bus);
+  ata = grub_ata_real_open (id, bus);
 
-    if (!ata)
-      {
-       grub_errno = GRUB_ERR_NONE;
-       return 0;
-      }
-    if (ata->atapi)
-      {
-       grub_ata_real_close (ata);
-       return 0;
-      }
-    grub_snprintf (devname, sizeof (devname), 
-                  "%s%d", grub_scsi_names[id], bus);
-    ret = hook_in (devname);
-    grub_ata_real_close (ata);
-    return ret;
-  }
+  if (!ata)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  if (ata->atapi)
+    {
+      grub_ata_real_close (ata);
+      return 0;
+    }
+  grub_snprintf (devname, sizeof (devname), 
+                "%s%d", grub_scsi_names[id], bus);
+  ret = ctx->hook (devname, ctx->hook_data);
+  grub_ata_real_close (ata);
+  return ret;
+}
 
+static int
+grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                 grub_disk_pull_t pull)
+{
+  struct grub_ata_iterate_ctx ctx = { hook, hook_data };
   grub_ata_dev_t p;
   
   for (p = grub_ata_dev_list; p; p = p->next)
-    if (p->iterate && p->iterate (hook, pull))
+    if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull))
       return 1;
   return 0;
 }
@@ -561,37 +571,47 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi)
   return GRUB_ERR_NONE;
 }
 
+/* Context for grub_atapi_iterate.  */
+struct grub_atapi_iterate_ctx
+{
+  grub_scsi_dev_iterate_hook_t hook;
+  void *hook_data;
+};
+
+/* Helper for grub_atapi_iterate.  */
 static int
-grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns),
-                   grub_disk_pull_t pull)
+grub_atapi_iterate_iter (int id, int bus, void *data)
 {
-  auto int hook (int id, int bus);
-  int hook (int id, int bus)
-  {
-    struct grub_ata *ata;
-    int ret;
+  struct grub_atapi_iterate_ctx *ctx = data;
+  struct grub_ata *ata;
+  int ret;
 
-    ata = grub_ata_real_open (id, bus);
+  ata = grub_ata_real_open (id, bus);
 
-    if (!ata)
-      {
-       grub_errno = GRUB_ERR_NONE;
-       return 0;
-      }
-    if (!ata->atapi)
-      {
-       grub_ata_real_close (ata);
-       return 0;
-      }
-    ret = hook_in (id, bus, 1);
-    grub_ata_real_close (ata);
-    return ret;
-  }
+  if (!ata)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  if (!ata->atapi)
+    {
+      grub_ata_real_close (ata);
+      return 0;
+    }
+  ret = ctx->hook (id, bus, 1, ctx->hook_data);
+  grub_ata_real_close (ata);
+  return ret;
+}
 
+static int
+grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
+                   grub_disk_pull_t pull)
+{
+  struct grub_atapi_iterate_ctx ctx = { hook, hook_data };
   grub_ata_dev_t p;
   
   for (p = grub_ata_dev_list; p; p = p->next)
-    if (p->iterate && p->iterate (hook, pull))
+    if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull))
       return 1;
   return 0;
 }
index 3de3b86..ce755c3 100644 (file)
@@ -448,8 +448,8 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke
 }
 
 static int
-grub_cryptodisk_iterate (int (*hook) (const char *name),
-                  grub_disk_pull_t pull)
+grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                        grub_disk_pull_t pull)
 {
   grub_cryptodisk_t i;
 
@@ -460,7 +460,7 @@ grub_cryptodisk_iterate (int (*hook) (const char *name),
     {
       char buf[30];
       grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id);
-      if (hook (buf))
+      if (hook (buf, hook_data))
        return 1;
     }
 
@@ -866,7 +866,8 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
 #endif
 
 static int
-grub_cryptodisk_scan_device (const char *name)
+grub_cryptodisk_scan_device (const char *name,
+                            void *data __attribute__ ((unused)))
 {
   grub_err_t err;
   grub_disk_t source;
@@ -908,7 +909,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
 
       check_boot = state[2].set;
       search_uuid = args[0];
-      grub_device_iterate (&grub_cryptodisk_scan_device);
+      grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
       search_uuid = NULL;
 
       if (!have_it)
@@ -919,7 +920,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
     {
       search_uuid = NULL;
       check_boot = state[2].set;
-      grub_device_iterate (&grub_cryptodisk_scan_device);
+      grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
       search_uuid = NULL;
       return GRUB_ERR_NONE;
     }
index 4117b20..2ff47e9 100644 (file)
@@ -120,65 +120,68 @@ is_valid_diskfilter_name (const char *name)
          || grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0);
 }
 
+/* Helper for scan_disk.  */
 static int
-scan_disk (const char *name, int accept_diskfilter)
+scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data)
 {
-  auto int hook (grub_disk_t disk, grub_partition_t p);
-  int hook (grub_disk_t disk, grub_partition_t p)
-    {
-      struct grub_diskfilter_vg *arr;
-      grub_disk_addr_t start_sector;
-      struct grub_diskfilter_pv_id id;
-      grub_diskfilter_t diskfilter;
-
-      grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
-                   name);
+  const char *name = data;
+  struct grub_diskfilter_vg *arr;
+  grub_disk_addr_t start_sector;
+  struct grub_diskfilter_pv_id id;
+  grub_diskfilter_t diskfilter;
+
+  grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n",
+               name);
 #ifdef GRUB_UTIL
-      grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
+  grub_util_info ("Scanning for DISKFILTER devices on disk %s", name);
 #endif
 
-      disk->partition = p;
-      
-      for (arr = array_list; arr != NULL; arr = arr->next)
-       {
-         struct grub_diskfilter_pv *m;
-         for (m = arr->pvs; m; m = m->next)
-           if (m->disk && m->disk->id == disk->id
-               && m->disk->dev->id == disk->dev->id
-               && m->part_start == grub_partition_get_start (disk->partition)
-               && m->part_size == grub_disk_get_size (disk))
-             return 0;
-       }
+  disk->partition = p;
+  
+  for (arr = array_list; arr != NULL; arr = arr->next)
+    {
+      struct grub_diskfilter_pv *m;
+      for (m = arr->pvs; m; m = m->next)
+       if (m->disk && m->disk->id == disk->id
+           && m->disk->dev->id == disk->dev->id
+           && m->part_start == grub_partition_get_start (disk->partition)
+           && m->part_size == grub_disk_get_size (disk))
+         return 0;
+    }
 
-      for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
-       {
+  for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next)
+    {
 #ifdef GRUB_UTIL
-         grub_util_info ("Scanning for %s devices on disk %s", 
-                         diskfilter->name, name);
+      grub_util_info ("Scanning for %s devices on disk %s", 
+                     diskfilter->name, name);
 #endif
-         id.uuid = 0;
-         id.uuidlen = 0;
-         arr = diskfilter->detect (disk, &id, &start_sector);
-         if (arr &&
-             (! insert_array (disk, &id, arr, start_sector, diskfilter)))
-           {
-             if (id.uuidlen)
-               grub_free (id.uuid);
-             return 0;
-           }
-         if (arr && id.uuidlen)
+      id.uuid = 0;
+      id.uuidlen = 0;
+      arr = diskfilter->detect (disk, &id, &start_sector);
+      if (arr &&
+         (! insert_array (disk, &id, arr, start_sector, diskfilter)))
+       {
+         if (id.uuidlen)
            grub_free (id.uuid);
-
-         /* This error usually means it's not diskfilter, no need to display
-            it.  */
-         if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
-           grub_print_error ();
-
-         grub_errno = GRUB_ERR_NONE;
+         return 0;
        }
+      if (arr && id.uuidlen)
+       grub_free (id.uuid);
 
-      return 0;
+      /* This error usually means it's not diskfilter, no need to display
+        it.  */
+      if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
+       grub_print_error ();
+
+      grub_errno = GRUB_ERR_NONE;
     }
+
+  return 0;
+}
+
+static int
+scan_disk (const char *name, int accept_diskfilter)
+{
   grub_disk_t disk;
   static int scan_depth = 0;
 
@@ -196,12 +199,12 @@ scan_disk (const char *name, int accept_diskfilter)
       scan_depth--;
       return 0;
     }
-  if (hook (disk, 0))
+  if (scan_disk_partition_iter (disk, 0, (void *) name))
     {
       scan_depth--;
       return 1;
     }
-  if (grub_partition_iterate (disk, hook))
+  if (grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name))
     {
       scan_depth--;
       return 1;
@@ -212,7 +215,7 @@ scan_disk (const char *name, int accept_diskfilter)
 }
 
 static int
-scan_disk_hook (const char *name)
+scan_disk_hook (const char *name, void *data __attribute__ ((unused)))
 {
   return scan_disk (name, 0);
 }
@@ -230,7 +233,7 @@ scan_devices (const char *arname)
       if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
          && p->iterate)
        {
-         if ((p->iterate) (scan_disk_hook, pull))
+         if ((p->iterate) (scan_disk_hook, NULL, pull))
            return;
          if (arname && is_lv_readable (find_lv (arname), 1))
            return;
@@ -249,8 +252,8 @@ scan_devices (const char *arname)
 }
 
 static int
-grub_diskfilter_iterate (int (*hook) (const char *name),
-                  grub_disk_pull_t pull)
+grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                        grub_disk_pull_t pull)
 {
   struct grub_diskfilter_vg *array;
   int islcnt = 0;
@@ -271,7 +274,7 @@ grub_diskfilter_iterate (int (*hook) (const char *name),
        for (lv = array->lvs; lv; lv = lv->next)
          if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt)
            {
-             if (hook (lv->fullname))
+             if (hook (lv->fullname, hook_data))
                return 1;
            }
     }
@@ -303,7 +306,7 @@ grub_diskfilter_memberlist (grub_disk_t disk)
       if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID
          && p->iterate)
        {
-         (p->iterate) (scan_disk_hook, pull);
+         (p->iterate) (scan_disk_hook, NULL, pull);
          while (pv && pv->disk)
            pv = pv->next;
        }
index d9d788c..98cd226 100644 (file)
@@ -404,7 +404,7 @@ enumerate_disks (void)
 }
 
 static int
-grub_efidisk_iterate (int (*hook) (const char *name),
+grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                      grub_disk_pull_t pull)
 {
   struct grub_efidisk_data *d;
@@ -418,7 +418,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
        {
          grub_snprintf (buf, sizeof (buf), "hd%d", count);
          grub_dprintf ("efidisk", "iterating %s\n", buf);
-         if (hook (buf))
+         if (hook (buf, hook_data))
            return 1;
        }
       break;
@@ -427,7 +427,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
        {
          grub_snprintf (buf, sizeof (buf), "fd%d", count);
          grub_dprintf ("efidisk", "iterating %s\n", buf);
-         if (hook (buf))
+         if (hook (buf, hook_data))
            return 1;
        }
 
@@ -435,7 +435,7 @@ grub_efidisk_iterate (int (*hook) (const char *name),
        {
          grub_snprintf (buf, sizeof (buf), "cd%d", count);
          grub_dprintf ("efidisk", "iterating %s\n", buf);
-         if (hook (buf))
+         if (hook (buf, hook_data))
            return 1;
        }
       break;
@@ -736,6 +736,31 @@ get_diskname_from_path (const grub_efi_device_path_t *path,
   return 0;
 }
 
+/* Context for grub_efidisk_get_device_name.  */
+struct grub_efidisk_get_device_name_ctx
+{
+  char *partition_name;
+  grub_efi_hard_drive_device_path_t hd;
+};
+
+/* Helper for grub_efidisk_get_device_name.
+   Find the identical partition.  */
+static int
+grub_efidisk_get_device_name_iter (grub_disk_t disk __attribute__ ((unused)),
+                                  const grub_partition_t part, void *data)
+{
+  struct grub_efidisk_get_device_name_ctx *ctx = data;
+
+  if (grub_partition_get_start (part) == ctx->hd.partition_start
+      && grub_partition_get_len (part) == ctx->hd.partition_size)
+    {
+      ctx->partition_name = grub_partition_get_name (part);
+      return 1;
+    }
+
+  return 0;
+}
+
 char *
 grub_efidisk_get_device_name (grub_efi_handle_t *handle)
 {
@@ -754,28 +779,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
       && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
          == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
     {
-      char *partition_name = NULL;
+      struct grub_efidisk_get_device_name_ctx ctx;
       char *dev_name;
       grub_efi_device_path_t *dup_dp, *dup_ldp;
-      grub_efi_hard_drive_device_path_t hd;
       grub_disk_t parent = 0;
 
-      auto int find_partition (grub_disk_t disk, const grub_partition_t part);
-
-      /* Find the identical partition.  */
-      int find_partition (grub_disk_t disk __attribute__ ((unused)),
-                         const grub_partition_t part)
-       {
-         if (grub_partition_get_start (part) == hd.partition_start
-             && grub_partition_get_len (part) == hd.partition_size)
-           {
-             partition_name = grub_partition_get_name (part);
-             return 1;
-           }
-
-         return 0;
-       }
-
       /* It is necessary to duplicate the device path so that GRUB
         can overwrite it.  */
       dup_dp = duplicate_device_path (dp);
@@ -797,24 +805,27 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
        return 0;
 
       /* Find a partition which matches the hard drive device path.  */
-      grub_memcpy (&hd, ldp, sizeof (hd));
-      if (hd.partition_start == 0
-         && hd.partition_size == grub_disk_get_size (parent))
+      ctx.partition_name = NULL;
+      grub_memcpy (&ctx.hd, ldp, sizeof (ctx.hd));
+      if (ctx.hd.partition_start == 0
+         && ctx.hd.partition_size == grub_disk_get_size (parent))
        {
          dev_name = grub_strdup (parent->name);
        }
       else
        {
-         grub_partition_iterate (parent, find_partition);
+         grub_partition_iterate (parent, grub_efidisk_get_device_name_iter,
+                                 &ctx);
 
-         if (! partition_name)
+         if (! ctx.partition_name)
            {
              grub_disk_close (parent);
              return 0;
            }
 
-         dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
-         grub_free (partition_name);
+         dev_name = grub_xasprintf ("%s,%s", parent->name,
+                                    ctx.partition_name);
+         grub_free (ctx.partition_name);
        }
       grub_disk_close (parent);
 
index 5ee0d2e..959211b 100644 (file)
 int grub_disk_host_i_want_a_reference;
 
 static int
-grub_host_iterate (int (*hook) (const char *name),
+grub_host_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                   grub_disk_pull_t pull)
 {
   if (pull != GRUB_DISK_PULL_NONE)
     return 0;
 
-  if (hook ("host"))
+  if (hook ("host", hook_data))
     return 1;
   return 0;
 }
index 7ca89e3..7c8dca3 100644 (file)
@@ -272,20 +272,21 @@ grub_biosdisk_get_drive (const char *name)
 }
 
 static int
-grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
+grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                        int drive)
 {
   char name[10];
 
   if (cd_drive && drive == cd_drive)
-    return hook ("cd");
+    return hook ("cd", hook_data);
 
   grub_snprintf (name, sizeof (name),
                 (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
-  return hook (name);
+  return hook (name, hook_data);
 }
 
 static int
-grub_biosdisk_iterate (int (*hook) (const char *name),
+grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                       grub_disk_pull_t pull __attribute__ ((unused)))
 {
   int num_floppies;
@@ -304,7 +305,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name),
              break;
            }
 
-         if (grub_biosdisk_call_hook (hook, drive))
+         if (grub_biosdisk_call_hook (hook, hook_data, drive))
            return 1;
        }
       return 0;
@@ -312,14 +313,14 @@ grub_biosdisk_iterate (int (*hook) (const char *name),
     case GRUB_DISK_PULL_REMOVABLE:
       if (cd_drive)
        {
-         if (grub_biosdisk_call_hook (hook, cd_drive))
+         if (grub_biosdisk_call_hook (hook, hook_data, cd_drive))
            return 1;
        }
 
       /* For floppy disks, we can get the number safely.  */
       num_floppies = grub_biosdisk_get_num_floppies ();
       for (drive = 0; drive < num_floppies; drive++)
-       if (grub_biosdisk_call_hook (hook, drive))
+       if (grub_biosdisk_call_hook (hook, hook_data, drive))
          return 1;
       return 0;
     default:
index 3474b3e..b2844b1 100644 (file)
@@ -33,7 +33,7 @@ struct grub_nand_data
 };
 
 static int
-grub_nand_iterate (int (*hook) (const char *name),
+grub_nand_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                   grub_disk_pull_t pull)
 {
   auto int dev_iterate (struct grub_ieee1275_devalias *alias);
@@ -41,7 +41,7 @@ grub_nand_iterate (int (*hook) (const char *name),
   {
     if (grub_strcmp (alias->name, "nand") == 0)
       {
-       hook (alias->name);
+       hook (alias->name, hook_data);
        return 1;
       }
     
index c9535a0..644bbd2 100644 (file)
@@ -218,7 +218,7 @@ scan (void)
 }
 
 static int
-grub_ofdisk_iterate (int (*hook) (const char *name),
+grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                     grub_disk_pull_t pull)
 {
   unsigned i;
@@ -276,7 +276,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name),
                *optr++ = *iptr++;
              }
            *optr = 0;
-           if (hook (buffer))
+           if (hook (buffer, hook_data))
              return 1;
          }
        }
index 0e4761b..b92433d 100644 (file)
@@ -105,35 +105,39 @@ read_int (grub_uint8_t *in, grub_size_t s)
 
 static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
 
+/* Helper for gpt_ldm_sector.  */
+static int
+gpt_ldm_sector_iter (grub_disk_t disk, const grub_partition_t p, void *data)
+{
+  grub_disk_addr_t *sector = data;
+  struct grub_gpt_partentry gptdata;
+  grub_partition_t p2;
+
+  p2 = disk->partition;
+  disk->partition = p->parent;
+  if (grub_disk_read (disk, p->offset, p->index,
+                     sizeof (gptdata), &gptdata))
+    {
+      disk->partition = p2;
+      return 0;
+    }
+  disk->partition = p2;
+
+  if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
+    {
+      *sector = p->start + p->len - 1;
+      return 1;
+    }
+  return 0;
+}
+
 static grub_disk_addr_t
 gpt_ldm_sector (grub_disk_t dsk)
 {
   grub_disk_addr_t sector = 0;
   grub_err_t err;
-  auto int hook (grub_disk_t disk, const grub_partition_t p);
-  int hook (grub_disk_t disk, const grub_partition_t p)
-  {
-    struct grub_gpt_partentry gptdata;
-    grub_partition_t p2;
-
-    p2 = disk->partition;
-    disk->partition = p->parent;
-    if (grub_disk_read (disk, p->offset, p->index,
-                       sizeof (gptdata), &gptdata))
-      {
-       disk->partition = p2;
-       return 0;
-      }
-    disk->partition = p2;
 
-    if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
-      {
-       sector = p->start + p->len - 1;
-       return 1;
-      }
-    return 0;
-  }
-  err = grub_gpt_partition_map_iterate (dsk, hook);
+  err = grub_gpt_partition_map_iterate (dsk, gpt_ldm_sector_iter, &sector);
   if (err)
     {
       grub_errno = GRUB_ERR_NONE;
index fffd1bb..fed88de 100644 (file)
@@ -135,15 +135,15 @@ fail:
 
 \f
 static int
-grub_loopback_iterate (int (*hook) (const char *name),
-                   grub_disk_pull_t pull)
+grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                      grub_disk_pull_t pull)
 {
   struct grub_loopback *d;
   if (pull != GRUB_DISK_PULL_NONE)
     return 0;
   for (d = loopback_list; d; d = d->next)
     {
-      if (hook (d->devname))
+      if (hook (d->devname, hook_data))
        return 1;
     }
   return 0;
index 4de0971..4ad1cb1 100644 (file)
@@ -30,13 +30,13 @@ static char *memdisk_addr;
 static grub_off_t memdisk_size = 0;
 
 static int
-grub_memdisk_iterate (int (*hook) (const char *name),
+grub_memdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                      grub_disk_pull_t pull)
 {
   if (pull != GRUB_DISK_PULL_NONE)
     return 0;
 
-  return hook ("memdisk");
+  return hook ("memdisk", hook_data);
 }
 
 static grub_err_t
index 07c3d7f..75e5deb 100644 (file)
@@ -501,7 +501,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
 }
 
 static int
-grub_pata_iterate (int (*hook) (int id, int bus),
+grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data,
                   grub_disk_pull_t pull)
 {
   struct grub_pata_device *dev;
@@ -510,7 +510,8 @@ grub_pata_iterate (int (*hook) (int id, int bus),
     return 0;
 
   for (dev = grub_pata_devices; dev; dev = dev->next)
-    if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
+    if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device,
+             hook_data))
       return 1;
 
   return 0;
index 29dd0d3..90ac379 100644 (file)
@@ -423,50 +423,59 @@ grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector,
 
 
 \f
-static int
-grub_scsi_iterate (int (*hook) (const char *name),
-                  grub_disk_pull_t pull)
+/* Context for grub_scsi_iterate.  */
+struct grub_scsi_iterate_ctx
 {
-  grub_scsi_dev_t p;
+  grub_disk_dev_iterate_hook_t hook;
+  void *hook_data;
+};
 
-  auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns);
+/* Helper for grub_scsi_iterate.  */
+static int
+scsi_iterate (int id, int bus, int luns, void *data)
+{
+  struct grub_scsi_iterate_ctx *ctx = data;
+  int i;
 
-  int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns)
+  /* In case of a single LUN, just return `usbX'.  */
+  if (luns == 1)
     {
-      int i;
-
-      /* In case of a single LUN, just return `usbX'.  */
-      if (luns == 1)
-       {
-         char *sname;
-         int ret;
-         sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
-         if (!sname)
-           return 1;
-         ret = hook (sname);
-         grub_free (sname);
-         return ret;
-       }
+      char *sname;
+      int ret;
+      sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
+      if (!sname)
+       return 1;
+      ret = ctx->hook (sname, ctx->hook_data);
+      grub_free (sname);
+      return ret;
+    }
 
-      /* In case of multiple LUNs, every LUN will get a prefix to
-        distinguish it.  */
-      for (i = 0; i < luns; i++)
-       {
-         char *sname;
-         int ret;
-         sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
-         if (!sname)
-           return 1;
-         ret = hook (sname);
-         grub_free (sname);
-         if (ret)
-           return 1;
-       }
-      return 0;
+  /* In case of multiple LUNs, every LUN will get a prefix to
+     distinguish it.  */
+  for (i = 0; i < luns; i++)
+    {
+      char *sname;
+      int ret;
+      sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
+      if (!sname)
+       return 1;
+      ret = ctx->hook (sname, ctx->hook_data);
+      grub_free (sname);
+      if (ret)
+       return 1;
     }
+  return 0;
+}
+
+static int
+grub_scsi_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
+                  grub_disk_pull_t pull)
+{
+  struct grub_scsi_iterate_ctx ctx = { hook, hook_data };
+  grub_scsi_dev_t p;
 
   for (p = grub_scsi_dev_list; p; p = p->next)
-    if (p->iterate && (p->iterate) (scsi_iterate, pull))
+    if (p->iterate && (p->iterate) (scsi_iterate, &ctx, pull))
       return 1;
 
   return 0;
index 52cc33e..50f0caf 100644 (file)
@@ -265,7 +265,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
 \f
 
 static int
-grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
+grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
                    grub_disk_pull_t pull)
 {
   unsigned i;
@@ -278,7 +278,8 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
   for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
     if (grub_usbms_devices[i])
       {
-       if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns))
+       if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns,
+                 hook_data))
          return 1;
       }
 
index a993f07..bcc75ba 100644 (file)
@@ -538,56 +538,71 @@ lower_bound (struct grub_btrfs_data *data,
     }
 }
 
-static grub_device_t
-find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
+/* Context for find_device.  */
+struct find_device_ctx
 {
-  grub_device_t dev_found = NULL;
-  auto int hook (const char *name);
-  int hook (const char *name)
-  {
-    grub_device_t dev;
-    grub_err_t err;
-    struct grub_btrfs_superblock sb;
-    dev = grub_device_open (name);
-    if (!dev)
+  struct grub_btrfs_data *data;
+  grub_uint64_t id;
+  grub_device_t dev_found;
+};
+
+/* Helper for find_device.  */
+static int
+find_device_iter (const char *name, void *data)
+{
+  struct find_device_ctx *ctx = data;
+  grub_device_t dev;
+  grub_err_t err;
+  struct grub_btrfs_superblock sb;
+
+  dev = grub_device_open (name);
+  if (!dev)
+    return 0;
+  if (!dev->disk)
+    {
+      grub_device_close (dev);
       return 0;
-    if (!dev->disk)
-      {
-       grub_device_close (dev);
-       return 0;
-      }
-    err = read_sblock (dev->disk, &sb);
-    if (err == GRUB_ERR_BAD_FS)
-      {
-       grub_device_close (dev);
-       grub_errno = GRUB_ERR_NONE;
-       return 0;
-      }
-    if (err)
-      {
-       grub_device_close (dev);
-       grub_print_error ();
-       return 0;
-      }
-    if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
-       || sb.this_device.device_id != id)
-      {
-       grub_device_close (dev);
-       return 0;
-      }
+    }
+  err = read_sblock (dev->disk, &sb);
+  if (err == GRUB_ERR_BAD_FS)
+    {
+      grub_device_close (dev);
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  if (err)
+    {
+      grub_device_close (dev);
+      grub_print_error ();
+      return 0;
+    }
+  if (grub_memcmp (ctx->data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0
+      || sb.this_device.device_id != ctx->id)
+    {
+      grub_device_close (dev);
+      return 0;
+    }
 
-    dev_found = dev;
-    return 1;
-  }
+  ctx->dev_found = dev;
+  return 1;
+}
 
+static grub_device_t
+find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
+{
+  struct find_device_ctx ctx = {
+    .data = data,
+    .id = id,
+    .dev_found = NULL
+  };
   unsigned i;
 
   for (i = 0; i < data->n_devices_attached; i++)
     if (id == data->devices_attached[i].id)
       return data->devices_attached[i].dev;
   if (do_rescan)
-    grub_device_iterate (hook);
-  if (!dev_found)
+    grub_device_iterate (find_device_iter, &ctx);
+  if (!ctx.dev_found)
     {
       grub_error (GRUB_ERR_BAD_FS,
                  N_("couldn't find a necessary member device "
@@ -605,14 +620,14 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
                        * sizeof (data->devices_attached[0]));
       if (!data->devices_attached)
        {
-         grub_device_close (dev_found);
+         grub_device_close (ctx.dev_found);
          data->devices_attached = tmp;
          return NULL;
        }
     }
   data->devices_attached[data->n_devices_attached - 1].id = id;
-  data->devices_attached[data->n_devices_attached - 1].dev = dev_found;
-  return dev_found;
+  data->devices_attached[data->n_devices_attached - 1].dev = ctx.dev_found;
+  return ctx.dev_found;
 }
 
 static grub_err_t
index ba0554a..6ef6db3 100644 (file)
@@ -988,43 +988,47 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data,
   return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label");
 }
 
-static grub_err_t
-scan_devices (struct grub_zfs_data *data)
+/* Helper for scan_devices.  */
+static int
+scan_devices_iter (const char *name, void *hook_data)
 {
-  auto int hook (const char *name);
-  int hook (const char *name)
-  {
-    grub_device_t dev;
-    grub_err_t err;
-    int inserted;
-    dev = grub_device_open (name);
-    if (!dev)
-      return 0;
-    if (!dev->disk)
-      {
-       grub_device_close (dev);
-       return 0;
-      }
-    err = scan_disk (dev, data, 0, &inserted);
-    if (err == GRUB_ERR_BAD_FS)
-      {
-       grub_device_close (dev);
-       grub_errno = GRUB_ERR_NONE;
-       return 0;
-      }
-    if (err)
-      {
-       grub_device_close (dev);
-       grub_print_error ();
-       return 0;
-      }
+  struct grub_zfs_data *data = hook_data;
+  grub_device_t dev;
+  grub_err_t err;
+  int inserted;
 
-    if (!inserted)
-      grub_device_close (dev);
-    
+  dev = grub_device_open (name);
+  if (!dev)
     return 0;
-  }
-  grub_device_iterate (hook);
+  if (!dev->disk)
+    {
+      grub_device_close (dev);
+      return 0;
+    }
+  err = scan_disk (dev, data, 0, &inserted);
+  if (err == GRUB_ERR_BAD_FS)
+    {
+      grub_device_close (dev);
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  if (err)
+    {
+      grub_device_close (dev);
+      grub_print_error ();
+      return 0;
+    }
+
+  if (!inserted)
+    grub_device_close (dev);
+  
+  return 0;
+}
+
+static grub_err_t
+scan_devices (struct grub_zfs_data *data)
+{
+  grub_device_iterate (scan_devices_iter, data);
   return GRUB_ERR_NONE;
 }
 
index 43240e9..3441ccb 100644 (file)
@@ -96,7 +96,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)),
 }
 
 static int
-grub_mini_print_devices (const char *name)
+grub_mini_print_devices (const char *name, void *data __attribute__ ((unused)))
 {
   grub_printf ("(%s) ", name);
 
@@ -119,7 +119,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)),
 {
   if (argc < 1)
     {
-      grub_device_iterate (grub_mini_print_devices);
+      grub_device_iterate (grub_mini_print_devices, NULL);
       grub_xputs ("\n");
       grub_refresh ();
     }
index 1261564..73b8ecc 100644 (file)
@@ -85,94 +85,107 @@ grub_device_close (grub_device_t device)
   return grub_errno;
 }
 
-int
-grub_device_iterate (int (*hook) (const char *name))
+struct part_ent
 {
-  auto int iterate_disk (const char *disk_name);
-  auto int iterate_partition (grub_disk_t disk,
-                             const grub_partition_t partition);
+  struct part_ent *next;
+  char *name;
+};
 
-  struct part_ent
-  {
-    struct part_ent *next;
-    char *name;
-  } *ents;
+/* Context for grub_device_iterate.  */
+struct grub_device_iterate_ctx
+{
+  grub_device_iterate_hook_t hook;
+  void *hook_data;
+  struct part_ent *ents;
+};
+
+/* Helper for grub_device_iterate.  */
+static int
+iterate_partition (grub_disk_t disk, const grub_partition_t partition,
+                  void *data)
+{
+  struct grub_device_iterate_ctx *ctx = data;
+  struct part_ent *p;
+  char *part_name;
 
-  int iterate_disk (const char *disk_name)
+  p = grub_malloc (sizeof (*p));
+  if (!p)
     {
-      grub_device_t dev;
-
-      if (hook (disk_name))
-       return 1;
-
-      dev = grub_device_open (disk_name);
-      if (! dev)
-       {
-         grub_errno = GRUB_ERR_NONE;
-         return 0;
-       }
-
-      if (dev->disk)
-       {
-         struct part_ent *p;
-         int ret = 0;
+      return 1;
+    }
 
-         ents = NULL;
-         (void) grub_partition_iterate (dev->disk, iterate_partition);
-         grub_device_close (dev);
+  part_name = grub_partition_get_name (partition);
+  if (!part_name)
+    {
+      grub_free (p);
+      return 1;
+    }
+  p->name = grub_xasprintf ("%s,%s", disk->name, part_name);
+  grub_free (part_name);
+  if (!p->name)
+    {
+      grub_free (p);
+      return 1;
+    }
 
-         grub_errno = GRUB_ERR_NONE;
+  p->next = ctx->ents;
+  ctx->ents = p;
 
-         p = ents;
-         while (p != NULL)
-           {
-             struct part_ent *next = p->next;
+  return 0;
+}
 
-             if (!ret)
-               ret = hook (p->name);
-             grub_free (p->name);
-             grub_free (p);
-             p = next;
-           }
+/* Helper for grub_device_iterate.  */
+static int
+iterate_disk (const char *disk_name, void *data)
+{
+  struct grub_device_iterate_ctx *ctx = data;
+  grub_device_t dev;
 
-         return ret;
-       }
+  if (ctx->hook (disk_name, ctx->hook_data))
+    return 1;
 
-      grub_device_close (dev);
+  dev = grub_device_open (disk_name);
+  if (! dev)
+    {
+      grub_errno = GRUB_ERR_NONE;
       return 0;
     }
 
-  int iterate_partition (grub_disk_t disk, const grub_partition_t partition)
+  if (dev->disk)
     {
       struct part_ent *p;
-      char *part_name;
+      int ret = 0;
 
-      p = grub_malloc (sizeof (*p));
-      if (!p)
-       {
-         return 1;
-       }
+      ctx->ents = NULL;
+      (void) grub_partition_iterate (dev->disk, iterate_partition, ctx);
+      grub_device_close (dev);
 
-      part_name = grub_partition_get_name (partition);
-      if (!part_name)
-       {
-         grub_free (p);
-         return 1;
-       }
-      p->name = grub_xasprintf ("%s,%s", disk->name, part_name);
-      grub_free (part_name);
-      if (!p->name)
+      grub_errno = GRUB_ERR_NONE;
+
+      p = ctx->ents;
+      while (p != NULL)
        {
+         struct part_ent *next = p->next;
+
+         if (!ret)
+           ret = ctx->hook (p->name, ctx->hook_data);
+         grub_free (p->name);
          grub_free (p);
-         return 1;
+         p = next;
        }
 
-      p->next = ents;
-      ents = p;
-
-      return 0;
+      return ret;
     }
 
+  grub_device_close (dev);
+  return 0;
+}
+
+int
+grub_device_iterate (grub_device_iterate_hook_t hook, void *hook_data)
+{
+  struct grub_device_iterate_ctx ctx = { hook, hook_data, NULL };
+
   /* Only disk devices are supported at the moment.  */
-  return grub_disk_dev_iterate (iterate_disk);
+  return grub_disk_dev_iterate (iterate_disk, &ctx);
 }
index ccd2417..92ce1d9 100644 (file)
@@ -223,7 +223,7 @@ find_free_slot (void)
 }
 
 static int
-grub_util_biosdisk_iterate (int (*hook) (const char *name),
+grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                            grub_disk_pull_t pull)
 {
   unsigned i;
@@ -232,7 +232,7 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name),
     return 0;
 
   for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
-    if (map[i].drive && hook (map[i].drive))
+    if (map[i].drive && hook (map[i].drive, hook_data))
       return 1;
 
   return 0;
index 4d680ed..f63ac6d 100644 (file)
@@ -48,8 +48,7 @@ const char *type_names[] = {
 
 static int
 iterate_rec (const char *prefix, const struct grub_arc_component *parent,
-            int (*hook) (const char *name,
-                         const struct grub_arc_component *comp),
+            grub_arc_iterate_devs_hook_t hook, void *hook_data,
             int alt_names)
 {
   const struct grub_arc_component *comp;
@@ -67,12 +66,13 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent,
        name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key);
       if (!name)
        return 1;
-      if (hook (name, comp))
+      if (hook (name, comp, hook_data))
        {
          grub_free (name);
          return 1;
        }
-      if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names))
+      if (iterate_rec ((parent ? name : prefix), comp, hook, hook_data,
+                      alt_names))
        {
          grub_free (name);
          return 1;
@@ -83,11 +83,11 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent,
 }
 
 int
-grub_arc_iterate_devs (int (*hook) (const char *name,
-                                   const struct grub_arc_component *comp),
+grub_arc_iterate_devs (grub_arc_iterate_devs_hook_t hook, void *hook_data,
                       int alt_names)
 {
-  return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names);
+  return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, hook_data,
+                     alt_names);
 }
 
 grub_err_t
index 82ae9c8..e499147 100644 (file)
@@ -59,39 +59,50 @@ grub_partition_check_containment (const grub_disk_t disk,
   return 1;
 }
 
-static grub_partition_t
-grub_partition_map_probe (const grub_partition_map_t partmap,
-                         grub_disk_t disk, int partnum)
+/* Context for grub_partition_map_probe.  */
+struct grub_partition_map_probe_ctx
 {
-  grub_partition_t p = 0;
+  int partnum;
+  grub_partition_t p;
+};
 
-  auto int find_func (grub_disk_t d, const grub_partition_t partition);
+/* Helper for grub_partition_map_probe.  */
+static int
+probe_iter (grub_disk_t dsk, const grub_partition_t partition, void *data)
+{
+  struct grub_partition_map_probe_ctx *ctx = data;
 
-  int find_func (grub_disk_t dsk,
-                const grub_partition_t partition)
-    {
-      if (partnum != partition->number)
-       return 0;
+  if (ctx->partnum != partition->number)
+    return 0;
 
-      if (!(grub_partition_check_containment (dsk, partition)))
-       return 0;
+  if (!(grub_partition_check_containment (dsk, partition)))
+    return 0;
 
-      p = (grub_partition_t) grub_malloc (sizeof (*p));
-      if (! p)
-       return 1;
+  ctx->p = (grub_partition_t) grub_malloc (sizeof (*ctx->p));
+  if (! ctx->p)
+    return 1;
 
-      grub_memcpy (p, partition, sizeof (*p));
-      return 1;
-    }
+  grub_memcpy (ctx->p, partition, sizeof (*ctx->p));
+  return 1;
+}
 
-  partmap->iterate (disk, find_func);
+static grub_partition_t
+grub_partition_map_probe (const grub_partition_map_t partmap,
+                         grub_disk_t disk, int partnum)
+{
+  struct grub_partition_map_probe_ctx ctx = {
+    .partnum = partnum,
+    .p = 0
+  };
+
+  partmap->iterate (disk, probe_iter, &ctx);
   if (grub_errno)
     goto fail;
 
-  return p;
+  return ctx.p;
 
  fail:
-  grub_free (p);
+  grub_free (ctx.p);
   return 0;
 }
 
@@ -162,62 +173,71 @@ grub_partition_probe (struct grub_disk *disk, const char *str)
   return part;
 }
 
-int
-grub_partition_iterate (struct grub_disk *disk,
-                       int (*hook) (grub_disk_t disk,
-                                    const grub_partition_t partition))
+/* Context for grub_partition_iterate.  */
+struct grub_partition_iterate_ctx
 {
-  int ret = 0;
-
-  auto int part_iterate (grub_disk_t dsk, const grub_partition_t p);
+  int ret;
+  grub_partition_iterate_hook_t hook;
+  void *hook_data;
+};
 
-  int part_iterate (grub_disk_t dsk,
-                   const grub_partition_t partition)
-    {
-      struct grub_partition p = *partition;
+/* Helper for grub_partition_iterate.  */
+static int
+part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data)
+{
+  struct grub_partition_iterate_ctx *ctx = data;
+  struct grub_partition p = *partition;
 
-      if (!(grub_partition_check_containment (dsk, partition)))
-       return 0;
+  if (!(grub_partition_check_containment (dsk, partition)))
+    return 0;
 
-      p.parent = dsk->partition;
-      dsk->partition = 0;
-      if (hook (dsk, &p))
-       {
-         ret = 1;
-         return 1;
-       }
-      if (p.start != 0)
-       {
-         const struct grub_partition_map *partmap;
-         dsk->partition = &p;
-         FOR_PARTITION_MAPS(partmap)
-         {
-           grub_err_t err;
-           err = partmap->iterate (dsk, part_iterate);
-           if (err)
-             grub_errno = GRUB_ERR_NONE;
-           if (ret)
-             break;
-         }
-       }
-      dsk->partition = p.parent;
-      return ret;
+  p.parent = dsk->partition;
+  dsk->partition = 0;
+  if (ctx->hook (dsk, &p, ctx->hook_data))
+    {
+      ctx->ret = 1;
+      return 1;
     }
-
-  {
-    const struct grub_partition_map *partmap;
-    FOR_PARTITION_MAPS(partmap)
+  if (p.start != 0)
     {
-      grub_err_t err;
-      err = partmap->iterate (disk, part_iterate);
-      if (err)
-       grub_errno = GRUB_ERR_NONE;
-      if (ret)
-       break;
+      const struct grub_partition_map *partmap;
+      dsk->partition = &p;
+      FOR_PARTITION_MAPS(partmap)
+      {
+       grub_err_t err;
+       err = partmap->iterate (dsk, part_iterate, ctx);
+       if (err)
+         grub_errno = GRUB_ERR_NONE;
+       if (ctx->ret)
+         break;
+      }
     }
+  dsk->partition = p.parent;
+  return ctx->ret;
+}
+
+int
+grub_partition_iterate (struct grub_disk *disk,
+                       grub_partition_iterate_hook_t hook, void *hook_data)
+{
+  struct grub_partition_iterate_ctx ctx = {
+    .ret = 0,
+    .hook = hook,
+    .hook_data = hook_data
+  };
+  const struct grub_partition_map *partmap;
+
+  FOR_PARTITION_MAPS(partmap)
+  {
+    grub_err_t err;
+    err = partmap->iterate (disk, part_iterate, &ctx);
+    if (err)
+      grub_errno = GRUB_ERR_NONE;
+    if (ctx.ret)
+      break;
   }
 
-  return ret;
+  return ctx.ret;
 }
 
 char *
index b41dfd2..7dc12a8 100644 (file)
@@ -102,248 +102,281 @@ grub_plan9_unload (void)
   return GRUB_ERR_NONE;
 }
 
-static grub_err_t
-grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
+/* Context for grub_cmd_plan9.  */
+struct grub_cmd_plan9_ctx
 {
-  grub_file_t file = 0;
-  void *mem;
-  grub_size_t memsize, padsize;
-  struct grub_plan9_header hdr;
-  char *config, *configptr;
-  grub_size_t configsize;
-  char *pmap = NULL;
-  grub_size_t pmapalloc = 256;
-  grub_size_t pmapptr = 0;
-  int noslash = 1;
-  char prefixes[5][10] = {"dos", "plan9", "ntfs", "linux", "linuxswap"};
+  grub_extcmd_context_t ctxt;
+  grub_file_t file;
+  char *pmap;
+  grub_size_t pmapalloc;
+  grub_size_t pmapptr;
+  int noslash;
   int prefixescnt[5];
-  char *bootdisk = NULL, *bootpart = NULL, *bootpath = NULL;
+  char *bootdisk, *bootpart;
+};
 
-  auto int fill_partition (grub_disk_t disk,
-                          const grub_partition_t partition);
-  int fill_partition (grub_disk_t disk,
-                     const grub_partition_t partition)
-  {
-    int file_disk = 0;
-    int pstart, pend;
-    if (!noslash)
-      {
-       if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap))
-         return 1;
-       pmap[pmapptr++] = '/';
-      }
-    noslash = 0;
+static const char prefixes[5][10] = {
+  "dos", "plan9", "ntfs", "linux", "linuxswap"
+};
 
-    file_disk = file->device->disk && disk->id == file->device->disk->id
-      && disk->dev->id == file->device->disk->dev->id;
+/* Helper for grub_cmd_plan9.  */
+static int
+fill_partition (grub_disk_t disk, const grub_partition_t partition, void *data)
+{
+  struct grub_cmd_plan9_ctx *fill_ctx = data;
+  int file_disk = 0;
+  int pstart, pend;
 
-    pstart = pmapptr;
-    if (grub_strcmp (partition->partmap->name, "plan") == 0)
-      {
-       unsigned ptr = partition->index + sizeof ("part ") - 1;
-       grub_err_t err;
-       disk->partition = partition->parent;
-       do
-         {
-           if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap))
-             return 1;
-           err = grub_disk_read (disk, 1, ptr, 1, pmap + pmapptr);
-           if (err)
-             {
-               disk->partition = 0;
-               return err;
-             }
-           ptr++;
-           pmapptr++;
-         }
-       while (grub_isalpha (pmap[pmapptr - 1])
-              || grub_isdigit (pmap[pmapptr - 1]));
-       pmapptr--;
-      }
-    else
-      {
-       char name[50];
-       int c = 0;
-       if (grub_strcmp (partition->partmap->name, "msdos") == 0)
-         {
-           switch (partition->msdostype)
-             {
-             case GRUB_PC_PARTITION_TYPE_PLAN9:
-               c = 1;
-               break;
-             case GRUB_PC_PARTITION_TYPE_NTFS:
-               c = 2;
-               break;
-             case GRUB_PC_PARTITION_TYPE_MINIX:
-             case GRUB_PC_PARTITION_TYPE_LINUX_MINIX:
-             case GRUB_PC_PARTITION_TYPE_EXT2FS:
-               c = 3;
-               break;
-             case GRUB_PC_PARTITION_TYPE_LINUX_SWAP:
-               c = 4;
-               break;
-             }
-         }
+  if (!fill_ctx->noslash)
+    {
+      if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
+                            (void **) &fill_ctx->pmap))
+       return 1;
+      fill_ctx->pmap[fill_ctx->pmapptr++] = '/';
+    }
+  fill_ctx->noslash = 0;
 
-       if (prefixescnt[c] == 0)
-         grub_strcpy (name, prefixes[c]);
-       else
-         grub_snprintf (name, sizeof (name), "%s.%d", prefixes[c],
-                        prefixescnt[c]);
-       prefixescnt[c]++;
-       if (grub_extend_alloc (pmapptr + grub_strlen (name) + 1,
-                              &pmapalloc, (void **) &pmap))
-         return 1;
-       grub_strcpy (pmap + pmapptr, name);
-       pmapptr += grub_strlen (name);
-      }
-    pend = pmapptr;
-    if (grub_extend_alloc (pmapptr + 2 + 25 + 5 + 25, &pmapalloc,
-                          (void **) &pmap))
-      return 1;
-    pmap[pmapptr++] = ' ';
-    grub_snprintf (pmap + pmapptr, 25 + 5 + 25,
-                  "%" PRIuGRUB_UINT64_T " %" PRIuGRUB_UINT64_T,
-                  grub_partition_get_start (partition),
-                  grub_partition_get_start (partition)
-                  + grub_partition_get_len (partition));
-    if (file_disk && grub_partition_get_start (partition)
-       == grub_partition_get_start (file->device->disk->partition)
-       && grub_partition_get_len (partition)
-       == grub_partition_get_len (file->device->disk->partition))
-      {
-       grub_free (bootpart);
-       bootpart = grub_strndup (pmap + pstart, pend - pstart);
-      }
+  file_disk = fill_ctx->file->device->disk
+    && disk->id == fill_ctx->file->device->disk->id
+    && disk->dev->id == fill_ctx->file->device->disk->dev->id;
 
-    pmapptr += grub_strlen (pmap + pmapptr);
-    return 0;
-  }
+  pstart = fill_ctx->pmapptr;
+  if (grub_strcmp (partition->partmap->name, "plan") == 0)
+    {
+      unsigned ptr = partition->index + sizeof ("part ") - 1;
+      grub_err_t err;
+      disk->partition = partition->parent;
+      do
+       {
+         if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
+                                (void **) &fill_ctx->pmap))
+           return 1;
+         err = grub_disk_read (disk, 1, ptr, 1,
+                               fill_ctx->pmap + fill_ctx->pmapptr);
+         if (err)
+           {
+             disk->partition = 0;
+             return err;
+           }
+         ptr++;
+         fill_ctx->pmapptr++;
+       }
+      while (grub_isalpha (fill_ctx->pmap[fill_ctx->pmapptr - 1])
+            || grub_isdigit (fill_ctx->pmap[fill_ctx->pmapptr - 1]));
+      fill_ctx->pmapptr--;
+    }
+  else
+    {
+      char name[50];
+      int c = 0;
+      if (grub_strcmp (partition->partmap->name, "msdos") == 0)
+       {
+         switch (partition->msdostype)
+           {
+           case GRUB_PC_PARTITION_TYPE_PLAN9:
+             c = 1;
+             break;
+           case GRUB_PC_PARTITION_TYPE_NTFS:
+             c = 2;
+             break;
+           case GRUB_PC_PARTITION_TYPE_MINIX:
+           case GRUB_PC_PARTITION_TYPE_LINUX_MINIX:
+           case GRUB_PC_PARTITION_TYPE_EXT2FS:
+             c = 3;
+             break;
+           case GRUB_PC_PARTITION_TYPE_LINUX_SWAP:
+             c = 4;
+             break;
+           }
+       }
 
-  auto int fill_disk (const char *name);
-  int fill_disk (const char *name)
-  {
-    grub_device_t dev;
-    char *plan9name = NULL;
-    unsigned i;
-    int file_disk = 0;
+      if (fill_ctx->prefixescnt[c] == 0)
+       grub_strcpy (name, prefixes[c]);
+      else
+       grub_snprintf (name, sizeof (name), "%s.%d", prefixes[c],
+                      fill_ctx->prefixescnt[c]);
+      fill_ctx->prefixescnt[c]++;
+      if (grub_extend_alloc (fill_ctx->pmapptr + grub_strlen (name) + 1,
+                            &fill_ctx->pmapalloc, (void **) &fill_ctx->pmap))
+       return 1;
+      grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, name);
+      fill_ctx->pmapptr += grub_strlen (name);
+    }
+  pend = fill_ctx->pmapptr;
+  if (grub_extend_alloc (fill_ctx->pmapptr + 2 + 25 + 5 + 25,
+                        &fill_ctx->pmapalloc, (void **) &fill_ctx->pmap))
+    return 1;
+  fill_ctx->pmap[fill_ctx->pmapptr++] = ' ';
+  grub_snprintf (fill_ctx->pmap + fill_ctx->pmapptr, 25 + 5 + 25,
+                "%" PRIuGRUB_UINT64_T " %" PRIuGRUB_UINT64_T,
+                grub_partition_get_start (partition),
+                grub_partition_get_start (partition)
+                + grub_partition_get_len (partition));
+  if (file_disk && grub_partition_get_start (partition)
+      == grub_partition_get_start (fill_ctx->file->device->disk->partition)
+      && grub_partition_get_len (partition)
+      == grub_partition_get_len (fill_ctx->file->device->disk->partition))
+    {
+      grub_free (fill_ctx->bootpart);
+      fill_ctx->bootpart = grub_strndup (fill_ctx->pmap + pstart,
+                                        pend - pstart);
+    }
 
-    dev = grub_device_open (name);
-    if (!dev)
-      {
-       grub_print_error ();
-       return 0;
-      }
-    if (!dev->disk)
+  fill_ctx->pmapptr += grub_strlen (fill_ctx->pmap + fill_ctx->pmapptr);
+  return 0;
+}
+
+/* Helper for grub_cmd_plan9.  */
+static int
+fill_disk (const char *name, void *data)
+{
+  struct grub_cmd_plan9_ctx *fill_ctx = data;
+  grub_device_t dev;
+  char *plan9name = NULL;
+  unsigned i;
+  int file_disk = 0;
+
+  dev = grub_device_open (name);
+  if (!dev)
+    {
+      grub_print_error ();
+      return 0;
+    }
+  if (!dev->disk)
+    {
+      grub_device_close (dev);
+      return 0;
+    }
+  file_disk = fill_ctx->file->device->disk
+    && dev->disk->id == fill_ctx->file->device->disk->id
+    && dev->disk->dev->id == fill_ctx->file->device->disk->dev->id;
+  for (i = 0;
+       fill_ctx->ctxt->state[0].args && fill_ctx->ctxt->state[0].args[i]; i++)
+    if (grub_strncmp (name, fill_ctx->ctxt->state[0].args[i],
+                     grub_strlen (name)) == 0
+       && fill_ctx->ctxt->state[0].args[i][grub_strlen (name)] == '=')
+      break;
+  if (fill_ctx->ctxt->state[0].args && fill_ctx->ctxt->state[0].args[i])
+    plan9name = grub_strdup (fill_ctx->ctxt->state[0].args[i]
+                            + grub_strlen (name) + 1);
+  else
+    switch (dev->disk->dev->id)
       {
-       grub_device_close (dev);
-       return 0;
-      }
-    file_disk = file->device->disk && dev->disk->id == file->device->disk->id
-      && dev->disk->dev->id == file->device->disk->dev->id;
-    for (i = 0; ctxt->state[0].args && ctxt->state[0].args[i]; i++)
-      if (grub_strncmp (name, ctxt->state[0].args[i], grub_strlen (name)) == 0
-         && ctxt->state[0].args[i][grub_strlen (name)] == '=')
+      case GRUB_DISK_DEVICE_BIOSDISK_ID:
+       if (dev->disk->id & 0x80)
+         plan9name = grub_xasprintf ("sdB%u",
+                                     (unsigned) (dev->disk->id & 0x7f));
+       else
+         plan9name = grub_xasprintf ("fd%u",
+                                     (unsigned) (dev->disk->id & 0x7f));
        break;
-    if (ctxt->state[0].args && ctxt->state[0].args[i])
-      plan9name = grub_strdup (ctxt->state[0].args[i] + grub_strlen (name) + 1);
-    else
-      switch (dev->disk->dev->id)
+       /* Shouldn't happen as Plan9 doesn't work on these platforms.  */
+      case GRUB_DISK_DEVICE_OFDISK_ID:
+      case GRUB_DISK_DEVICE_EFIDISK_ID:
+
+       /* Plan9 doesn't see those.  */
+      default:
+
+       /* Not sure how to handle those. */
+      case GRUB_DISK_DEVICE_NAND_ID:
+       if (!file_disk)
+         {
+           grub_device_close (dev);
+           return 0;
+         }
+       
+       /* if it's the disk the kernel is loaded from we need to name
+          it nevertheless.  */
+       plan9name = grub_strdup ("sdZ0");
+       break;
+
+      case GRUB_DISK_DEVICE_ATA_ID:
        {
-       case GRUB_DISK_DEVICE_BIOSDISK_ID:
-         if (dev->disk->id & 0x80)
-           plan9name = grub_xasprintf ("sdB%u",
-                                       (unsigned) (dev->disk->id & 0x7f));
+         int unit;
+         if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1)
+           unit = 0;
          else
-           plan9name = grub_xasprintf ("fd%u",
-                                       (unsigned) (dev->disk->id & 0x7f));
-         break;
-         /* Shouldn't happen as Plan9 doesn't work on these platforms.  */
-       case GRUB_DISK_DEVICE_OFDISK_ID:
-       case GRUB_DISK_DEVICE_EFIDISK_ID:
-
-         /* Plan9 doesn't see those.  */
-       default:
-
-         /* Not sure how to handle those. */
-       case GRUB_DISK_DEVICE_NAND_ID:
-         if (!file_disk)
-           {
-             grub_device_close (dev);
-             return 0;
-           }
-         
-         /* if it's the disk the kernel is loaded from we need to name
-            it nevertheless.  */
-         plan9name = grub_strdup ("sdZ0");
-         break;
-
-       case GRUB_DISK_DEVICE_ATA_ID:
+           unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0);
+         plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
+       }
+       break;
+      case GRUB_DISK_DEVICE_SCSI_ID:
+       if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff)
+           == GRUB_SCSI_SUBSYSTEM_PATA)
          {
            int unit;
            if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1)
              unit = 0;
            else
-             unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0);
+             unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1,
+                                  0, 0);
            plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
+           break;
          }
-         break;
-       case GRUB_DISK_DEVICE_SCSI_ID:
-         if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff)
-             == GRUB_SCSI_SUBSYSTEM_PATA)
-           {
-             int unit;
-             if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1)
-               unit = 0;
-             else
-               unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1,
-                                    0, 0);
-             plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2);
-             break;
-           }
-         
-         /* FIXME: how does Plan9 number controllers?
-            We probably need save the SCSI devices and sort them  */
-         plan9name
-           = grub_xasprintf ("sd0%u", (unsigned)
-                             ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT)
-                              & 0xf));
-         break;
-       }
-    if (!plan9name)
-      {
-       grub_print_error ();
-       return 0;
-      }
-    if (grub_extend_alloc (pmapptr + grub_strlen (plan9name)
-                          + sizeof ("part="), &pmapalloc,
-                          (void **) &pmap))
-      {
-       grub_free (plan9name);
-       return 1;
+       
+       /* FIXME: how does Plan9 number controllers?
+          We probably need save the SCSI devices and sort them  */
+       plan9name
+         = grub_xasprintf ("sd0%u", (unsigned)
+                           ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT)
+                            & 0xf));
+       break;
       }
-    grub_strcpy (pmap + pmapptr, plan9name);
-    pmapptr += grub_strlen (plan9name);
-    if (!file_disk)
+  if (!plan9name)
+    {
+      grub_print_error ();
+      return 0;
+    }
+  if (grub_extend_alloc (fill_ctx->pmapptr + grub_strlen (plan9name)
+                        + sizeof ("part="), &fill_ctx->pmapalloc,
+                        (void **) &fill_ctx->pmap))
+    {
       grub_free (plan9name);
-    else
-      {
-       grub_free (bootdisk);
-       bootdisk = plan9name;
-      }
-    grub_strcpy (pmap + pmapptr, "part=");
-    pmapptr += sizeof ("part=") - 1;
-
-    noslash = 1;
-    grub_memset (prefixescnt, 0, sizeof (prefixescnt));
-    if (grub_partition_iterate (dev->disk, fill_partition))
-      return 1;
-    if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap))
       return 1;
-    pmap[pmapptr++] = '\n';
+    }
+  grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, plan9name);
+  fill_ctx->pmapptr += grub_strlen (plan9name);
+  if (!file_disk)
+    grub_free (plan9name);
+  else
+    {
+      grub_free (fill_ctx->bootdisk);
+      fill_ctx->bootdisk = plan9name;
+    }
+  grub_strcpy (fill_ctx->pmap + fill_ctx->pmapptr, "part=");
+  fill_ctx->pmapptr += sizeof ("part=") - 1;
+
+  fill_ctx->noslash = 1;
+  grub_memset (fill_ctx->prefixescnt, 0, sizeof (fill_ctx->prefixescnt));
+  if (grub_partition_iterate (dev->disk, fill_partition, fill_ctx))
+    return 1;
+  if (grub_extend_alloc (fill_ctx->pmapptr + 1, &fill_ctx->pmapalloc,
+                        (void **) &fill_ctx->pmap))
+    return 1;
+  fill_ctx->pmap[fill_ctx->pmapptr++] = '\n';
+
+  return 0;
+}
 
-    return 0;
-  }
+static grub_err_t
+grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
+{
+  struct grub_cmd_plan9_ctx fill_ctx = {
+    .ctxt = ctxt,
+    .file = 0,
+    .pmap = NULL,
+    .pmapalloc = 256,
+    .pmapptr = 0,
+    .noslash = 1,
+    .bootdisk = NULL,
+    .bootpart = NULL
+  };
+  void *mem;
+  grub_size_t memsize, padsize;
+  struct grub_plan9_header hdr;
+  char *config, *configptr;
+  grub_size_t configsize;
+  char *bootpath = NULL;
 
   if (argc == 0)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
@@ -354,21 +387,21 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
   if (!rel)
     goto fail;
 
-  file = grub_file_open (argv[0]);
-  if (! file)
+  fill_ctx.file = grub_file_open (argv[0]);
+  if (! fill_ctx.file)
     goto fail;
 
-  pmap = grub_malloc (pmapalloc);
-  if (!pmap)
+  fill_ctx.pmap = grub_malloc (fill_ctx.pmapalloc);
+  if (!fill_ctx.pmap)
     goto fail;
 
-  if (grub_disk_dev_iterate (fill_disk))
+  if (grub_disk_dev_iterate (fill_disk, &fill_ctx))
     goto fail;
 
-  if (grub_extend_alloc (pmapptr + 1, &pmapalloc,
-                        (void **) &pmap))
+  if (grub_extend_alloc (fill_ctx.pmapptr + 1, &fill_ctx.pmapalloc,
+                        (void **) &fill_ctx.pmap))
     goto fail;
-  pmap[pmapptr] = 0;
+  fill_ctx.pmap[fill_ctx.pmapptr] = 0;
 
   {
     char *file_name = grub_strchr (argv[0], ')');
@@ -379,17 +412,19 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
     if (*file_name)
       file_name++;
 
-    if (bootpart)
-      bootpath = grub_xasprintf ("%s!%s!%s", bootdisk, bootpart, file_name);
+    if (fill_ctx.bootpart)
+      bootpath = grub_xasprintf ("%s!%s!%s", fill_ctx.bootdisk,
+                                fill_ctx.bootpart, file_name);
     else
-      bootpath = grub_xasprintf ("%s!%s", bootdisk, file_name);
-    grub_free (bootdisk);
-    grub_free (bootpart);
+      bootpath = grub_xasprintf ("%s!%s", fill_ctx.bootdisk, file_name);
+    grub_free (fill_ctx.bootdisk);
+    grub_free (fill_ctx.bootpart);
   }
   if (!bootpath)
     goto fail;
 
-  if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr))
+  if (grub_file_read (fill_ctx.file, &hdr,
+                     sizeof (hdr)) != (grub_ssize_t) sizeof (hdr))
     {
       if (!grub_errno)
        grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
@@ -420,7 +455,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
       configsize += grub_strlen (argv[i]) + 1;
   }
   configsize += (sizeof ("bootfile=") - 1) + grub_strlen (bootpath) + 1;
-  configsize += pmapptr;
+  configsize += fill_ctx.pmapptr;
   /* Terminating \0.  */
   configsize++;
 
@@ -452,7 +487,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
        *configptr++ = '\n';
       }
   }
-  configptr = grub_stpcpy (configptr, pmap);
+  configptr = grub_stpcpy (configptr, fill_ctx.pmap);
 
   {
     grub_relocator_chunk_t ch;
@@ -471,7 +506,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
     grub_memcpy (ptr, &hdr, sizeof (hdr));
     ptr += sizeof (hdr);
 
-    if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size))
+    if (grub_file_read (fill_ctx.file, ptr, grub_be_to_cpu32 (hdr.text_size))
        != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size))
       {
        if (!grub_errno)
@@ -487,7 +522,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
     grub_memset (ptr, 0, padsize);
     ptr += padsize;
 
-    if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size))
+    if (grub_file_read (fill_ctx.file, ptr, grub_be_to_cpu32 (hdr.data_size))
        != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size))
       {
        if (!grub_errno)
@@ -508,10 +543,10 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[])
   return GRUB_ERR_NONE;
 
  fail:
-  grub_free (pmap);
+  grub_free (fill_ctx.pmap);
 
-  if (file)
-    grub_file_close (file);
+  if (fill_ctx.file)
+    grub_file_close (fill_ctx.file);
 
   grub_plan9_unload ();
 
index 805f002..367a2b7 100644 (file)
@@ -99,7 +99,8 @@ add_completion (const char *completion, const char *extra,
 }
 
 static int
-iterate_partition (grub_disk_t disk, const grub_partition_t p)
+iterate_partition (grub_disk_t disk, const grub_partition_t p,
+                  void *data __attribute__ ((unused)))
 {
   const char *disk_name = disk->name;
   char *name;
@@ -154,7 +155,7 @@ iterate_dir (const char *filename, const struct grub_dirhook_info *info)
 }
 
 static int
-iterate_dev (const char *devname)
+iterate_dev (const char *devname, void *data __attribute__ ((unused)))
 {
   grub_device_t dev;
 
@@ -180,7 +181,7 @@ iterate_dev (const char *devname)
          }
 
        if (dev->disk)
-         if (grub_partition_iterate (dev->disk, iterate_partition))
+         if (grub_partition_iterate (dev->disk, iterate_partition, NULL))
            {
              grub_device_close (dev);
              return 1;
@@ -213,7 +214,7 @@ complete_device (void)
   if (! p)
     {
       /* Complete the disk part.  */
-      if (grub_disk_dev_iterate (iterate_dev))
+      if (grub_disk_dev_iterate (iterate_dev, NULL))
        return 1;
     }
   else
@@ -228,7 +229,7 @@ complete_device (void)
        {
          if (dev->disk)
            {
-             if (grub_partition_iterate (dev->disk, iterate_partition))
+             if (grub_partition_iterate (dev->disk, iterate_partition, NULL))
                {
                  grub_device_close (dev);
                  return 1;
index 341b8ac..4d7f500 100644 (file)
@@ -101,8 +101,8 @@ fail:
 
 static grub_err_t
 acorn_partition_map_iterate (grub_disk_t disk,
-                            int (*hook) (grub_disk_t disk,
-                                         const grub_partition_t partition))
+                            grub_partition_iterate_hook_t hook,
+                            void *hook_data)
 {
   struct grub_partition part;
   struct linux_part map[LINUX_MAP_ENTRIES];
@@ -127,7 +127,7 @@ acorn_partition_map_iterate (grub_disk_t disk,
       part.offset = 6;
       part.number = part.index = i;
 
-      if (hook (disk, &part))
+      if (hook (disk, &part, hook_data))
        return grub_errno;
     }
 
index 0b89cdc..213d707 100644 (file)
@@ -87,8 +87,8 @@ amiga_partition_map_checksum (void *buf, grub_size_t sz)
 
 static grub_err_t
 amiga_partition_map_iterate (grub_disk_t disk,
-                            int (*hook) (grub_disk_t disk,
-                                         const grub_partition_t partition))
+                            grub_partition_iterate_hook_t hook,
+                            void *hook_data)
 {
   struct grub_partition part;
   struct grub_amiga_rdsk rdsk;
@@ -145,7 +145,7 @@ amiga_partition_map_iterate (grub_disk_t disk,
       part.index = 0;
       part.partmap = &grub_amiga_partition_map;
 
-      if (hook (disk, &part))
+      if (hook (disk, &part, hook_data))
        return grub_errno;
 
       next = grub_be_to_cpu32 (apart.next);
index c08cae5..f4e608f 100644 (file)
@@ -101,8 +101,8 @@ static struct grub_partition_map grub_apple_partition_map;
 
 static grub_err_t
 apple_partition_map_iterate (grub_disk_t disk,
-                            int (*hook) (grub_disk_t disk,
-                                         const grub_partition_t partition))
+                            grub_partition_iterate_hook_t hook,
+                            void *hook_data)
 {
   struct grub_partition part;
   struct grub_apple_header aheader;
@@ -163,7 +163,7 @@ apple_partition_map_iterate (grub_disk_t disk,
                    grub_be_to_cpu32 (apart.first_phys_block),
                    grub_be_to_cpu32 (apart.blockcnt));
 
-      if (hook (disk, &part))
+      if (hook (disk, &part, hook_data))
        return grub_errno;
 
       pos += grub_be_to_cpu16 (aheader.blocksize);
index c806f19..16b9c87 100644 (file)
@@ -41,8 +41,7 @@ static struct grub_partition_map grub_openbsdlabel_partition_map;
 static grub_err_t
 iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
              struct grub_partition_map *pmap,
-             int (*hook) (grub_disk_t disk,
-                          const grub_partition_t partition))
+             grub_partition_iterate_hook_t hook, void *hook_data)
 {
   struct grub_partition_bsd_disk_label label;
   struct grub_partition p;
@@ -116,7 +115,7 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
 
       p.start -= delta;
 
-      if (hook (disk, &p))
+      if (hook (disk, &p, hook_data))
        return grub_errno;
     }
   return GRUB_ERR_NONE;
@@ -124,14 +123,14 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd,
 
 static grub_err_t
 bsdlabel_partition_map_iterate (grub_disk_t disk,
-                               int (*hook) (grub_disk_t disk,
-                                            const grub_partition_t partition))
+                               grub_partition_iterate_hook_t hook,
+                               void *hook_data)
 {
 
   if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
       == 0 && disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_FREEBSD)
     return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 1,
-                        &grub_bsdlabel_partition_map, hook);
+                        &grub_bsdlabel_partition_map, hook, hook_data);
 
   if (disk->partition 
       && (grub_strcmp (disk->partition->partmap->name, "msdos") == 0
@@ -141,7 +140,44 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
       return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
 
   return iterate_real (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, 
-                      &grub_bsdlabel_partition_map, hook);
+                      &grub_bsdlabel_partition_map, hook, hook_data);
+}
+
+/* Context for netopenbsdlabel_partition_map_iterate.  */
+struct netopenbsdlabel_ctx
+{
+  grub_uint8_t type;
+  struct grub_partition_map *pmap;
+  grub_partition_iterate_hook_t hook;
+  void *hook_data;
+  int count;
+};
+
+/* Helper for netopenbsdlabel_partition_map_iterate.  */
+static int
+check_msdos (grub_disk_t dsk, const grub_partition_t partition, void *data)
+{
+  struct netopenbsdlabel_ctx *ctx = data;
+  grub_err_t err;
+
+  if (partition->msdostype != ctx->type)
+    return 0;
+
+  err = iterate_real (dsk, partition->start
+                     + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, ctx->pmap,
+                     ctx->hook, ctx->hook_data);
+  if (err == GRUB_ERR_NONE)
+    {
+      ctx->count++;
+      return 1;
+    }
+  if (err == GRUB_ERR_BAD_PART_TABLE)
+    {
+      grub_errno = GRUB_ERR_NONE;
+      return 0;
+    }
+  grub_print_error ();
+  return 0;
 }
 
 /* This is a total breakage. Even when net-/openbsd label is inside partition
@@ -150,45 +186,26 @@ bsdlabel_partition_map_iterate (grub_disk_t disk,
 static grub_err_t
 netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
                                       struct grub_partition_map *pmap,
-                                      int (*hook) (grub_disk_t disk,
-                                                   const grub_partition_t partition))
+                                      grub_partition_iterate_hook_t hook,
+                                      void *hook_data)
 {
   int count = 0;
 
-  auto int check_msdos (grub_disk_t dsk,
-                       const grub_partition_t partition);
-
-  int check_msdos (grub_disk_t dsk,
-                  const grub_partition_t partition)
-  {
-    grub_err_t err;
-
-    if (partition->msdostype != type)
-      return 0;
-
-    err = iterate_real (dsk, partition->start
-                       + GRUB_PC_PARTITION_BSD_LABEL_SECTOR, 0, pmap, hook);
-    if (err == GRUB_ERR_NONE)
-      {
-       count++;
-       return 1;
-      }
-    if (err == GRUB_ERR_BAD_PART_TABLE)
-      {
-       grub_errno = GRUB_ERR_NONE;
-       return 0;
-      }
-    grub_print_error ();
-    return 0;
-  }
-
   if (disk->partition && grub_strcmp (disk->partition->partmap->name, "msdos")
       == 0)
     return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
 
   {
+    struct netopenbsdlabel_ctx ctx = {
+      .type = type,
+      .pmap = pmap,
+      .hook = hook,
+      .hook_data = hook_data,
+      .count = count
+    };
     grub_err_t err;
-    err = grub_partition_msdos_iterate (disk, check_msdos);
+
+    err = grub_partition_msdos_iterate (disk, check_msdos, &ctx);
 
     if (err)
       return err;
@@ -200,24 +217,24 @@ netopenbsdlabel_partition_map_iterate (grub_disk_t disk, grub_uint8_t type,
 
 static grub_err_t
 netbsdlabel_partition_map_iterate (grub_disk_t disk,
-                                  int (*hook) (grub_disk_t disk,
-                                               const grub_partition_t partition))
+                                  grub_partition_iterate_hook_t hook,
+                                  void *hook_data)
 {
   return netopenbsdlabel_partition_map_iterate (disk,
                                                GRUB_PC_PARTITION_TYPE_NETBSD,
                                                &grub_netbsdlabel_partition_map,
-                                               hook);
+                                               hook, hook_data);
 }
 
 static grub_err_t
 openbsdlabel_partition_map_iterate (grub_disk_t disk,
-                                  int (*hook) (grub_disk_t disk,
-                                               const grub_partition_t partition))
+                                   grub_partition_iterate_hook_t hook,
+                                   void *hook_data)
 {
   return netopenbsdlabel_partition_map_iterate (disk,
                                                GRUB_PC_PARTITION_TYPE_OPENBSD,
                                                &grub_openbsdlabel_partition_map,
-                                               hook);
+                                               hook, hook_data);
 }
 
 
index 79ec01b..5b464da 100644 (file)
@@ -64,8 +64,7 @@ grub_dvh_is_valid (grub_uint32_t *label)
 
 static grub_err_t
 dvh_partition_map_iterate (grub_disk_t disk,
-                           int (*hook) (grub_disk_t disk,
-                                       const grub_partition_t partition))
+                          grub_partition_iterate_hook_t hook, void *hook_data)
 {
   struct grub_partition p;
   union
@@ -101,7 +100,7 @@ dvh_partition_map_iterate (grub_disk_t disk,
       p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start);
       p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length);
       p.number = p.index = partnum;
-      if (hook (disk, &p))
+      if (hook (disk, &p, hook_data))
        break;
     }
 
index 17f242d..38df7b3 100644 (file)
@@ -48,8 +48,8 @@ static struct grub_partition_map grub_gpt_partition_map;
 
 grub_err_t
 grub_gpt_partition_map_iterate (grub_disk_t disk,
-                               int (*hook) (grub_disk_t disk,
-                                            const grub_partition_t partition))
+                               grub_partition_iterate_hook_t hook,
+                               void *hook_data)
 {
   struct grub_partition part;
   struct grub_gpt_header gpt;
@@ -113,7 +113,7 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
                        (unsigned long long) part.start,
                        (unsigned long long) part.len);
 
-         if (hook (disk, &part))
+         if (hook (disk, &part, hook_data))
            return grub_errno;
        }
 
@@ -129,71 +129,81 @@ grub_gpt_partition_map_iterate (grub_disk_t disk,
 }
 
 #ifdef GRUB_UTIL
+/* Context for gpt_partition_map_embed.  */
+struct gpt_partition_map_embed_ctx
+{
+  grub_disk_addr_t start, len;
+};
+
+/* Helper for gpt_partition_map_embed.  */
+static int
+find_usable_region (grub_disk_t disk __attribute__ ((unused)),
+                   const grub_partition_t p, void *data)
+{
+  struct gpt_partition_map_embed_ctx *ctx = data;
+  struct grub_gpt_partentry gptdata;
+  grub_partition_t p2;
+
+  p2 = disk->partition;
+  disk->partition = p->parent;
+  if (grub_disk_read (disk, p->offset, p->index,
+                     sizeof (gptdata), &gptdata))
+    {
+      disk->partition = p2;
+      return 0;
+    }
+  disk->partition = p2;
+
+  /* If there's an embed region, it is in a dedicated partition.  */
+  if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16))
+    {
+      ctx->start = p->start;
+      ctx->len = p->len;
+      return 1;
+    }
+
+  return 0;
+}
+
 static grub_err_t
-gpt_partition_map_embed (struct grub_disk *disk_, unsigned int *nsectors,
+gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
                         unsigned int max_nsectors,
                         grub_embed_type_t embed_type,
                         grub_disk_addr_t **sectors)
 {
-  grub_disk_addr_t start = 0, len = 0;
+  struct gpt_partition_map_embed_ctx ctx = {
+    .start = 0,
+    .len = 0
+  };
   unsigned i;
   grub_err_t err;
 
-  auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk,
-                                               const grub_partition_t p);
-  int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)),
-                                          const grub_partition_t p)
-  {
-    struct grub_gpt_partentry gptdata;
-    grub_partition_t p2;
-
-    p2 = disk->partition;
-    disk->partition = p->parent;
-    if (grub_disk_read (disk, p->offset, p->index,
-                       sizeof (gptdata), &gptdata))
-      {
-       disk->partition = p2;
-       return 0;
-      }
-    disk->partition = p2;
-
-    /* If there's an embed region, it is in a dedicated partition.  */
-    if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16))
-      {
-       start = p->start;
-       len = p->len;
-       return 1;
-      }
-
-      return 0;
-    }
-
   if (embed_type != GRUB_EMBED_PCBIOS)
     return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
                       "GPT currently supports only PC-BIOS embedding");
 
-  err = grub_gpt_partition_map_iterate (disk_, find_usable_region);
+  err = grub_gpt_partition_map_iterate (disk, find_usable_region, &ctx);
   if (err)
     return err;
 
-  if (len == 0)
+  if (ctx.len == 0)
     return grub_error (GRUB_ERR_FILE_NOT_FOUND,
                       N_("this GPT partition label contains no BIOS Boot Partition;"
                          " embedding won't be possible"));
 
-  if (len < *nsectors)
+  if (ctx.len < *nsectors)
     return grub_error (GRUB_ERR_OUT_OF_RANGE,
                       N_("your BIOS Boot Partition is too small;"
                          " embedding won't be possible"));
 
-  *nsectors = len;
+  *nsectors = ctx.len;
   if (*nsectors > max_nsectors)
     *nsectors = max_nsectors;
   *sectors = grub_malloc (*nsectors * sizeof (**sectors));
   if (!*sectors)
     return grub_errno;
   for (i = 0; i < *nsectors; i++)
-    (*sectors)[i] = start + i;
+    (*sectors)[i] = ctx.start + i;
 
   return GRUB_ERR_NONE;
 }
index 10ca3f0..47527c3 100644 (file)
@@ -100,8 +100,8 @@ struct embed_signature embed_signatures[] =
 
 grub_err_t
 grub_partition_msdos_iterate (grub_disk_t disk,
-                             int (*hook) (grub_disk_t disk,
-                                          const grub_partition_t partition))
+                             grub_partition_iterate_hook_t hook,
+                             void *hook_data)
 {
   struct grub_partition p;
   struct grub_msdos_partition_mbr mbr;
@@ -186,7 +186,7 @@ grub_partition_msdos_iterate (grub_disk_t disk,
            {
              p.number++;
 
-             if (hook (disk, &p))
+             if (hook (disk, &p, hook_data))
                return grub_errno;
            }
          else if (p.number < 4)
index e6e3113..83db224 100644 (file)
@@ -31,8 +31,8 @@ static struct grub_partition_map grub_plan_partition_map;
 
 static grub_err_t
 plan_partition_map_iterate (grub_disk_t disk,
-                           int (*hook) (grub_disk_t disk,
-                                        const grub_partition_t partition))
+                           grub_partition_iterate_hook_t hook,
+                           void *hook_data)
 {
   struct grub_partition p;
   int ptr = 0;
@@ -92,7 +92,7 @@ plan_partition_map_iterate (grub_disk_t disk,
       if (c != '\n')
        break;
       p.len -= p.start;
-      if (hook (disk, &p))
+      if (hook (disk, &p, hook_data))
        return grub_errno;
     }
   if (p.number == 0)
index dfe51f3..cff09ae 100644 (file)
@@ -86,8 +86,7 @@ grub_sun_is_valid (grub_uint16_t *label)
 
 static grub_err_t
 sun_partition_map_iterate (grub_disk_t disk,
-                           int (*hook) (grub_disk_t disk,
-                                       const grub_partition_t partition))
+                          grub_partition_iterate_hook_t hook, void *hook_data)
 {
   struct grub_partition p;
   union
@@ -128,7 +127,7 @@ sun_partition_map_iterate (grub_disk_t disk,
       p.number = p.index = partnum;
       if (p.len)
        {
-         if (hook (disk, &p))
+         if (hook (disk, &p, hook_data))
            partnum = GRUB_PARTMAP_SUN_MAX_PARTS;
        }
     }
index 1c1fdce..7034272 100644 (file)
@@ -68,8 +68,8 @@ grub_sun_is_valid (grub_uint16_t *label)
 
 static grub_err_t
 sun_pc_partition_map_iterate (grub_disk_t disk,
-                             int (*hook) (grub_disk_t disk,
-                                          const grub_partition_t partition))
+                             grub_partition_iterate_hook_t hook,
+                             void *hook_data)
 {
   grub_partition_t p;
   union
@@ -122,7 +122,7 @@ sun_pc_partition_map_iterate (grub_disk_t disk,
       p->number = partnum;
       if (p->len)
        {
-         if (hook (disk, p))
+         if (hook (disk, p, hook_data))
            partnum = GRUB_PARTMAP_SUN_PC_MAX_PARTS;
        }
     }
index a825a98..739926f 100644 (file)
@@ -255,7 +255,12 @@ struct grub_arc_system_parameter_block
 #define GRUB_ARC_STDIN 0
 #define GRUB_ARC_STDOUT 1
 
-int EXPORT_FUNC (grub_arc_iterate_devs) (int (*hook) (const char *name, const struct grub_arc_component *comp), int alt_names);
+typedef int (*grub_arc_iterate_devs_hook_t)
+  (const char *name, const struct grub_arc_component *comp, void *data);
+
+int EXPORT_FUNC (grub_arc_iterate_devs) (grub_arc_iterate_devs_hook_t hook,
+                                        void *hook_data,
+                                        int alt_names);
 
 #define FOR_ARC_CHILDREN(comp, parent) for (comp = GRUB_ARC_FIRMWARE_VECTOR->getchild (parent); comp; comp = GRUB_ARC_FIRMWARE_VECTOR->getpeer (comp))
 
index efba7b7..e8a84b8 100644 (file)
@@ -193,10 +193,12 @@ struct grub_ata
 
 typedef struct grub_ata *grub_ata_t;
 
+typedef int (*grub_ata_dev_iterate_hook_t) (int id, int bus, void *data);
+
 struct grub_ata_dev
 {
   /* Call HOOK with each device name, until HOOK returns non-zero.  */
-  int (*iterate) (int (*hook) (int id, int bus),
+  int (*iterate) (grub_ata_dev_iterate_hook_t hook, void *hook_data,
                  grub_disk_pull_t pull);
 
   /* Open the device named NAME, and set up SCSI.  */
index f3e43bf..1d1a239 100644 (file)
@@ -33,8 +33,11 @@ struct grub_device
 };
 typedef struct grub_device *grub_device_t;
 
+typedef int (*grub_device_iterate_hook_t) (const char *name, void *data);
+
 grub_device_t EXPORT_FUNC(grub_device_open) (const char *name);
 grub_err_t EXPORT_FUNC(grub_device_close) (grub_device_t device);
-int EXPORT_FUNC(grub_device_iterate) (int (*hook) (const char *name));
+int EXPORT_FUNC(grub_device_iterate) (grub_device_iterate_hook_t hook,
+                                     void *hook_data);
 
 #endif /* ! GRUB_DEVICE_HEADER */
index 096173d..013ca1f 100644 (file)
@@ -56,6 +56,8 @@ typedef enum
     GRUB_DISK_PULL_MAX
   } grub_disk_pull_t;
 
+typedef int (*grub_disk_dev_iterate_hook_t) (const char *name, void *data);
+
 /* Disk device.  */
 struct grub_disk_dev
 {
@@ -66,7 +68,7 @@ struct grub_disk_dev
   enum grub_disk_dev_id id;
 
   /* Call HOOK with each device name, until HOOK returns non-zero.  */
-  int (*iterate) (int (*hook) (const char *name),
+  int (*iterate) (grub_disk_dev_iterate_hook_t hook, void *hook_data,
                  grub_disk_pull_t pull);
 
   /* Open the device named NAME, and set up DISK.  */
@@ -158,14 +160,14 @@ void grub_disk_cache_invalidate_all (void);
 void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev);
 void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev);
 static inline int
-grub_disk_dev_iterate (int (*hook) (const char *name))
+grub_disk_dev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data)
 {
   grub_disk_dev_t p;
   grub_disk_pull_t pull;
 
   for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++)
     for (p = grub_disk_dev_list; p; p = p->next)
-      if (p->iterate && (p->iterate) (hook, pull))
+      if (p->iterate && (p->iterate) (hook, hook_data, pull))
        return 1;
 
   return 0;
index 83e3b31..4aaf1c4 100644 (file)
@@ -80,8 +80,8 @@ struct grub_gpt_partentry
 
 grub_err_t
 grub_gpt_partition_map_iterate (grub_disk_t disk,
-                               int (*hook) (grub_disk_t disk,
-                                            const grub_partition_t partition));
+                               grub_partition_iterate_hook_t hook,
+                               void *hook_data);
 
 
 #endif /* ! GRUB_GPT_PARTITION_HEADER */
index 9c8ac3e..1e9b65e 100644 (file)
@@ -120,7 +120,7 @@ grub_msdos_partition_is_extended (int type)
 
 grub_err_t
 grub_partition_msdos_iterate (grub_disk_t disk,
-                             int (*hook) (grub_disk_t disk,
-                                          const grub_partition_t partition));
+                             grub_partition_iterate_hook_t hook,
+                             void *hook_data);
 
 #endif /* ! GRUB_PC_PARTITION_HEADER */
index ec0a667..7adb7ec 100644 (file)
@@ -33,6 +33,10 @@ typedef enum
 } grub_embed_type_t;
 #endif
 
+typedef int (*grub_partition_iterate_hook_t) (struct grub_disk *disk,
+                                             const grub_partition_t partition,
+                                             void *data);
+
 /* Partition map type.  */
 struct grub_partition_map
 {
@@ -45,8 +49,7 @@ struct grub_partition_map
 
   /* Call HOOK with each partition, until HOOK returns non-zero.  */
   grub_err_t (*iterate) (struct grub_disk *disk,
-                        int (*hook) (struct grub_disk *disk,
-                                     const grub_partition_t partition));
+                        grub_partition_iterate_hook_t hook, void *hook_data);
 #ifdef GRUB_UTIL
   /* Determine sectors available for embedding.  */
   grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors,
@@ -89,8 +92,8 @@ struct grub_partition
 grub_partition_t EXPORT_FUNC(grub_partition_probe) (struct grub_disk *disk,
                                                    const char *str);
 int EXPORT_FUNC(grub_partition_iterate) (struct grub_disk *disk,
-                                        int (*hook) (struct grub_disk *disk,
-                                                     const grub_partition_t partition));
+                                        grub_partition_iterate_hook_t hook,
+                                        void *hook_data);
 char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition);
 
 
index 13300ca..a919a7c 100644 (file)
@@ -49,10 +49,13 @@ grub_make_scsi_id (int subsystem, int bus, int lun)
     | (bus << GRUB_SCSI_ID_BUS_SHIFT) | (lun << GRUB_SCSI_ID_LUN_SHIFT);
 }
 
+typedef int (*grub_scsi_dev_iterate_hook_t) (int id, int bus, int luns,
+                                            void *data);
+
 struct grub_scsi_dev
 {
   /* Call HOOK with each device name, until HOOK returns non-zero.  */
-  int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
+  int (*iterate) (grub_scsi_dev_iterate_hook_t hook, void *hook_data,
                  grub_disk_pull_t pull);
 
   /* Open the device named NAME, and set up SCSI.  */
index 3b5b0f6..654d1e1 100644 (file)
@@ -2198,6 +2198,36 @@ grub_util_get_os_disk (const char *os_dev)
   return convert_system_partition_to_system_disk (os_dev, &st, &is_part);
 }
 
+#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__)
+/* Context for grub_util_biosdisk_get_grub_dev.  */
+struct grub_util_biosdisk_get_grub_dev_ctx
+{
+  char *partname;
+  grub_disk_addr_t start;
+};
+
+/* Helper for grub_util_biosdisk_get_grub_dev.  */
+static int
+find_partition (grub_disk_t dsk __attribute__ ((unused)),
+               const grub_partition_t partition, void *data)
+{
+  struct grub_util_biosdisk_get_grub_dev_ctx *ctx = data;
+  grub_disk_addr_t part_start = 0;
+  grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T,
+                 partition->number, partition->start);
+
+  part_start = grub_partition_get_start (partition);
+
+  if (ctx->start == part_start)
+    {
+      ctx->partname = grub_partition_get_name (partition);
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
 char *
 grub_util_biosdisk_get_grub_dev (const char *os_dev)
 {
@@ -2250,29 +2280,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
      For NetBSD and FreeBSD, proceed as for Linux, except that the start
      sector is obtained from the disk label.  */
   {
-    char *name, *partname;
+    char *name;
     grub_disk_t disk;
-    grub_disk_addr_t start;
-    auto int find_partition (grub_disk_t dsk,
-                            const grub_partition_t partition);
-
-    int find_partition (grub_disk_t dsk __attribute__ ((unused)),
-                       const grub_partition_t partition)
-      {
-       grub_disk_addr_t part_start = 0;
-       grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T,
-                       partition->number, partition->start);
-
-       part_start = grub_partition_get_start (partition);
-
-       if (start == part_start)
-         {
-           partname = grub_partition_get_name (partition);
-           return 1;
-         }
-
-       return 0;
-      }
+    struct grub_util_biosdisk_get_grub_dev_ctx ctx;
 
     name = make_device_name (drive, -1, -1);
 
@@ -2284,16 +2294,16 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
      * different, we know that os_dev cannot be a floppy device.  */
 # endif /* !defined(HAVE_DIOCGDINFO) */
 
-    start = grub_hostdisk_find_partition_start (os_dev);
+    ctx.start = grub_hostdisk_find_partition_start (os_dev);
     if (grub_errno != GRUB_ERR_NONE)
       {
        free (name);
        return 0;
       }
 
-    grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, start);
+    grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, ctx.start);
 
-    if (start == 0 && !is_part)
+    if (ctx.start == 0 && !is_part)
       return name;
 
     grub_util_info ("opening the device %s", name);
@@ -2325,20 +2335,20 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
          return 0;
       }
 
-    name = grub_util_get_ldm (disk, start);
+    name = grub_util_get_ldm (disk, ctx.start);
     if (name)
       return name;
 
-    partname = NULL;
+    ctx.partname = NULL;
 
-    grub_partition_iterate (disk, find_partition);
+    grub_partition_iterate (disk, find_partition, &ctx);
     if (grub_errno != GRUB_ERR_NONE)
       {
        grub_disk_close (disk);
        return 0;
       }
 
-    if (partname == NULL)
+    if (ctx.partname == NULL)
       {
        grub_disk_close (disk);
        grub_util_info ("cannot find the partition of `%s'", os_dev);
@@ -2347,8 +2357,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
        return 0;
       }
 
-    name = grub_xasprintf ("%s,%s", disk->name, partname);
-    free (partname);
+    name = grub_xasprintf ("%s,%s", disk->name, ctx.partname);
+    free (ctx.partname);
     grub_disk_close (disk);
     return name;
   }
index de0417f..187345a 100644 (file)
@@ -138,6 +138,44 @@ write_rootdev (grub_device_t root_dev,
 #define BOOT_SECTOR 0
 #endif
 
+#ifdef GRUB_SETUP_BIOS
+/* Context for setup/identify_partmap.  */
+struct identify_partmap_ctx
+{
+  grub_partition_map_t dest_partmap;
+  grub_partition_t container;
+  int multiple_partmaps;
+};
+
+/* Helper for setup/identify_partmap.
+   Unlike root_dev, with dest_dev we're interested in the partition map even
+   if dest_dev itself is a whole disk.  */
+static int
+identify_partmap (grub_disk_t disk __attribute__ ((unused)),
+                 const grub_partition_t p, void *data)
+{
+  struct identify_partmap_ctx *ctx = data;
+
+  if (p->parent != ctx->container)
+    return 0;
+  /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
+     so they are safe to ignore.
+   */
+  if (grub_strcmp (p->partmap->name, "netbsd") == 0
+      || grub_strcmp (p->partmap->name, "openbsd") == 0)
+    return 0;
+  if (ctx->dest_partmap == NULL)
+    {
+      ctx->dest_partmap = p->partmap;
+      return 0;
+    }
+  if (ctx->dest_partmap == p->partmap)
+    return 0;
+  ctx->multiple_partmaps = 1;
+  return 1;
+}
+#endif
+
 static void
 setup (const char *dir,
        const char *boot_file, const char *core_file,
@@ -337,9 +375,11 @@ setup (const char *dir,
 
 #ifdef GRUB_SETUP_BIOS
   {
-    grub_partition_map_t dest_partmap = NULL;
-    grub_partition_t container = dest_dev->disk->partition;
-    int multiple_partmaps = 0;
+    struct identify_partmap_ctx ctx = {
+      .dest_partmap = NULL,
+      .container = dest_dev->disk->partition,
+      .multiple_partmaps = 0
+    };
     int is_ldm;
     grub_err_t err;
     grub_disk_addr_t *sectors;
@@ -347,38 +387,13 @@ setup (const char *dir,
     grub_fs_t fs;
     unsigned int nsec, maxsec;
 
-    /* Unlike root_dev, with dest_dev we're interested in the partition map even
-       if dest_dev itself is a whole disk.  */
-    auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk,
-                                               const grub_partition_t p);
-    int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)),
-                                          const grub_partition_t p)
-    {
-      if (p->parent != container)
-       return 0;
-      /* NetBSD and OpenBSD subpartitions have metadata inside a partition,
-        so they are safe to ignore.
-       */
-      if (grub_strcmp (p->partmap->name, "netbsd") == 0
-         || grub_strcmp (p->partmap->name, "openbsd") == 0)
-       return 0;
-      if (dest_partmap == NULL)
-       {
-         dest_partmap = p->partmap;
-         return 0;
-       }
-      if (dest_partmap == p->partmap)
-       return 0;
-      multiple_partmaps = 1;
-      return 1;
-    }
-
-    grub_partition_iterate (dest_dev->disk, identify_partmap);
+    grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
 
-    if (container && grub_strcmp (container->partmap->name, "msdos") == 0
-       && dest_partmap
-       && (container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
-           || container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
+    if (ctx.container
+       && grub_strcmp (ctx.container->partmap->name, "msdos") == 0
+       && ctx.dest_partmap
+       && (ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD
+           || ctx.container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD))
       {
        grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem.  This is not supported yet."));
        goto unable_to_embed;
@@ -392,7 +407,7 @@ setup (const char *dir,
 
     if (fs_probe)
       {
-       if (!fs && !dest_partmap)
+       if (!fs && !ctx.dest_partmap)
          grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"),
                           dest_dev->disk->name);
        if (fs && !fs->reserved_first_sector)
@@ -403,20 +418,20 @@ setup (const char *dir,
                             "by grub-setup (--skip-fs-probe disables this "
                             "check, use at your own risk)"), dest_dev->disk->name, fs->name);
 
-       if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0
-           && strcmp (dest_partmap->name, "gpt") != 0
-           && strcmp (dest_partmap->name, "bsd") != 0
-           && strcmp (dest_partmap->name, "netbsd") != 0
-           && strcmp (dest_partmap->name, "openbsd") != 0
-           && strcmp (dest_partmap->name, "sunpc") != 0)
+       if (ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
+           && strcmp (ctx.dest_partmap->name, "gpt") != 0
+           && strcmp (ctx.dest_partmap->name, "bsd") != 0
+           && strcmp (ctx.dest_partmap->name, "netbsd") != 0
+           && strcmp (ctx.dest_partmap->name, "openbsd") != 0
+           && strcmp (ctx.dest_partmap->name, "sunpc") != 0)
          /* TRANSLATORS: Partition map may reserve the space just GRUB isn't sure about it.  */
          grub_util_error (_("%s appears to contain a %s partition map which isn't known to "
                             "reserve space for DOS-style boot.  Installing GRUB there could "
                             "result in FILESYSTEM DESTRUCTION if valuable data is overwritten "
                             "by grub-setup (--skip-fs-probe disables this "
-                            "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name);
-       if (is_ldm && dest_partmap && strcmp (dest_partmap->name, "msdos") != 0
-           && strcmp (dest_partmap->name, "gpt") != 0)
+                            "check, use at your own risk)"), dest_dev->disk->name, ctx.dest_partmap->name);
+       if (is_ldm && ctx.dest_partmap && strcmp (ctx.dest_partmap->name, "msdos") != 0
+           && strcmp (ctx.dest_partmap->name, "gpt") != 0)
          grub_util_error (_("%s appears to contain a %s partition map and "
                             "LDM which isn't known to be a safe combination."
                             "  Installing GRUB there could "
@@ -424,12 +439,12 @@ setup (const char *dir,
                             " is overwritten "
                             "by grub-setup (--skip-fs-probe disables this "
                             "check, use at your own risk)"),
-                          dest_dev->disk->name, dest_partmap->name);
+                          dest_dev->disk->name, ctx.dest_partmap->name);
 
       }
 
     /* Copy the partition table.  */
-    if (dest_partmap ||
+    if (ctx.dest_partmap ||
         (!allow_floppy && !grub_util_biosdisk_is_floppy (dest_dev->disk)))
       memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
              tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC,
@@ -437,21 +452,21 @@ setup (const char *dir,
 
     free (tmp_img);
     
-    if (! dest_partmap && ! fs && !is_ldm)
+    if (! ctx.dest_partmap && ! fs && !is_ldm)
       {
        grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition.  This is a BAD idea."));
        goto unable_to_embed;
       }
-    if (multiple_partmaps || (dest_partmap && fs) || (is_ldm && fs))
+    if (ctx.multiple_partmaps || (ctx.dest_partmap && fs) || (is_ldm && fs))
       {
        grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels.  This is not supported yet."));
        goto unable_to_embed;
       }
 
-    if (dest_partmap && !dest_partmap->embed)
+    if (ctx.dest_partmap && !ctx.dest_partmap->embed)
       {
        grub_util_warn (_("Partition style `%s' doesn't support embedding"),
-                       dest_partmap->name);
+                       ctx.dest_partmap->name);
        goto unable_to_embed;
       }
 
@@ -473,9 +488,9 @@ setup (const char *dir,
     if (is_ldm)
       err = grub_util_ldm_embed (dest_dev->disk, &nsec, maxsec,
                                 GRUB_EMBED_PCBIOS, &sectors);
-    else if (dest_partmap)
-      err = dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
-                                GRUB_EMBED_PCBIOS, &sectors);
+    else if (ctx.dest_partmap)
+      err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
+                                    GRUB_EMBED_PCBIOS, &sectors);
     else
       err = fs->embed (dest_dev, &nsec, maxsec,
                       GRUB_EMBED_PCBIOS, &sectors);
@@ -507,12 +522,12 @@ setup (const char *dir,
          grub_util_error ("%s", _("no terminator in the core image"));
       }
 
-    save_first_sector (sectors[0] + grub_partition_get_start (container),
+    save_first_sector (sectors[0] + grub_partition_get_start (ctx.container),
                       0, GRUB_DISK_SECTOR_SIZE);
 
     block = first_block;
     for (i = 1; i < nsec; i++)
-      save_blocklists (sectors[i] + grub_partition_get_start (container),
+      save_blocklists (sectors[i] + grub_partition_get_start (ctx.container),
                       0, GRUB_DISK_SECTOR_SIZE);
 
     /* Make sure that the last blocklist is a terminator.  */