123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- /*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 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 <config.h>
- #include <grub/emu/getroot.h>
- #include <grub/mm.h>
- #ifdef HAVE_DEVICE_MAPPER
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <assert.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <string.h>
- #include <dirent.h>
- #include <errno.h>
- #include <error.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #if defined(MAJOR_IN_MKDEV)
- #include <sys/mkdev.h>
- #elif defined(MAJOR_IN_SYSMACROS)
- #include <sys/sysmacros.h>
- #endif
- #include <libdevmapper.h>
- #include <grub/types.h>
- #include <grub/util/misc.h>
- #include <grub/mm.h>
- #include <grub/misc.h>
- #include <grub/emu/misc.h>
- #include <grub/emu/hostdisk.h>
- static int
- grub_util_open_dm (const char *os_dev, struct dm_tree **tree,
- struct dm_tree_node **node)
- {
- uint32_t maj, min;
- struct stat st;
- *node = NULL;
- *tree = NULL;
- if (stat (os_dev, &st) < 0)
- return 0;
- maj = major (st.st_rdev);
- min = minor (st.st_rdev);
- if (!dm_is_dm_major (maj))
- return 0;
- *tree = dm_tree_create ();
- if (! *tree)
- {
- grub_puts_ (N_("Failed to create `device-mapper' tree"));
- grub_dprintf ("hostdisk", "dm_tree_create failed\n");
- return 0;
- }
- if (! dm_tree_add_dev (*tree, maj, min))
- {
- grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
- dm_tree_free (*tree);
- *tree = NULL;
- return 0;
- }
- *node = dm_tree_find_node (*tree, maj, min);
- if (! *node)
- {
- grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
- dm_tree_free (*tree);
- *tree = NULL;
- return 0;
- }
- return 1;
- }
- static char *
- get_dm_uuid (const char *os_dev)
- {
- struct dm_tree *tree;
- struct dm_tree_node *node;
- const char *node_uuid;
- char *ret;
- if (!grub_util_open_dm (os_dev, &tree, &node))
- return NULL;
- node_uuid = dm_tree_node_get_uuid (node);
- if (! node_uuid)
- {
- grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev);
- dm_tree_free (tree);
- return NULL;
- }
- ret = grub_strdup (node_uuid);
- dm_tree_free (tree);
- return ret;
- }
- enum grub_dev_abstraction_types
- grub_util_get_dm_abstraction (const char *os_dev)
- {
- char *uuid;
- uuid = get_dm_uuid (os_dev);
- if (uuid == NULL)
- return GRUB_DEV_ABSTRACTION_NONE;
- if (strncmp (uuid, "LVM-", 4) == 0)
- {
- grub_free (uuid);
- return GRUB_DEV_ABSTRACTION_LVM;
- }
- if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0)
- {
- grub_free (uuid);
- return GRUB_DEV_ABSTRACTION_LUKS;
- }
- grub_free (uuid);
- return GRUB_DEV_ABSTRACTION_NONE;
- }
- 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);
- }
- 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);
- }
- char *
- grub_util_get_devmapper_grub_dev (const char *os_dev)
- {
- char *uuid, *optr;
- char *grub_dev;
- uuid = get_dm_uuid (os_dev);
- if (!uuid)
- return NULL;
- switch (grub_util_get_dev_abstraction (os_dev))
- {
- case GRUB_DEV_ABSTRACTION_LVM:
- {
- unsigned i;
- int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32, 38, 42, 46, 50, 54, 58};
- grub_dev = xmalloc (grub_strlen (uuid) + 40);
- optr = grub_stpcpy (grub_dev, "lvmid/");
- for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++)
- {
- memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i],
- dashes[i+1] - dashes[i]);
- optr += dashes[i+1] - dashes[i];
- *optr++ = '-';
- }
- optr = stpcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i]);
- *optr = '\0';
- grub_dev[sizeof("lvmid/xxxxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxxxx") - 1]
- = '/';
- free (uuid);
- return grub_dev;
- }
- case GRUB_DEV_ABSTRACTION_LUKS:
- {
- char *dash;
- dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-');
- if (dash)
- *dash = 0;
- grub_dev = grub_xasprintf ("cryptouuid/%s",
- uuid + sizeof ("CRYPT-LUKS1-") - 1);
- grub_free (uuid);
- return grub_dev;
- }
- default:
- grub_free (uuid);
- return NULL;
- }
- }
- char *
- grub_util_get_vg_uuid (const char *os_dev)
- {
- char *uuid, *vgid;
- int dashes[] = { 0, 6, 10, 14, 18, 22, 26, 32};
- unsigned i;
- char *optr;
- uuid = get_dm_uuid (os_dev);
- if (!uuid)
- return NULL;
- vgid = xmalloc (grub_strlen (uuid));
- optr = vgid;
- for (i = 0; i < ARRAY_SIZE (dashes) - 1; i++)
- {
- memcpy (optr, uuid + sizeof ("LVM-") - 1 + dashes[i],
- dashes[i+1] - dashes[i]);
- optr += dashes[i+1] - dashes[i];
- *optr++ = '-';
- }
- optr--;
- *optr = '\0';
- grub_free (uuid);
- return vgid;
- }
- void
- grub_util_devmapper_cleanup (void)
- {
- dm_lib_release ();
- }
- #else
- void
- grub_util_pull_devmapper (const char *os_dev __attribute__ ((unused)))
- {
- return;
- }
- void
- grub_util_devmapper_cleanup (void)
- {
- }
- enum grub_dev_abstraction_types
- grub_util_get_dm_abstraction (const char *os_dev __attribute__ ((unused)))
- {
- return GRUB_DEV_ABSTRACTION_NONE;
- }
- char *
- grub_util_get_vg_uuid (const char *os_dev __attribute__ ((unused)))
- {
- return NULL;
- }
- char *
- grub_util_devmapper_part_to_disk (struct stat *st __attribute__ ((unused)),
- int *is_part __attribute__ ((unused)),
- const char *os_dev __attribute__ ((unused)))
- {
- return NULL;
- }
- char *
- grub_util_get_devmapper_grub_dev (const char *os_dev __attribute__ ((unused)))
- {
- return NULL;
- }
- #endif
|