gpt-auto-generator.c revision 4c8bda2442bfc6d84a5deb241dc29efcb81bf3af
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/***
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering This file is part of systemd.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Copyright 2013 Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering (at your option) any later version.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is distributed in the hope that it will be useful, but
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Lesser General Public License for more details.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering***/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <unistd.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <stdlib.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <fcntl.h>
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther#include <sys/ioctl.h>
6482f6269c87d2249e52e889a63adbdd50f2d691Ronny Chevalier#include <sys/statfs.h>
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include <blkid.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#ifdef HAVE_LINUX_BTRFS_H
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include <linux/btrfs.h>
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#endif
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#include "path-util.h"
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#include "util.h"
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#include "mkdir.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "missing.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "sd-id128.h"
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "libudev.h"
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#include "udev-util.h"
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering#include "special.h"
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering#include "unit-name.h"
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering#include "virt.h"
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering/* TODO:
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering *
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering * - Properly handle cryptsetup partitions
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering * - Define new partition type for encrypted swap
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering * - Make /home automount rather than mount
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering *
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering */
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#define GPT_SWAP SD_ID128_MAKE(06,57,fd,6d,a4,ab,43,c4,84,e5,09,33,c8,4b,4f,4f)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#define GPT_HOME SD_ID128_MAKE(93,3a,c7,e1,2e,b4,4f,13,b8,44,0e,14,e2,ae,f9,15)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmekstatic const char *arg_dest = "/tmp";
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-SzmekDEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poetteringstatic int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering const char *v;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering int r;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering errno = 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering b = blkid_new_probe_from_filename(node);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (!b)
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering return errno != 0 ? -errno : -ENOMEM;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering blkid_probe_enable_superblocks(b, 1);
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering blkid_probe_enable_partitions(b, 1);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering errno = 0;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering r = blkid_do_safeprobe(b);
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek if (r == -2)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return -ENODEV;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek else if (r == 1)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek return -ENODEV;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek else if (r != 0)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return errno ? -errno : -EIO;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering errno = 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering if (r != 0)
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering /* return 0 if we're not on GPT */
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering return errno ? -errno : 0;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (strcmp(v, "gpt") != 0)
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return 0;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering if (type) {
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering errno = 0;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek if (r != 0)
320814811417146cfa1e416f69f1101eed630c36Luke Shumaker return errno ? -errno : -EIO;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering r = sd_id128_from_string(v, type);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (r < 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return r;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (nr) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering errno = 0;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek if (r != 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return errno ? -errno : -EIO;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering r = safe_atou(v, nr);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (r < 0)
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering return r;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (fstype) {
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering errno = 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (r != 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering *fstype = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering else {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering char *fst;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering fst = strdup(v);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (!fst)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return -ENOMEM;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering *fstype = fst;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering }
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering }
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return 1;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering}
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poetteringstatic int add_swap(const char *path, const char *fstype) {
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering log_debug("Adding swap: %s %s", path, fstype);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering name = unit_name_from_path(path, ".swap");
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering if (!name)
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return log_oom();
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (!unit)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return log_oom();
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering f = fopen(unit, "wxe");
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (!f) {
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -errno;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering }
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering fprintf(f,
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "[Unit]\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "DefaultDependencies=no\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_SWAP_TARGET "\n\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "[Swap]\n"
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "What=%s\n",
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering path);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering fflush(f);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (ferror(f)) {
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -errno;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!lnk)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return log_oom();
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering mkdir_parents_label(lnk, 0755);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (symlink(unit, lnk) < 0) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return -errno;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering }
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return 0;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poetteringstatic int add_home(const char *path, const char *fstype) {
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *fsck = NULL;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
fed1e721fd0c81e60c77120539f34e16c2585634Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (dir_is_empty("/home") <= 0)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return 0;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering log_debug("Adding home: %s %s", path, fstype);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering unit = strappend(arg_dest, "/home.mount");
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!unit)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering f = fopen(unit, "wxe");
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!f) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return -errno;
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering fsck = unit_name_from_path_instance("systemd-fsck", path, ".service");
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!fsck)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering fprintf(f,
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "[Unit]\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "DefaultDependencies=no\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Requires=%s\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "After=" SPECIAL_LOCAL_FS_PRE_TARGET " %s\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "Conflicts=" SPECIAL_UMOUNT_TARGET "\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Before=" SPECIAL_UMOUNT_TARGET " " SPECIAL_LOCAL_FS_TARGET "\n\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "[Mount]\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "What=%s\n"
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering "Where=/home\n"
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering "Type=%s\n",
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering fsck, fsck, path, fstype);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering fflush(f);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (ferror(f)) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering log_error("Failed to write unit file %s: %m", unit);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return -errno;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/home.mount", NULL);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!lnk)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return log_oom();
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering mkdir_parents_label(lnk, 0755);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (symlink(unit, lnk) < 0) {
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return -errno;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers return 0;
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers}
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poetteringstatic int enumerate_partitions(struct udev *udev, dev_t dev) {
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering struct udev_device *parent = NULL;
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering struct udev_list_entry *first, *item;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering unsigned home_nr = (unsigned) -1;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering _cleanup_free_ char *home = NULL, *home_fstype = NULL;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering int r;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering e = udev_enumerate_new(udev);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering if (!e)
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return log_oom();
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering d = udev_device_new_from_devnum(udev, 'b', dev);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering if (!d)
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return log_oom();
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering parent = udev_device_get_parent(d);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (!parent)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return log_oom();
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (r < 0)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return log_oom();
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (r < 0)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return log_oom();
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering r = udev_enumerate_scan_devices(e);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (r < 0) {
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s",
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering major(dev), minor(dev), strerror(-r));
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return r;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering }
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering first = udev_enumerate_get_list_entry(e);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering udev_list_entry_foreach(item, first) {
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_free_ char *fstype = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering const char *node = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *q;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering sd_id128_t type_id;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering unsigned nr;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering if (!q)
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering return log_oom();
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering continue;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek continue;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering node = udev_device_get_devnode(q);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (!node)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return log_oom();
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering r = verify_gpt_partition(node, &type_id, &nr, &fstype);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (r < 0) {
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther log_error("Failed to verify GPT partition %s: %s",
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering node, strerror(-r));
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther return r;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering }
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (r == 0)
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering continue;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek if (sd_id128_equal(type_id, GPT_SWAP))
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek add_swap(node, fstype);
else if (sd_id128_equal(type_id, GPT_HOME)) {
if (!home || nr < home_nr) {
free(home);
home = strdup(node);
if (!home)
return log_oom();
home_nr = nr;
free(home_fstype);
home_fstype = fstype;
fstype = NULL;
}
}
}
if (home && home_fstype)
add_home(home, home_fstype);
return r;
}
static int get_btrfs_block_device(const char *path, dev_t *dev) {
struct btrfs_ioctl_fs_info_args fsi = {};
_cleanup_close_ int fd = -1;
uint64_t id;
assert(path);
assert(dev);
fd = open(path, O_DIRECTORY|O_CLOEXEC);
if (fd < 0)
return -errno;
if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
return -errno;
/* We won't do this for btrfs RAID */
if (fsi.num_devices != 1)
return 0;
for (id = 1; id <= fsi.max_id; id++) {
struct btrfs_ioctl_dev_info_args di = {
.devid = id,
};
struct stat st;
if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
if (errno == ENODEV)
continue;
return -errno;
}
if (stat((char*) di.path, &st) < 0)
return -errno;
if (!S_ISBLK(st.st_mode))
return -ENODEV;
if (major(st.st_rdev) == 0)
return -ENODEV;
*dev = st.st_rdev;
return 1;
}
return -ENODEV;
}
static int get_block_device(const char *path, dev_t *dev) {
struct stat st;
struct statfs sfs;
assert(path);
assert(dev);
if (lstat("/", &st))
return -errno;
if (major(st.st_dev) != 0) {
*dev = st.st_dev;
return 1;
}
if (statfs("/", &sfs) < 0)
return -errno;
if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
return get_btrfs_block_device(path, dev);
return 0;
}
static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
_cleanup_udev_device_unref_ struct udev_device *d;
const char *t;
char *n;
d = udev_device_new_from_devnum(udev, 'b', devno);
if (!d)
return log_oom();
t = udev_device_get_devnode(d);
if (!t)
return -ENODEV;
n = strdup(t);
if (!n)
return -ENOMEM;
*ret = n;
return 0;
}
int main(int argc, char *argv[]) {
_cleanup_free_ char *node = NULL;
_cleanup_udev_unref_ struct udev *udev = NULL;
dev_t devno;
int r = 0;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
r = -EINVAL;
goto finish;
}
if (argc > 1)
arg_dest = argv[3];
log_set_target(LOG_TARGET_SAFE);
log_parse_environment();
log_open();
umask(0022);
if (in_initrd()) {
log_debug("In initrd, exiting.");
goto finish;
}
if (detect_container(NULL) > 0) {
log_debug("In a container, exiting.");
goto finish;
}
r = get_block_device("/", &devno);
if (r < 0) {
log_error("Failed to determine block device of root file system: %s", strerror(-r));
goto finish;
}
if (r == 0) {
log_debug("Root file system not on a (single) block device.");
goto finish;
}
udev = udev_new();
if (!udev) {
r = log_oom();
goto finish;
}
r = devno_to_devnode(udev, devno, &node);
if (r < 0) {
log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
goto finish;
}
log_debug("Root device %s.", node);
r = verify_gpt_partition(node, NULL, NULL, NULL);
if (r < 0) {
log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
goto finish;
}
if (r == 0)
goto finish;
r = enumerate_partitions(udev, devno);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}