Exemple #1
0
/*
 * Checks that disk->partition contains part.  This function assumes that the
 * start of part is relative to the start of disk->partition.  Returns 1 if
 * disk->partition is null.
 */
static int
grub_partition_check_containment (const grub_disk_t disk,
				  const grub_partition_t part)
{
  if (disk->partition == NULL)
    return 1;

  if (part->start + part->len > disk->partition->len)
    {
      char *partname;

      partname = grub_partition_get_name (disk->partition);
      grub_dprintf ("partition", "sub-partition %s%d of (%s,%s) ends after parent.\n",
		    part->partmap->name, part->number + 1, disk->name, partname);
#ifdef GRUB_UTIL
      grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
		      disk->name, partname, part->partmap->name, part->number + 1);
#endif
      grub_free (partname);

      return 0;
    }

  return 1;
}
Exemple #2
0
static char *
get_mdadm_uuid (const char *os_dev)
{
  const char *argv[5];
  int fd;
  pid_t pid;
  FILE *mdadm;
  char *buf = NULL;
  size_t len = 0;
  char *name = NULL;

  argv[0] = "mdadm";
  argv[1] = "--detail";
  argv[2] = "--export";
  argv[3] = os_dev;
  argv[4] = NULL;

  pid = grub_util_exec_pipe (argv, &fd);

  if (!pid)
    return NULL;

  /* Parent.  Read mdadm's output.  */
  mdadm = fdopen (fd, "r");
  if (! mdadm)
    {
      grub_util_warn (_("Unable to open stream from %s: %s"),
		      "mdadm", strerror (errno));
      goto out;
    }

  while (getline (&buf, &len, mdadm) > 0)
    {
      if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0)
	{
	  char *name_start, *ptri, *ptro;
	  
	  free (name);
	  name_start = buf + sizeof ("MD_UUID=") - 1;
	  ptro = name = xmalloc (strlen (name_start) + 1);
	  for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r';
	       ptri++)
	    if ((*ptri >= '0' && *ptri <= '9')
		|| (*ptri >= 'a' && *ptri <= 'f')
		|| (*ptri >= 'A' && *ptri <= 'F'))
	      *ptro++ = *ptri;
	  *ptro = 0;
	}
    }

