gpt-auto-generator.c revision 1a14a53cfded6e78c6e8dfb73fdff0039971d642
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/***
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2013 Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is free software; you can redistribute it and/or modify it
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering under the terms of the GNU Lesser General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (at your option) any later version.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is distributed in the hope that it will be useful, but
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Lesser General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU Lesser General Public License
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering***/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <unistd.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <stdlib.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <fcntl.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <linux/btrfs.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <sys/ioctl.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <sys/statfs.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <blkid.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "path-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "mkdir.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "missing.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "sd-id128.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "libudev.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "special.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "unit-name.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/* TODO:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * - Properly handle cryptsetup partitions
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering * - Define new partition type for encrypted swap
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic const char *arg_dest = "/tmp";
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int verify_gpt_partition(dev_t dev, sd_id128_t *type, unsigned *nr, char **fstype) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *t = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_probe b = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *v;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = asprintf(&t, "/dev/block/%u:%u", major(dev), minor(dev));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering b = blkid_new_probe_from_filename(t);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!b) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (errno != 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_probe_enable_superblocks(b, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_probe_enable_partitions(b, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = blkid_do_safeprobe(b);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == -2) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = -ENODEV;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else if (r == 1) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = -ENODEV;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else if (r != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = errno ? -errno : -EIO;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = errno ? -errno : -EIO;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strcmp(v, "gpt") != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (type) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = errno ? -errno : -EIO;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_id128_from_string(v, type);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (nr) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = errno ? -errno : -EIO;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = safe_atou(v, nr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (fstype) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *fst;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering errno = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r != 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *fstype = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fst = strdup(v);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!fst) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *fstype = fst;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfinish:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (b)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering blkid_free_probe(b);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int add_swap(const char *path, const char *fstype) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Adding swap: %s %s", path, fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering name = unit_name_from_path(path, ".swap");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!name)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!unit)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering f = fopen(unit, "wxe");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!f) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "[Unit]\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "DefaultDependencies=no\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_SWAP_TARGET "\n\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "[Mount]\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "What=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fflush(f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ferror(f)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!lnk)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering mkdir_parents_label(lnk, 0755);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (symlink(unit, lnk) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int add_home(const char *path, const char *fstype) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Adding home: %s %s", path, fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unit = strappend(arg_dest, "/home.mount");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!unit)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering f = fopen(unit, "wxe");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!f) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "[Unit]\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "DefaultDependencies=no\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "After=" SPECIAL_LOCAL_FS_PRE_TARGET "\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_LOCAL_FS_TARGET "\n\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "[Mount]\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "What=%s\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Where=/home\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "Type=%s\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "FsckPassNo=2\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering path, fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fflush(f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ferror(f)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/home.mount", NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!lnk)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering mkdir_parents_label(lnk, 0755);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (symlink(unit, lnk) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int enumerate_partitions(dev_t dev) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct udev *udev;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct udev_enumerate *e = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct udev_device *parent = NULL, *d = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct udev_list_entry *first, *item;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned home_nr = (unsigned) -1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *home = NULL, *home_fstype = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev = udev_new();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!udev)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering e = udev_enumerate_new(udev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!e) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering d = udev_device_new_from_devnum(udev, 'b', dev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!d) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering parent = udev_device_get_parent(d);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!parent) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = udev_enumerate_scan_devices(e);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to enumerate partitions: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering first = udev_enumerate_get_list_entry(e);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_list_entry_foreach(item, first) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *fstype = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *node = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct udev_device *q;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_id128_t type_id;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned nr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!q) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto skip;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto skip;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering node = udev_device_get_devnode(q);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!node) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = verify_gpt_partition(udev_device_get_devnum(q), &type_id, &nr, &fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to verify GPT partition: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_device_unref(q);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto skip;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart 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)))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering add_swap(node, fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart 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))) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!home || nr < home_nr) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(home);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering home = strdup(node);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!home) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = log_oom();
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering home_nr = nr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(home_fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering home_fstype = fstype;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fstype = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering skip:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_device_unref(q);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (home && home_fstype)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering add_home(home, home_fstype);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfinish:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (d)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_device_unref(d);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (e)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_enumerate_unref(e);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (udev)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering udev_unref(udev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int get_btrfs_block_device(const char *path, dev_t *dev) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct btrfs_ioctl_fs_info_args fsi;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_close_ int fd = -1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering uint64_t id;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(dev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fd = open(path, O_DIRECTORY|O_CLOEXEC);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (fd < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering zero(fsi);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* We won't do this for btrfs RAID */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (fsi.num_devices != 1)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (id = 1; id <= fsi.max_id; id++) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct btrfs_ioctl_dev_info_args di;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct stat st;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering zero(di);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering di.devid = id;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (errno == ENODEV)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering continue;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (stat((char*) di.path, &st) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!S_ISBLK(st.st_mode))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENODEV;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (major(st.st_rdev) == 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENODEV;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *dev = st.st_rdev;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENODEV;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int get_block_device(const char *path, dev_t *dev) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct stat st;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct statfs sfs;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(dev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (lstat("/", &st))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (major(st.st_dev) != 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *dev = st.st_dev;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 1;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (statfs("/", &sfs) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -errno;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (F_TYPE_CMP(sfs.f_type, BTRFS_SUPER_MAGIC))
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return get_btrfs_block_device(path, dev);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return 0;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering}
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringint main(int argc, char *argv[]) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering dev_t dev;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering int r;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (argc > 1 && argc != 4) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_error("This program takes three or no arguments.");
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return EXIT_FAILURE;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering }
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (argc > 1)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering arg_dest = argv[3];
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_set_target(LOG_TARGET_SAFE);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_parse_environment();
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_open();
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering umask(0022);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (in_initrd())
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return EXIT_SUCCESS;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = get_block_device("/", &dev);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_error("Failed to determine block device of root file system: %s", strerror(-r));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return EXIT_FAILURE;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering }
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r == 0) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_debug("Root file system not on a (single) block device.");
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return EXIT_SUCCESS;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering }
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_debug("Root device %u:%u.", major(dev), minor(dev));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = verify_gpt_partition(dev, NULL, NULL, NULL);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_error("Failed to verify GPT partition: %s", strerror(-r));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return EXIT_FAILURE;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return EXIT_SUCCESS;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = enumerate_partitions(dev);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering