/* hostdisk.c - emulate biosdisk */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010  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 <config-util.h>

#include <grub/disk.h>
#include <grub/partition.h>
#include <grub/msdos_partition.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
#include <grub/emu/getroot.h>
#include <grub/misc.h>
#include <grub/i18n.h>
#include <grub/list.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>

#ifdef __linux__
# include <sys/ioctl.h>         /* ioctl */
# include <sys/mount.h>
# ifndef BLKFLSBUF
#  define BLKFLSBUF     _IO (0x12,97)   /* flush buffer cache */
# endif /* ! BLKFLSBUF */
#endif /* __linux__ */

static struct
{
  char *drive;
  char *device;
  int device_map;
} map[256];

static int
unescape_cmp (const char *a, const char *b_escaped)
{
  while (*a || *b_escaped)
    {
      if (*b_escaped == '\\' && b_escaped[1] != 0)
	b_escaped++;
      if (*a < *b_escaped)
	return -1;
      if (*a > *b_escaped)
	return +1;
      a++;
      b_escaped++;
    }
  if (*a)
    return +1;
  if (*b_escaped)
    return -1;
  return 0;
}

static int
find_grub_drive (const char *name)
{
  unsigned int i;

  if (name)
    {
      for (i = 0; i < ARRAY_SIZE (map); i++)
	if (map[i].drive && unescape_cmp (map[i].drive, name) == 0)
	  return i;
    }

  return -1;
}

static int
find_free_slot (void)
{
  unsigned int i;

  for (i = 0; i < ARRAY_SIZE (map); i++)
    if (! map[i].drive)
      return i;

  return -1;
}

static int
grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data,
			    grub_disk_pull_t pull)
{
  unsigned i;

  if (pull != GRUB_DISK_PULL_NONE)
    return 0;

  for (i = 0; i < ARRAY_SIZE (map); i++)
    if (map[i].drive && hook (map[i].drive, hook_data))
      return 1;

  return 0;
}

static grub_err_t
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
{
  int drive;
  struct grub_util_hostdisk_data *data;

  drive = find_grub_drive (name);
  grub_util_info ("drive = %d", drive);
  if (drive < 0)
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
		       "no mapping exists for `%s'", name);

  disk->id = drive;
  disk->data = data = xmalloc (sizeof (struct grub_util_hostdisk_data));
  data->dev = NULL;
  data->access_mode = 0;
  data->fd = GRUB_UTIL_FD_INVALID;
  data->is_disk = 0;
  data->device_map = map[drive].device_map;

  /* Get the size.  */
  {
    grub_util_fd_t fd;

    fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY);

    if (!GRUB_UTIL_FD_IS_VALID(fd))
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"),
			 map[drive].device, grub_util_fd_strerror ());

    disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device,
						 &disk->log_sector_size);
    disk->total_sectors >>= disk->log_sector_size;
    disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;

#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
    {
      struct stat st;
# if GRUB_DISK_DEVS_ARE_CHAR
      if (fstat (fd, &st) >= 0 && S_ISCHR (st.st_mode))
# else
      if (fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode))
# endif
	data->is_disk = 1;
    }
#endif

    grub_util_fd_close (fd);

    grub_util_info ("the size of %s is %" GRUB_HOST_PRIuLONG_LONG,
		    name, (unsigned long long) disk->total_sectors);

    return GRUB_ERR_NONE;
  }
}

const char *
grub_hostdisk_os_dev_to_grub_drive (const char *os_disk, int add)
{
  unsigned int i;
  char *canon;

  canon = grub_canonicalize_file_name (os_disk);
  if (!canon)
    canon = xstrdup (os_disk);

  for (i = 0; i < ARRAY_SIZE (map); i++)
    if (! map[i].device)
      break;
    else if (strcmp (map[i].device, canon) == 0)
      {
	free (canon);
	return map[i].drive;
      }

  if (!add)
    {
      free (canon);
      return NULL;
    }

  if (i == ARRAY_SIZE (map))
    /* TRANSLATORS: it refers to the lack of free slots.  */
    grub_util_error ("%s", _("device count exceeds limit"));

  map[i].device = canon;
  map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk));
  strcpy (map[i].drive, "hostdisk/");
  strcpy (map[i].drive + sizeof ("hostdisk/") - 1, os_disk);
  map[i].device_map = 0;

  grub_hostdisk_flush_initial_buffer (os_disk);

  return map[i].drive;
}

