/* fs_uuid.c - Access disks by their filesystem UUID. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2007,2008 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 . */ #include #include #include #include #include #include #include #include static grub_device_t search_fs_uuid (const char *key, unsigned long *count) { *count = 0; grub_device_t ret = NULL; auto int iterate_device (const char *name); int iterate_device (const char *name) { grub_device_t dev; dev = grub_device_open (name); if (dev) { grub_fs_t fs; fs = grub_fs_probe (dev); if (fs && fs->uuid) { char *uuid; (fs->uuid) (dev, &uuid); if (grub_errno == GRUB_ERR_NONE && uuid) { (*count)++; if (grub_strcasecmp (uuid, key) == 0) { ret = dev; grub_free (uuid); return 1; } grub_free (uuid); } } grub_device_close (dev); } grub_errno = GRUB_ERR_NONE; return 0; } grub_device_iterate (iterate_device); return ret; } static grub_err_t grub_fs_uuid_open (const char *name, grub_disk_t disk) { grub_device_t dev; if (grub_strncmp (name, "UUID=", sizeof ("UUID=")-1)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a UUID virtual volume"); dev = search_fs_uuid (name + sizeof ("UUID=") - 1, &disk->id); if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching UUID found"); disk->total_sectors = dev->disk->total_sectors; disk->has_partitions = 0; if (dev->disk->partition) { disk->partition = grub_malloc (sizeof (*disk->partition)); if (disk->partition) grub_memcpy (disk->partition, dev->disk->partition, sizeof (*disk->partition)); } else disk->partition = NULL; disk->data = dev; return GRUB_ERR_NONE; } static void grub_fs_uuid_close (grub_disk_t disk __attribute((unused))) { grub_device_t parent = disk->data; grub_device_close (parent); } static grub_err_t grub_fs_uuid_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { grub_device_t parent = disk->data; return parent->disk->dev->read (parent->disk, sector, size, buf); } static grub_err_t grub_fs_uuid_write (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, const char *buf) { grub_device_t parent = disk->data; return parent->disk->dev->write (parent->disk, sector, size, buf); } static struct grub_disk_dev grub_fs_uuid_dev = { .name = "fs_uuid", .id = GRUB_DISK_DEVICE_UUID_ID, .open = grub_fs_uuid_open, .close = grub_fs_uuid_close, .read = grub_fs_uuid_read, .write = grub_fs_uuid_write, .next = 0 }; GRUB_MOD_INIT(fs_uuid) { grub_disk_dev_register (&grub_fs_uuid_dev); } GRUB_MOD_FINI(fs_uuid) { grub_disk_dev_unregister (&grub_fs_uuid_dev); }