Exemple #1
0
void
grub_util_pull_devmapper (const char *os_dev)
{
  struct dm_tree *tree;
  struct dm_tree_node *node;
  struct dm_tree_node *child;
  void *handle = NULL;
  char *lastsubdev = NULL;
  char *uuid;

  uuid = get_dm_uuid (os_dev);

  if (!grub_util_open_dm (os_dev, &tree, &node))
    {
      grub_free (uuid);
      return;
    }

  while ((child = dm_tree_next_child (&handle, node, 0)))
    {
      const struct dm_info *dm = dm_tree_node_get_info (child);
      char *subdev;
      if (!dm)
	continue;
      subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor));
      if (subdev)
	{
	  lastsubdev = subdev;
	  grub_util_pull_device (subdev);
	}
    }
  if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
      && lastsubdev)
    {
      char *grdev = grub_util_get_grub_dev (lastsubdev);
      dm_tree_free (tree);
      if (grdev)
	{
	  grub_err_t err;
	  err = grub_cryptodisk_cheat_mount (grdev, os_dev);
	  if (err)
	    grub_util_error (_("can't mount encrypted volume `%s': %s"),
			     lastsubdev, grub_errmsg);
	}
      grub_free (grdev);
    }
  else
    dm_tree_free (tree);
  grub_free (uuid);
}
Exemple #2
0
char *
grub_util_devmapper_part_to_disk (struct stat *st,
				  int *is_part, const char *path)
{
  int major, minor;

  if (grub_util_get_dm_node_linear_info (st->st_rdev,
					 &major, &minor, 0))
    {
      *is_part = 1;
      return grub_find_device ("/dev", makedev (major, minor));
    }
  *is_part = 0;
  return xstrdup (path);
}
Exemple #3
0
char *
grub_find_device (const char *dir, dev_t dev)
{
  DIR *dp;
  char *saved_cwd;
  struct dirent *ent;

  if (! dir)
    dir = "/dev";

  dp = opendir (dir);
  if (! dp)
    return 0;

  saved_cwd = xgetcwd ();

  grub_util_info ("changing current directory to %s", dir);
  if (chdir (dir) < 0)
    {
      free (saved_cwd);
      closedir (dp);
      return 0;
    }

  while ((ent = readdir (dp)) != 0)
    {
      struct stat st;

      /* Avoid:
	 - dotfiles (like "/dev/.tmp.md0") since they could be duplicates.
	 - dotdirs (like "/dev/.static") since they could contain duplicates.  */
      if (ent->d_name[0] == '.')
	continue;

      if (lstat (ent->d_name, &st) < 0)
	/* Ignore any error.  */
	continue;

      if (S_ISLNK (st.st_mode)) {
#ifdef __linux__
	if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
	  /* Follow symbolic links under /dev/mapper/; the canonical name
	     may be something like /dev/dm-0, but the names under
	     /dev/mapper/ are more human-readable and so we prefer them if
	     we can get them.  */
	  if (stat (ent->d_name, &st) < 0)
	    continue;
	} else
#endif /* __linux__ */
	/* Don't follow other symbolic links.  */
	continue;
      }

      if (S_ISDIR (st.st_mode))
	{
	  /* Find it recursively.  */
	  char *res;

	  res = grub_find_device (ent->d_name, dev);

	  if (res)
	    {
	      if (chdir (saved_cwd) < 0)
		grub_util_error ("%s",
				 _("cannot restore the original directory"));

	      free (saved_cwd);
	      closedir (dp);
	      return res;
	    }
	}

#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
      if (S_ISCHR (st.st_mode) && st.st_rdev == dev)
#else
      if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
#endif
	{
#ifdef __linux__
	  /* Skip device names like /dev/dm-0, which are short-hand aliases
	     to more descriptive device names, e.g. those under /dev/mapper */
	  if (ent->d_name[0] == 'd' &&
	      ent->d_name[1] == 'm' &&
	      ent->d_name[2] == '-' &&
	      ent->d_name[3] >= '0' &&
	      ent->d_name[3] <= '9')
	    continue;
#endif

	  /* Found!  */
	  char *res;
	  char *cwd;

	  cwd = xgetcwd ();
	  res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 3);
	  sprintf (res, 
#if defined(__NetBSD__) || defined(__OpenBSD__)
		   /* Convert this block device to its character (raw) device.  */
		   "%s/r%s",
#else
		   /* Keep the device name as it is.  */
		   "%s/%s",
#endif
		   cwd, ent->d_name);
	  strip_extra_slashes (res);
	  free (cwd);

	  /* /dev/root is not a real block device keep looking, takes care
	     of situation where root filesystem is on the same partition as
	     grub files */

	  if (strcmp(res, "/dev/root") == 0)
	    {
	      free (res);
	      continue;
	    }

	  if (chdir (saved_cwd) < 0)
	    grub_util_error ("%s", _("cannot restore the original directory"));

	  free (saved_cwd);
	  closedir (dp);
	  return res;
	}
    }

  if (chdir (saved_cwd) < 0)
    grub_util_error ("%s", _("cannot restore the original directory"));

  free (saved_cwd);
  closedir (dp);
  return 0;
}