gpt-auto-generator.c revision c51cf05646a11c65daf65c1123c77efb068f4f7b
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering This file is part of systemd.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Copyright 2013 Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering (at your option) any later version.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is distributed in the hope that it will be useful, but
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Lesser General Public License for more details.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering * - Properly handle cryptsetup partitions
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering * - Define new partition type for encrypted swap
4b1b14a6a6acb1640596d5e9542829d32989d385Lennart Poettering * - Make /home automount rather than mount
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmekstatic inline void blkid_free_probep(blkid_probe *b) {
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek#define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int verify_gpt_partition(dev_t dev, sd_id128_t *type, unsigned *nr, char **fstype) {
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering const char *v;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = asprintf(&t, "/dev/block/%u:%u", major(dev), minor(dev));
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek return errno != 0 ? -errno : -ENOMEM;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek else if (r == 1)
7384146530ac083efbef62b9ef5bb82c56565cd4Zbigniew Jędrzejewski-Szmek else if (r != 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
091526ab20485492124852dcf629787f35816df8Zbigniew Jędrzejewski-Szmek /* return 0 if we're not on GPT */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_swap(const char *path, const char *fstype) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Adding swap: %s %s", path, fstype);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering name = unit_name_from_path(path, ".swap");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "DefaultDependencies=no\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_SWAP_TARGET "\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int add_home(const char *path, const char *fstype) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Adding home: %s %s", path, fstype);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering unit = strappend(arg_dest, "/home.mount");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "DefaultDependencies=no\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "After=" SPECIAL_LOCAL_FS_PRE_TARGET "\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_LOCAL_FS_TARGET "\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "Where=/home\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "FsckPassNo=2\n",
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/home.mount", NULL);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int enumerate_partitions(dev_t dev) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering struct udev_device *parent = NULL, *d = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_free_ char *home = NULL, *home_fstype = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering d = udev_device_new_from_devnum(udev, 'b', dev);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s",
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek major(dev), minor(dev), strerror(-r));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering first = udev_enumerate_get_list_entry(e);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek sub = udev_device_get_devnum(q);
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek r = verify_gpt_partition(sub, &type_id, &nr, &fstype);
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek log_error("Failed to verify GPT partition /dev/block/%u:%u: %s",
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek major(sub), minor(sub), strerror(-r));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (sd_id128_equal(type_id, SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering else if (sd_id128_equal(type_id, SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15))) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int get_btrfs_block_device(const char *path, dev_t *dev) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering /* We won't do this for btrfs RAID */
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int get_block_device(const char *path, dev_t *dev) {
c51cf05646a11c65daf65c1123c77efb068f4f7bZbigniew Jędrzejewski-Szmek if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return get_btrfs_block_device(path, dev);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("This program takes three or no arguments.");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_error("Failed to determine block device of root file system: %s", strerror(-r));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering log_debug("Root file system not on a (single) block device.");
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek log_debug("Root device /dev/block/%u:%u.", major(dev), minor(dev));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = verify_gpt_partition(dev, NULL, NULL, NULL);
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek log_error("Failed to verify GPT partition /dev/block/%u:%u: %s",
d98cc1c019651b895464161072894a02cc43daabZbigniew Jędrzejewski-Szmek major(dev), minor(dev), strerror(-r));