out:
  close (fd);
  waitpid (pid, NULL, 0);
  free (buf);

  return name;
}
Exemple #3
0
void
grub_util_pull_lvm_by_command (const char *os_dev)
{
  const char *argv[8];
  int fd;
  pid_t pid;
  FILE *vgs;
  char *buf = NULL;
  size_t len = 0;
  char *vgname = NULL;
  const char *iptr;
  char *optr;
  char *vgid = NULL;
  grub_size_t vgidlen = 0;

  vgid = grub_util_get_vg_uuid (os_dev);
  if (vgid)
    vgidlen = grub_strlen (vgid);

  if (!vgid)
    {
      if (strncmp (os_dev, LVM_DEV_MAPPER_STRING,
		   sizeof (LVM_DEV_MAPPER_STRING) - 1)
	  != 0)
	return;

      vgname = xmalloc (strlen (os_dev + sizeof (LVM_DEV_MAPPER_STRING) - 1) + 1);
      for (iptr = os_dev + sizeof (LVM_DEV_MAPPER_STRING) - 1, optr = vgname; *iptr; )
	if (*iptr != '-')
	  *optr++ = *iptr++;
	else if (iptr[0] == '-' && iptr[1] == '-')
	  {
	    iptr += 2;
	    *optr++ = '-';
	  }
	else
	  break;
      *optr = '\0';
    }

  /* by default PV name is left aligned in 10 character field, meaning that
     we do not know where name ends. Using dummy --separator disables
     alignment. We have a single field, so separator itself is not output */
  argv[0] = "vgs";
  argv[1] = "--options";
  if (vgid)
    argv[2] = "vg_uuid,pv_name";
  else
    argv[2] = "pv_name";
  argv[3] = "--noheadings";
  argv[4] = "--separator";
  argv[5] = ":";
  argv[6] = vgname;
  argv[7] = NULL;

  pid = grub_util_exec_pipe (argv, &fd);
  free (vgname);

  if (!pid)
    return;

  /* Parent.  Read vgs' output.  */
  vgs = fdopen (fd, "r");
  if (! vgs)
    {
      grub_util_warn (_("Unable to open stream from %s: %s"),
		      "vgs", strerror (errno));
      goto out;
    }

  while (getline (&buf, &len, vgs) > 0)
    {
      char *ptr;
      /* LVM adds two spaces as standard prefix */
      for (ptr = buf; ptr < buf + 2 && *ptr == ' '; ptr++);

      if (vgid && (grub_strncmp (vgid, ptr, vgidlen) != 0
		   || ptr[vgidlen] != ':'))
	continue;
      if (vgid)
	ptr += vgidlen + 1;
      if (*ptr == '\0')
	continue;
      *(ptr + strlen (ptr) - 1) = '\0';
      grub_util_pull_device (ptr);
    }

out:
  close (fd);
  waitpid (pid, NULL, 0);
  free (buf);
}
Exemple #4
0
static int
grub_util_is_imsm (const char *os_dev)
{
  int retry;
  int is_imsm = 0;
  int container_seen = 0;
  const char *dev = os_dev;

  do
    {
      const char *argv[5];
      int fd;
      pid_t pid;
      FILE *mdadm;
      char *buf = NULL;
      size_t len = 0;

      retry = 0; /* We'll do one more pass if device is part of container */

      argv[0] = "mdadm";
      argv[1] = "--detail";
      argv[2] = "--export";
      argv[3] = dev;
      argv[4] = NULL;

      pid = grub_util_exec_pipe (argv, &fd);

      if (!pid)
	{
	  if (dev != os_dev)
	    free ((void *) dev);
	  return 0;
	}

      /* Parent.  Read mdadm's output.  */
      mdadm = fdopen (fd, "r");
      if (! mdadm)
	{
	  grub_util_warn (_("Unable to open stream from %s: %s"),
			  "mdadm", strerror (errno));
	  close (fd);
	  waitpid (pid, NULL, 0);
	  if (dev != os_dev)
	    free ((void *) dev);
	  return 0;
	}

      while (getline (&buf, &len, mdadm) > 0)
	{
	  if (strncmp (buf, "MD_CONTAINER=", sizeof ("MD_CONTAINER=") - 1) == 0
	      && !container_seen)
	    {
	      char *newdev, *ptr;
	      newdev = xstrdup (buf + sizeof ("MD_CONTAINER=") - 1);
	      ptr = newdev + strlen (newdev) - 1;
	      for (; ptr >= newdev && (*ptr == '\n' || *ptr == '\r'); ptr--);
	      ptr[1] = 0;
	      grub_util_info ("Container of %s is %s", dev, newdev);
	      dev = newdev;
	      container_seen = retry = 1;
	      break;
	    }
	  if (strncmp (buf, "MD_METADATA=imsm",
		       sizeof ("MD_METADATA=imsm") - 1) == 0)
	    {
	      is_imsm = 1;
	      grub_util_info ("%s is imsm", dev);	      
	      break;
	    }
	}

      free (buf);
      close (fd);
      waitpid (pid, NULL, 0);
    }
  while (retry);

  if (dev != os_dev)
    free ((void *) dev);
  return is_imsm;
}
Exemple #5
0
static grub_err_t
bsdlabel_partition_map_iterate (grub_disk_t disk,
				int (*hook) (grub_disk_t disk,
					     const grub_partition_t partition))
{
  struct grub_partition_bsd_disk_label label;
  struct grub_partition p;
  grub_disk_addr_t delta = 0;
  unsigned pos;

  /* Read the BSD label.  */
  if (grub_disk_read (disk, GRUB_PC_PARTITION_BSD_LABEL_SECTOR,
		      0, sizeof (label), &label))
    return grub_errno;

  /* Check if it is valid.  */
  if (label.magic != grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC))
    return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");

  /* A kludge to determine a base of be.offset.  */
  if (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION
      < grub_cpu_to_le16 (label.num_partitions))
    {
      struct grub_partition_bsd_entry whole_disk_be;

      pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
	* GRUB_DISK_SECTOR_SIZE + sizeof (struct grub_partition_bsd_entry)
	* GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION;

      if (grub_disk_read (disk, pos / GRUB_DISK_SECTOR_SIZE,
			  pos % GRUB_DISK_SECTOR_SIZE, sizeof (whole_disk_be),
			  &whole_disk_be))
	return grub_errno;

      delta = grub_le_to_cpu32 (whole_disk_be.offset);
    }

  pos = sizeof (label) + GRUB_PC_PARTITION_BSD_LABEL_SECTOR
    * GRUB_DISK_SECTOR_SIZE;

  for (p.number = 0;
       p.number < grub_cpu_to_le16 (label.num_partitions);
       p.number++, pos += sizeof (struct grub_partition_bsd_entry))
    {
      struct grub_partition_bsd_entry be;

      if (p.number == GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION)
	continue;

      p.offset = pos / GRUB_DISK_SECTOR_SIZE;
      p.index = pos % GRUB_DISK_SECTOR_SIZE;

      if (grub_disk_read (disk, p.offset, p.index, sizeof (be),  &be))
	return grub_errno;

      p.start = grub_le_to_cpu32 (be.offset);
      p.len = grub_le_to_cpu32 (be.size);
      p.partmap = &grub_bsdlabel_partition_map;

      grub_dprintf ("partition",
		    "partition %d: type 0x%x, start 0x%llx, len 0x%llx\n",
		    p.number, be.fs_type,
		    (unsigned long long) p.start,
		    (unsigned long long) p.len);

      if (p.len == 0)
	continue;

      if (p.start < delta)
	{
#ifdef GRUB_UTIL
	  char *partname;
#endif
	  grub_dprintf ("partition",
			"partition %d: invalid start (found 0x%llx, wanted >= 0x%llx)\n",
			p.number,
			(unsigned long long) p.start,
			(unsigned long long) delta);
#ifdef GRUB_UTIL
	  /* disk->partition != NULL as 0 < delta */
	  partname = grub_partition_get_name (disk->partition);
	  grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)",
			  disk->name, partname, p.partmap->name, p.number + 1);
	  grub_free (partname);
#endif
	  continue;
	}

      p.start -= delta;

      if (hook (disk, &p))
	return grub_errno;
    }

  return GRUB_ERR_NONE;
}
Exemple #6
0
static void
read_device_map (const char *dev_map)
{
  FILE *fp;
  char buf[1024];	/* XXX */
  int lineno = 0;

  if (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 = 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);
}