#ifndef __linux__
grub_util_fd_t
grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags,
			  grub_disk_addr_t *max)
{
  grub_util_fd_t fd;
  struct grub_util_hostdisk_data *data = disk->data;

  *max = ~0ULL;

  flags |= GRUB_UTIL_FD_O_SYNC;

  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
      data->access_mode == (flags & O_ACCMODE))
    {
      grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
      fd = data->fd;
    }
  else
    {
      free (data->dev);
      data->dev = 0;
      if (GRUB_UTIL_FD_IS_VALID(data->fd))
	{
	    if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
	      grub_util_fd_sync (data->fd);
	    grub_util_fd_close (data->fd);
	    data->fd = GRUB_UTIL_FD_INVALID;
	}

      fd = grub_util_fd_open (map[disk->id].device, flags);
      if (GRUB_UTIL_FD_IS_VALID(fd))
	{
	  data->dev = xstrdup (map[disk->id].device);
	  data->access_mode = (flags & O_ACCMODE);
	  data->fd = fd;
	}
    }

  if (!GRUB_UTIL_FD_IS_VALID(data->fd))
    {
      grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"),
		  map[disk->id].device, grub_util_fd_strerror ());
      return GRUB_UTIL_FD_INVALID;
    }

  if (grub_util_fd_seek (fd, sector << disk->log_sector_size))
    {
      grub_util_fd_close (fd);
      grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"),
		  map[disk->id].device, grub_util_fd_strerror ());

      return GRUB_UTIL_FD_INVALID;
    }

  return fd;
}
#endif


static grub_err_t
grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
			 grub_size_t size, char *buf)
{
  while (size)
    {
      grub_util_fd_t fd;
      grub_disk_addr_t max = ~0ULL;
      fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_RDONLY, &max);
      if (!GRUB_UTIL_FD_IS_VALID (fd))
	return grub_errno;

#ifdef __linux__
      if (sector == 0)
	/* Work around a bug in Linux ez remapping.  Linux remaps all
	   sectors that are read together with the MBR in one read.  It
	   should only remap the MBR, so we split the read in two
	   parts. -jochen  */
	max = 1;
#endif /* __linux__ */

      if (max > size)
	max = size;

      if (grub_util_fd_read (fd, buf, max << disk->log_sector_size)
	  != (ssize_t) (max << disk->log_sector_size))
	return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"),
			   map[disk->id].device, grub_util_fd_strerror ());
      size -= max;
      buf += (max << disk->log_sector_size);
      sector += max;
    }
  return GRUB_ERR_NONE;
}

static grub_err_t
grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
			  grub_size_t size, const char *buf)
{
  while (size)
    {
      grub_util_fd_t fd;
      grub_disk_addr_t max = ~0ULL;
      fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_WRONLY, &max);
      if (!GRUB_UTIL_FD_IS_VALID (fd))
	return grub_errno;

#ifdef __linux__
      if (sector == 0)
	/* Work around a bug in Linux ez remapping.  Linux remaps all
	   sectors that are write together with the MBR in one write.  It
	   should only remap the MBR, so we split the write in two
	   parts. -jochen  */
	max = 1;
#endif /* __linux__ */

      if (max > size)
	max = size;

      if (grub_util_fd_write (fd, buf, max << disk->log_sector_size)
	  != (ssize_t) (max << disk->log_sector_size))
	return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"),
			   map[disk->id].device, grub_util_fd_strerror ());
      size -= max;
      buf += (max << disk->log_sector_size);
    }
  return GRUB_ERR_NONE;
}

grub_err_t
grub_util_biosdisk_flush (struct grub_disk *disk)
{
  struct grub_util_hostdisk_data *data = disk->data;

  if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
    return GRUB_ERR_NONE;
  if (!GRUB_UTIL_FD_IS_VALID (data->fd))
    {
      grub_disk_addr_t max;
      data->fd = grub_util_fd_open_device (disk, 0, GRUB_UTIL_FD_O_RDONLY, &max);
      if (!GRUB_UTIL_FD_IS_VALID (data->fd))
	return grub_errno;
    }
  grub_util_fd_sync (data->fd);
#ifdef __linux__
  if (data->is_disk)
    ioctl (data->fd, BLKFLSBUF, 0);
#endif
  return GRUB_ERR_NONE;
}

