/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2004,2007  Free Software Foundation, Inc.
 *
 *  GRUB is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  GRUB is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <grub/misc.h>
#include <grub/partition.h>
#include <grub/disk.h>

static grub_partition_map_t grub_partition_map_list;

void
grub_partition_map_register (grub_partition_map_t partmap)
{
  partmap->next = grub_partition_map_list;
  grub_partition_map_list = partmap;
}

void
grub_partition_map_unregister (grub_partition_map_t partmap)
{
  grub_partition_map_t *p, q;

  for (p = &grub_partition_map_list, q = *p; q; p = &(q->next), q = q->next)
    if (q == partmap)
      {
        *p = q->next;
	break;
      }
}

int
grub_partition_map_iterate (int (*hook) (const grub_partition_map_t partmap))
{
  grub_partition_map_t p;

  for (p = grub_partition_map_list; p; p = p->next)
    if (hook (p))
      return 1;

  return 0;
}

grub_partition_t
grub_partition_probe (struct grub_disk *disk, const char *str)
{
  grub_partition_t part = 0;

  auto int part_map_probe (const grub_partition_map_t partmap);

  int part_map_probe (const grub_partition_map_t partmap)
    {
      part = partmap->probe (disk, str);
      if (part)
	return 1;

      if (grub_errno == GRUB_ERR_BAD_PART_TABLE)
	{
	  /* Continue to next partition map type.  */
	  grub_errno = GRUB_ERR_NONE;
	  return 0;
	}

      return 1;
    }

  /* Use the first partition map type found.  */
  grub_partition_map_iterate (part_map_probe);

  return part;
}

int
grub_partition_iterate (struct grub_disk *disk,
			int (*hook) (grub_disk_t disk,
				     const grub_partition_t partition))
{
  grub_partition_map_t partmap = 0;
  int ret = 0;

  auto int part_map_iterate (const grub_partition_map_t p);
  auto int part_map_iterate_hook (grub_disk_t d,
				  const grub_partition_t partition);

  int part_map_iterate_hook (grub_disk_t d __attribute__ ((unused)),
			     const grub_partition_t partition __attribute__ ((unused)))
    {
      return 1;
    }

  int part_map_iterate (const grub_partition_map_t p)
    {
      grub_dprintf ("partition", "Detecting %s...\n", p->name);
      p->iterate (disk, part_map_iterate_hook);

      if (grub_errno != GRUB_ERR_NONE)
	{
	  /* Continue to next partition map type.  */
	  grub_dprintf ("partition", "%s detection failed.\n", p->name);
	  grub_errno = GRUB_ERR_NONE;
	  return 0;
	}

      grub_dprintf ("partition", "%s detection succeeded.\n", p->name);
      partmap = p;
      return 1;
    }

  grub_partition_map_iterate (part_map_iterate);
  if (partmap)
    ret = partmap->iterate (disk, hook);

  return ret;
}

char *
grub_partition_get_name (const grub_partition_t partition)
{
  return partition->partmap->get_name (partition);
}
