gpt-auto-generator.c revision 1af7211984a8dba3c5ba40fae794c4c55f5e6bd3
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/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 "sd-id128.h"
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#include "libudev.h"
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek#include "path-util.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "util.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "mkdir.h"
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "missing.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#include "generator.h"
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering#include "gpt.h"
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#include "fileio.h"
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poetteringstatic const char *arg_dest = "/tmp";
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart PoetteringDEFINE_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) {
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering const char *v;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek int r;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek errno = 0;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering b = blkid_new_probe_from_filename(node);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (!b)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return errno != 0 ? -errno : -ENOMEM;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering blkid_probe_enable_superblocks(b, 1);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering blkid_probe_enable_partitions(b, 1);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering errno = 0;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering r = blkid_do_safeprobe(b);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return -EBADSLT;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek else if (r != 0)
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering return errno ? -errno : -EIO;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering errno = 0;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (r != 0)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek /* return 0 if we're not on GPT */
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return errno ? -errno : 0;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek if (strcmp(v, "gpt") != 0)
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek return 0;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (type) {
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering errno = 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering if (r != 0)
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering return errno ? -errno : -EIO;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering r = sd_id128_from_string(v, type);
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (r < 0)
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering return r;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering }
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering if (nr) {
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering errno = 0;
d4fffc4b8beb86e77fd710c1f43913a490ed083aZbigniew Jędrzejewski-Szmek r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
320814811417146cfa1e416f69f1101eed630c36Luke Shumaker if (r != 0)
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering return errno ? -errno : -EIO;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering r = safe_atou(v, nr);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (r < 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return r;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek if (fstype) {
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek errno = 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering if (r != 0)
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering *fstype = NULL;
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering else {
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poettering char *fst;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering fst = strdup(v);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!fst)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return -ENOMEM;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering *fstype = fst;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 1;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering}
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
cfeaa44a09756a93a881f786678973d9b1e382dbLennart Poetteringstatic int add_swap(const char *path, const char *fstype) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
7027ff61a34a12487712b382a061c654acc3a679Lennart 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
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering unit = strjoin(arg_dest, "/", name, NULL);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering if (!unit)
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return log_oom();
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering f = fopen(unit, "wxe");
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering if (!f) {
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering log_error("Failed to create unit file %s: %m", unit);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering return -errno;
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering }
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering fprintf(f,
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\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;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering }
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (!lnk)
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return log_oom();
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering mkdir_parents_label(lnk, 0755);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (symlink(unit, lnk) < 0) {
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering log_error("Failed to create symlink %s: %m", lnk);
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return -errno;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering }
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering return 0;
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering}
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poetteringstatic int add_cryptsetup(const char *id, const char *what, char **device) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering _cleanup_fclose_ FILE *f = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering char *from, *ret;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering int r;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(id);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(what);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(device);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering d = unit_name_from_path(what, ".device");
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!d)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering e = unit_name_escape(id);
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering if (!e)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
fed1e721fd0c81e60c77120539f34e16c2585634Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering n = unit_name_build("systemd-cryptsetup", e, ".service");
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!n)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering p = strjoin(arg_dest, "/", n, NULL);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!n)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return log_oom();
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering f = fopen(p, "wxe");
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!f) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering log_error("Failed to create unit file %s: %m", p);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return -errno;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering }
e9174f29c7e3ee45137537b126458718913a3ec5Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering fprintf(f,
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "[Unit]\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Description=Cryptography Setup for %%I\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Documentation=man:systemd-cryptsetup@.service(8)\n"
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering "DefaultDependencies=no\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Conflicts=umount.target\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "BindsTo=dev-mapper-%%i.device %s\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "Before=umount.target cryptsetup.target\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "After=%s\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "IgnoreOnIsolate=true\n"
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "[Service]\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "Type=oneshot\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "RemainAfterExit=yes\n"
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering "TimeoutSec=0\n" /* the binary handles timeouts anyway */
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s'\n"
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering d, d,
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering id, what,
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering id);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering fflush(f);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (ferror(f)) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering log_error("Failed to write file %s: %m", p);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return -errno;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering from = strappenda("../", n);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!to)
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering return log_oom();
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering mkdir_parents_label(to, 0755);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (symlink(from, to) < 0) {
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers log_error("Failed to create symlink %s: %m", to);
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers return -errno;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering free(to);
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering if (!to)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return log_oom();
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering mkdir_parents_label(to, 0755);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering if (symlink(from, to) < 0) {
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering log_error("Failed to create symlink %s: %m", to);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return -errno;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering }
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering free(to);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering if (!to)
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return log_oom();
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering mkdir_parents_label(to, 0755);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (symlink(from, to) < 0) {
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering log_error("Failed to create symlink %s: %m", to);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return -errno;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering }
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(p);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (!p)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return log_oom();
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering mkdir_parents_label(p, 0755);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering r = write_string_file(p,
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering "[Unit]\n"
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (r < 0) {
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering log_error("Failed to write device drop-in: %s", strerror(-r));
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering return r;
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering }
c96cc5822c165e86be78ed96dac6573986032fabLennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering ret = strappend("/dev/mapper/", id);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (!ret)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return log_oom();
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering *device = ret;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering return 0;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering}
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poetteringstatic int add_mount(const char *id, const char *what, const char *where, const char *fstype, const char *description) {
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering int r;
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering assert(id);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering assert(what);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering assert(where);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering assert(fstype);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering assert(description);
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek if (dir_is_empty(where) <= 0) {
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering log_debug("%s already populated, ignoring.", where);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return 0;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering log_debug("Adding %s: %s %s", where, what, fstype);
8b0849e9710d721c5d0b775aaf0fd662eefa1449Lennart Poettering
329ac4bc5429cd86c4ac76b13e7e2784f3982760Lennart Poettering if (streq(fstype, "crypto_LUKS")) {
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering r = add_cryptsetup(id, what, &crypto_what);
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther if (r < 0)
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return r;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
751bc6ac79320bc16e63e8c1bbb713c30a3b7bc9Lennart Poettering what = crypto_what;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek fstype = NULL;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek }
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
unit = unit_name_from_path(where, ".mount");
if (!unit)
return log_oom();
p = strjoin(arg_dest, "/", unit, NULL);
if (!p)
return log_oom();
f = fopen(p, "wxe");
if (!f) {
log_error("Failed to create unit file %s: %m", unit);
return -errno;
}
fprintf(f,
"# Automatically generated by systemd-gpt-auto-generator\n\n"
"[Unit]\n"
"Description=%s\n",
description);
r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
if (r < 0)
return r;
fprintf(f,
"\n"
"[Mount]\n"
"What=%s\n"
"Where=%s\n",
what, where);
if (fstype) {
fprintf(f,
"Type=%s\n",
fstype);
}
fflush(f);
if (ferror(f)) {
log_error("Failed to write unit file %s: %m", unit);
return -errno;
}
lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/", unit, NULL);
if (!lnk)
return log_oom();
mkdir_parents_label(lnk, 0755);
if (symlink(unit, lnk) < 0) {
log_error("Failed to create symlink %s: %m", lnk);
return -errno;
}
return 0;
}
static int enumerate_partitions(struct udev *udev, dev_t dev) {
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
_cleanup_free_ char *home = NULL, *home_fstype = NULL, *srv = NULL, *srv_fstype = NULL;
unsigned home_nr = (unsigned) -1, srv_nr = (unsigned )-1;
struct udev_list_entry *first, *item;
struct udev_device *parent = NULL;
int r;
e = udev_enumerate_new(udev);
if (!e)
return log_oom();
d = udev_device_new_from_devnum(udev, 'b', dev);
if (!d)
return log_oom();
parent = udev_device_get_parent(d);
if (!parent)
return log_oom();
r = udev_enumerate_add_match_parent(e, parent);
if (r < 0)
return log_oom();
r = udev_enumerate_add_match_subsystem(e, "block");
if (r < 0)
return log_oom();
r = udev_enumerate_scan_devices(e);
if (r < 0) {
log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s", major(dev), minor(dev), strerror(-r));
return r;
}
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
_cleanup_udev_device_unref_ struct udev_device *q;
_cleanup_free_ char *fstype = NULL;
const char *node = NULL;
sd_id128_t type_id;
unsigned nr;
q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
if (!q)
return log_oom();
if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
continue;
if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
continue;
node = udev_device_get_devnode(q);
if (!node)
return log_oom();
r = verify_gpt_partition(node, &type_id, &nr, &fstype);
if (r < 0) {
/* skip child devices which are not detected properly */
if (r == -EBADSLT)
continue;
log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
return r;
}
if (r == 0)
continue;
if (sd_id128_equal(type_id, GPT_SWAP))
add_swap(node, fstype);
else if (sd_id128_equal(type_id, GPT_HOME)) {
/* We only care for the first /home partition */
if (home && nr >= home_nr)
continue;
home_nr = nr;
free(home);
home = strdup(node);
if (!home)
return log_oom();
free(home_fstype);
home_fstype = fstype;
fstype = NULL;
} else if (sd_id128_equal(type_id, GPT_SRV)) {
/* We only care for the first /srv partition */
if (srv && nr >= srv_nr)
continue;
srv_nr = nr;
free(srv);
srv = strdup(node);
if (!srv)
return log_oom();
free(srv_fstype);
srv_fstype = fstype;
fstype = NULL;
}
}
if (home && home_fstype)
add_mount("home", home, "/home", home_fstype, "Home Partition");
if (srv && srv_fstype)
add_mount("srv", srv, "/srv", srv_fstype, "Server Data Partition");
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(path, &st))
return -errno;
if (major(st.st_dev) != 0) {
*dev = st.st_dev;
return 1;
}
if (statfs(path, &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_udev_unref_ struct udev *udev = NULL;
_cleanup_free_ char *node = NULL;
dev_t devno;
int r = 0;
if (argc > 1 && argc != 4) {
log_error("This program takes three or no arguments.");
return EXIT_FAILURE;
}
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.");
return EXIT_SUCCESS;
}
if (detect_container(NULL) > 0) {
log_debug("In a container, exiting.");
return EXIT_SUCCESS;
}
r = get_block_device("/", &devno);
if (r < 0) {
log_error("Failed to determine block device of root file system: %s", strerror(-r));
return EXIT_FAILURE;
} else if (r == 0) {
log_debug("Root file system not on a (single) block device.");
return EXIT_SUCCESS;
}
udev = udev_new();
if (!udev) {
log_oom();
return EXIT_FAILURE;
}
r = devno_to_devnode(udev, devno, &node);
if (r < 0) {
log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
return EXIT_FAILURE;
}
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));
return EXIT_FAILURE;
}
if (r == 0) {
log_debug("Not a GPT disk, exiting.");
return EXIT_SUCCESS;
}
r = enumerate_partitions(udev, devno);
if (r < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}