static void
grub_util_biosdisk_close (struct grub_disk *disk)
{
  struct grub_util_hostdisk_data *data = disk->data;

  free (data->dev);
  if (GRUB_UTIL_FD_IS_VALID (data->fd))
    {
      if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
	grub_util_biosdisk_flush (disk);
      grub_util_fd_close (data->fd);
    }
  free (data);
}

static struct grub_disk_dev grub_util_biosdisk_dev =
  {
    .name = "hostdisk",
    .id = GRUB_DISK_DEVICE_HOSTDISK_ID,
    .iterate = grub_util_biosdisk_iterate,
    .open = grub_util_biosdisk_open,
    .close = grub_util_biosdisk_close,
    .read = grub_util_biosdisk_read,
    .write = grub_util_biosdisk_write,
    .next = 0
  };

static int
grub_util_check_file_presence (const char *p)
{
#if !GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
  grub_util_fd_t h;
  h = grub_util_fd_open (p, GRUB_UTIL_FD_O_RDONLY);
  if (!GRUB_UTIL_FD_IS_VALID(h))
    return 0;
  grub_util_fd_close (h);
  return 1;
#else
  struct stat st;

  if (stat (p, &st) == -1)
    return 0;
  return 1;
#endif
}

static void
read_device_map (const char *dev_map)
{
  FILE *fp;
  char buf[1024];	/* XXX */
  int lineno = 0;

  if (!dev_map || dev_map[0] == '\0')
    {
      grub_util_info ("no device.map");
      return;
    }

  fp = grub_util_fopen (dev_map, "r");
  if (! fp)
    {
      grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno));
      return;
    }

  while (fgets (buf, sizeof (buf), fp))
    {
      char *p = buf;
      char *e;
      char *drive_e, *drive_p;
      int drive;

      lineno++;

      /* Skip leading spaces.  */
      while (*p && grub_isspace (*p))
	p++;

      /* If the first character is `#' or NUL, skip this line.  */
      if (*p == '\0' || *p == '#')
	continue;

      if (*p != '(')
	{
	  char *tmp;
	  tmp = xasprintf (_("missing `%c' symbol"), '(');
	  grub_util_error ("%s:%d: %s", dev_map, lineno, tmp);
	}

      p++;
      /* Find a free slot.  */
      drive = find_free_slot ();
      if (drive < 0)
	grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit"));

      e = p;
      p = strchr (p, ')');
      if (! p)
	{
	  char *tmp;
	  tmp = xasprintf (_("missing `%c' symbol"), ')');
	  grub_util_error ("%s:%d: %s", dev_map, lineno, tmp);
	}

      map[drive].drive = 0;
      if ((e[0] == 'f' || e[0] == 'h' || e[0] == 'c') && e[1] == 'd')
	{
	  char *ptr;
	  for (ptr = e + 2; ptr < p; ptr++)
	    if (!grub_isdigit (*ptr))
	      break;
	  if (ptr == p)
	    {
	      map[drive].drive = xmalloc (p - e + sizeof ('\0'));
	      strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
	      map[drive].drive[p - e] = '\0';
	    }
	  if (*ptr == ',')
	    {
	      *p = 0;

	      /* TRANSLATORS: Only one entry is ignored. However the suggestion
		 is to correct/delete the whole file.
		 device.map is a file indicating which
		 devices are available at boot time. Fedora populated it with
		 entries like (hd0,1) /dev/sda1 which would mean that every
		 partition is a separate disk for BIOS. Such entries were
		 inactive in GRUB due to its bug which is now gone. Without
		 this additional check these entries would be harmful now.
	      */
	      grub_util_warn (_("the device.map entry `%s' is invalid. "
				"Ignoring it. Please correct or "
				"delete your device.map"), e);
	      continue;
	    }
	}
      drive_e = e;
      drive_p = p;
      map[drive].device_map = 1;

      p++;
      /* Skip leading spaces.  */
      while (*p && grub_isspace (*p))
	p++;

      if (*p == '\0')
	grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected"));

      /* NUL-terminate the filename.  */
      e = p;
      while (*e && ! grub_isspace (*e))
	e++;
      *e = '\0';

      if (!grub_util_check_file_presence (p))
	{
	  free (map[drive].drive);
	  map[drive].drive = NULL;
	  grub_util_info ("Cannot stat `%s', skipping", p);
	  continue;
	}

      /* On Linux, the devfs uses symbolic links horribly, and that
	 confuses the interface very much, so use realpath to expand
	 symbolic links.  */
      map[drive].device = grub_canonicalize_file_name (p);
      if (! map[drive].device)
	map[drive].device = xstrdup (p);
      
      if (!map[drive].drive)
	{
	  char c;
	  map[drive].drive = xmalloc (sizeof ("hostdisk/") + strlen (p));
	  memcpy (map[drive].drive, "hostdisk/", sizeof ("hostdisk/") - 1);
	  strcpy (map[drive].drive + sizeof ("hostdisk/") - 1, p);
	  c = *drive_p;
	  *drive_p = 0;
	  /* TRANSLATORS: device.map is a filename. Not to be translated.
	     device.map specifies disk correspondance overrides. Previously
	     one could create any kind of device name with this. Due to
	     some problems we decided to limit it to just a handful
	     possibilities.  */
	  grub_util_warn (_("the drive name `%s' in device.map is incorrect. "
			    "Using %s instead. "
			    "Please use the form [hfc]d[0-9]* "
			    "(E.g. `hd0' or `cd')"),
			  drive_e, map[drive].drive);
	  *drive_p = c;
	}

      grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive,
		      map[drive].device);

      grub_hostdisk_flush_initial_buffer (map[drive].device);
    }

  fclose (fp);
}

void
grub_util_biosdisk_init (const char *dev_map)
{
  read_device_map (dev_map);
  grub_disk_dev_register (&grub_util_biosdisk_dev);
}

void
grub_util_biosdisk_fini (void)
{
  unsigned i;

  for (i = 0; i < ARRAY_SIZE(map); i++)
    {
      if (map[i].drive)
	free (map[i].drive);
      if (map[i].device)
	free (map[i].device);
      map[i].drive = map[i].device = NULL;
    }

  grub_disk_dev_unregister (&grub_util_biosdisk_dev);
}

const char *
grub_util_biosdisk_get_compatibility_hint (grub_disk_t disk)
{
  if (disk->dev != &grub_util_biosdisk_dev || map[disk->id].device_map)
    return disk->name;
  return 0;
}

const char *
grub_util_biosdisk_get_osdev (grub_disk_t disk)
{
  if (disk->dev != &grub_util_biosdisk_dev)
    return 0;

  return map[disk->id].device;
}


static char *
grub_util_path_concat_real (size_t n, int ext, va_list ap)
{
  size_t totlen = 0;
  char **l = xcalloc (n + ext, sizeof (l[0]));
  char *r, *p, *pi;
  size_t i;
  int first = 1;

  for (i = 0; i < n + ext; i++)
    {
      l[i] = va_arg (ap, char *);
      if (l[i])
	totlen += strlen (l[i]) + 1;
    }

  r = xmalloc (totlen + 10);

  p = r;
  for (i = 0; i < n; i++)
    {
      pi = l[i];
      if (!pi)
	continue;
      while (*pi == '/')
	pi++;
      if ((p != r || (pi != l[i] && first)) && (p == r || *(p - 1) != '/'))
	*p++ = '/';
      first = 0;
      p = grub_stpcpy (p, pi);
      while (p != r && p != r + 1 && *(p - 1) == '/')
	p--;
    }

  if (ext && l[i])
    p = grub_stpcpy (p, l[i]);

  *p = '\0';

  free (l);

  return r;
}

char *
grub_util_path_concat (size_t n, ...)
{
  va_list ap;
  char *r;

  va_start (ap, n);

  r = grub_util_path_concat_real (n, 0, ap);

  va_end (ap);

  return r;
}

char *
grub_util_path_concat_ext (size_t n, ...)
{
  va_list ap;
  char *r;

  va_start (ap, n);

  r = grub_util_path_concat_real (n, 1, ap);

  va_end (ap);

  return r;
}
