1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering/***
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering This file is part of systemd.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Copyright 2013 Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering (at your option) any later version.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering systemd is distributed in the hope that it will be useful, but
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering Lesser General Public License for more details.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering***/
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include <blkid/blkid.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <stdlib.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include <sys/statfs.h>
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include <unistd.h>
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
b4bbcaa9c44260e88402cb8f9a5fb8ac7f35e123Thomas Hindoe Paaboel Andersen#include "libudev.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-id128.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "blkid-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "btrfs-util.h"
a09561746f15b84da9471b5c4be74e53d19e4f3fLennart Poettering#include "dirent-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "efivars.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fileio.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fstab-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "generator.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "gpt.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "missing.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "mkdir.h"
4349cd7c1d153c4ffa23cf1cff1644e0afa9bcf0Lennart Poettering#include "mount-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "parse-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "path-util.h"
4e731273edfe852a3eee2949cd20f49fd5b4f6d7Lennart Poettering#include "proc-cmdline.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "special.h"
8fcde01280adcbd07e8205b91ac52b06305b6208Lennart Poettering#include "stat-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "udev-util.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering#include "unit-name.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "util.h"
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek#include "virt.h"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic const char *arg_dest = "/tmp";
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic bool arg_enabled = true;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic bool arg_root_enabled = true;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic bool arg_root_rw = false;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poetteringstatic int add_cryptsetup(const char *id, const char *what, bool rw, char **device) {
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering char *from, *ret;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering int r;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(id);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(what);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(device);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering r = unit_name_from_path(what, ".device", &d);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering if (r < 0)
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering e = unit_name_escape(id);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!e)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering r = unit_name_build("systemd-cryptsetup", e, ".service", &n);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering if (r < 0)
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering p = strjoin(arg_dest, "/", n, NULL);
821b2e792159e237a1e5a1ea4bb6ae2e55d64be5Lukas Nykryn if (!p)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering f = fopen(p, "wxe");
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (!f)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create unit file %s: %m", p);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering fprintf(f,
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "[Unit]\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "Description=Cryptography Setup for %%I\n"
c3834f9b881f2b1a68dc7d797c134f0b66b47b57Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8) man:systemd-cryptsetup@.service(8)\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "DefaultDependencies=no\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "Conflicts=umount.target\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "BindsTo=dev-mapper-%%i.device %s\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "Before=umount.target cryptsetup.target\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "After=%s\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "IgnoreOnIsolate=true\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "[Service]\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "Type=oneshot\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "RemainAfterExit=yes\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "TimeoutSec=0\n" /* the binary handles timeouts anyway */
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s' '' '%s'\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering d, d,
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering id, what, rw ? "" : "read-only",
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering id);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = fflush_and_check(f);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering return log_error_errno(r, "Failed to write file %s: %m", p);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering from = strjoina("../", n);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!to)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering mkdir_parents_label(to, 0755);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (symlink(from, to) < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering free(to);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!to)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering mkdir_parents_label(to, 0755);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (symlink(from, to) < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering free(to);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!to)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering mkdir_parents_label(to, 0755);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (symlink(from, to) < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create symlink %s: %m", to);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering free(p);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!p)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering mkdir_parents_label(p, 0755);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering r = write_string_file(p,
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "[Unit]\n"
4c1fc3e404d648c70bd2f50ac50aeac6ece8872eDaniel Mack "JobTimeoutSec=0\n",
4c1fc3e404d648c70bd2f50ac50aeac6ece8872eDaniel Mack WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_error_errno(r, "Failed to write device drop-in: %m");
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering ret = strappend("/dev/mapper/", id);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (!ret)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return log_oom();
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering *device = ret;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return 0;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering}
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic int add_mount(
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *id,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *what,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *where,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *fstype,
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering bool rw,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers const char *options,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *description,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering const char *post) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(id);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(what);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(where);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering assert(description);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_debug("Adding %s: %s %s", where, what, strna(fstype));
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (streq_ptr(fstype, "crypto_LUKS")) {
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering r = add_cryptsetup(id, what, rw, &crypto_what);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering if (r < 0)
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering return r;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering what = crypto_what;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering fstype = NULL;
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering }
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering r = unit_name_from_path(where, ".mount", &unit);
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering if (r < 0)
7410616cd9dbbec97cf98d75324da5cda2b2f7a2Lennart Poettering return log_error_errno(r, "Failed to generate unit name: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering p = strjoin(arg_dest, "/", unit, NULL);
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (!p)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering return log_oom();
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering f = fopen(p, "wxe");
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (!f)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering fprintf(f,
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "# Automatically generated by systemd-gpt-auto-generator\n\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Unit]\n"
c3834f9b881f2b1a68dc7d797c134f0b66b47b57Lennart Poettering "Description=%s\n"
c3834f9b881f2b1a68dc7d797c134f0b66b47b57Lennart Poettering "Documentation=man:systemd-gpt-auto-generator(8)\n",
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering description);
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (post)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering fprintf(f, "Before=%s\n", post);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (r < 0)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering return r;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering fprintf(f,
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering "\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "[Mount]\n"
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering "What=%s\n"
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering "Where=%s\n",
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering what, where);
1af7211984a8dba3c5ba40fae794c4c55f5e6bd3Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (fstype)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering fprintf(f, "Type=%s\n", fstype);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (options)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers fprintf(f, "Options=%s,%s\n", options, rw ? "rw" : "ro");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers else
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers fprintf(f, "Options=%s\n", rw ? "rw" : "ro");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = fflush_and_check(f);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", p);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (post) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering lnk = strjoin(arg_dest, "/", post, ".requires/", unit, NULL);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (!lnk)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering mkdir_parents_label(lnk, 0755);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (symlink(p, lnk) < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sieversstatic bool path_is_busy(const char *where) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers int r;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers /* already a mountpoint; generators run during reload */
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = path_is_mount_point(where, AT_SYMLINK_FOLLOW);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r > 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return false;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers /* the directory might not exist on a stateless system */
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r == -ENOENT)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return false;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r < 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return true;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers /* not a mountpoint but it contains files */
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (dir_is_empty(where) <= 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return true;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return false;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers}
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poetteringstatic int probe_and_add_mount(
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *id,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *what,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *where,
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering bool rw,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *description,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *post) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
a0b1209c4a59754f428894e0485413542da50014Zbigniew Jędrzejewski-Szmek const char *fstype = NULL;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering int r;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering assert(id);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering assert(what);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering assert(where);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering assert(description);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (path_is_busy(where)) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering log_debug("%s already populated, ignoring.", where);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering /* Let's check the partition type here, so that we know
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering * whether to do LUKS magic. */
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering b = blkid_new_probe_from_filename(what);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!b) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (errno == 0)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return log_oom();
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt return log_error_errno(errno, "Failed to allocate prober: %m");
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_probe_enable_superblocks(b, 1);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering r = blkid_do_safeprobe(b);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (r == -2 || r == 1) /* no result or uncertain */
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
a0b1209c4a59754f428894e0485413542da50014Zbigniew Jędrzejewski-Szmek else if (r != 0)
a0b1209c4a59754f428894e0485413542da50014Zbigniew Jędrzejewski-Szmek return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
a0b1209c4a59754f428894e0485413542da50014Zbigniew Jędrzejewski-Szmek /* add_mount is OK with fstype being NULL. */
a0b1209c4a59754f428894e0485413542da50014Zbigniew Jędrzejewski-Szmek (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return add_mount(
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering id,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering what,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering where,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering fstype,
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering rw,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers NULL,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering description,
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering post);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering}
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sieversstatic int add_swap(const char *path) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers _cleanup_fclose_ FILE *f = NULL;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers int r;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers assert(path);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("Adding swap: %s", path);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = unit_name_from_path(path, ".swap", &name);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r < 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_error_errno(r, "Failed to generate unit name: %m");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers unit = strjoin(arg_dest, "/", name, NULL);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!unit)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_oom();
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers f = fopen(unit, "wxe");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!f)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers fprintf(f,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "# Automatically generated by systemd-gpt-auto-generator\n\n"
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "[Unit]\n"
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "Description=Swap Partition\n"
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "Documentation=man:systemd-gpt-auto-generator(8)\n\n"
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "[Swap]\n"
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "What=%s\n",
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers path);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering r = fflush_and_check(f);
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering return log_error_errno(r, "Failed to write unit file %s: %m", unit);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!lnk)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_oom();
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers mkdir_parents_label(lnk, 0755);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (symlink(unit, lnk) < 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers}
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers#ifdef ENABLE_EFI
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersenstatic int add_automount(
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *id,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *what,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *where,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *fstype,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen bool rw,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *options,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen const char *description,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen usec_t timeout) {
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen _cleanup_free_ char *unit = NULL, *lnk = NULL;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen _cleanup_free_ char *opt, *p = NULL;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen int r;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen assert(id);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen assert(where);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen assert(description);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (options)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen opt = strjoin(options, ",noauto", NULL);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen else
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen opt = strdup("noauto");
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (!opt)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_oom();
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen r = add_mount(id,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen what,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen where,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen fstype,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen rw,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen opt,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen description,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen NULL);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (r < 0)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return r;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen r = unit_name_from_path(where, ".automount", &unit);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (r < 0)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_error_errno(r, "Failed to generate unit name: %m");
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen p = strjoin(arg_dest, "/", unit, NULL);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (!p)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_oom();
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen f = fopen(p, "wxe");
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (!f)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_error_errno(errno, "Failed to create unit file %s: %m", unit);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen fprintf(f,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "# Automatically generated by systemd-gpt-auto-generator\n\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "[Unit]\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "Description=%s\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "Documentation=man:systemd-gpt-auto-generator(8)\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "[Automount]\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "Where=%s\n"
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen "TimeoutIdleSec=%lld\n",
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen description,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen where,
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen (unsigned long long)timeout / USEC_PER_SEC);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen r = fflush_and_check(f);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (r < 0)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_error_errno(r, "Failed to write unit file %s: %m", p);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/", unit, NULL);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (!lnk)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_oom();
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen mkdir_parents_label(lnk, 0755);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen if (symlink(p, lnk) < 0)
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen return 0;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen}
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersenstatic int add_boot(const char *what) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers _cleanup_blkid_free_probe_ blkid_probe b = NULL;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers const char *fstype = NULL, *uuid = NULL;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers sd_id128_t id, type_id;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers int r;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers assert(what);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!is_efi_boot()) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("Not an EFI boot, ignoring /boot.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (in_initrd()) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("In initrd, ignoring /boot.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
75f86906c52735c98dc0aa7e24b773edb42ee814Lennart Poettering if (detect_container() > 0) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("In a container, ignoring /boot.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers /* We create an .automount which is not overridden by the .mount from the fstab generator. */
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers if (fstab_is_mount_point("/boot")) {
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers log_debug("/boot specified in fstab, ignoring.");
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers return 0;
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers }
0b6b6787e3f0ae8906ce0212bd629edbe931b73dKay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (path_is_busy("/boot")) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("/boot already populated, ignoring.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = efi_loader_get_device_part_uuid(&id);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r == -ENOENT) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("EFI loader partition unknown.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r < 0) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_error_errno(r, "Failed to read ESP partition UUID: %m");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return r;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers errno = 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers b = blkid_new_probe_from_filename(what);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!b) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (errno == 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_oom();
e1427b138fbf7b7f13bb61187635b882be3ca2b2Michal Schmidt return log_error_errno(errno, "Failed to allocate prober: %m");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers blkid_probe_enable_partitions(b, 1);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers errno = 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = blkid_do_safeprobe(b);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r == -2 || r == 1) /* no result or uncertain */
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers else if (r != 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_error_errno(errno ?: EIO, "Failed to probe %s: %m", what);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers (void) blkid_probe_lookup_value(b, "TYPE", &fstype, NULL);
59e73c5b102402ea18aec1f4d69b4daad574e82bLennart Poettering if (!streq_ptr(fstype, "vfat")) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("Partition for /boot is not a FAT filesystem, ignoring.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59e73c5b102402ea18aec1f4d69b4daad574e82bLennart Poettering errno = 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = blkid_probe_lookup_value(b, "PART_ENTRY_UUID", &uuid, NULL);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (r != 0) {
59e73c5b102402ea18aec1f4d69b4daad574e82bLennart Poettering log_debug_errno(errno, "Partition for /boot does not have a UUID, ignoring.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (sd_id128_from_string(uuid, &type_id) < 0) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("Partition for /boot does not have a valid UUID, ignoring.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (!sd_id128_equal(type_id, id)) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers log_debug("Partition for /boot does not appear to be the partition we are booted from.");
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = add_automount("boot",
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers what,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "/boot",
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "vfat",
158df4b6a63c0d4e4f8de5210581619e7b693fb4Marius Thesing true,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers "umask=0077",
158df4b6a63c0d4e4f8de5210581619e7b693fb4Marius Thesing "EFI System Partition Automount",
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers 120 * USEC_PER_SEC);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return r;
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen}
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers#else
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersenstatic int add_boot(const char *what) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return 0;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers}
7a1494aa4e4a131d73e866cf1e7eb7b6e47dbab8Tom Gundersen#endif
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poetteringstatic int enumerate_partitions(dev_t devnum) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek _cleanup_udev_device_unref_ struct udev_device *d = NULL;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering _cleanup_blkid_free_probe_ blkid_probe b = NULL;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering _cleanup_udev_unref_ struct udev *udev = NULL;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering struct udev_list_entry *first, *item;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering struct udev_device *parent = NULL;
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek const char *name, *node, *pttype, *devtype;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers int boot_nr = -1, home_nr = -1, srv_nr = -1;
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering bool home_rw = true, srv_rw = true;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_partlist pl;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int r, k;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering dev_t pn;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering udev = udev_new();
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!udev)
b47d419c25ecc735615a1088060c1ec8bef1e41fZbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering d = udev_device_new_from_devnum(udev, 'b', devnum);
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek if (!d)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek name = udev_device_get_devnode(d);
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek if (!name)
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek name = udev_device_get_syspath(d);
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek if (!name) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("Device %u:%u does not have a name, ignoring.",
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek major(devnum), minor(devnum));
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek return 0;
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek }
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering parent = udev_device_get_parent(d);
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering if (!parent) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: not a partitioned device, ignoring.", name);
9c4495ca561624c2f0085507dd1288ed5f1247c5Tomasz Torcz return 0;
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering /* Does it have a devtype? */
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering devtype = udev_device_get_devtype(parent);
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering if (!devtype) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: parent doesn't have a device type, ignoring.", name);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering /* Is this a disk or a partition? We only care for disks... */
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering if (!streq(devtype, "disk")) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: parent isn't a raw disk, ignoring.", name);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering /* Does it have a device node? */
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering node = udev_device_get_devnode(parent);
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering if (!node) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: parent device does not have device node, ignoring.", name);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: root device %s.", name, node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering pn = udev_device_get_devnum(parent);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (major(pn) == 0)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering b = blkid_new_probe_from_filename(node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!b) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (errno == 0)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return log_oom();
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek return log_error_errno(errno, "%s: failed to allocate prober: %m", node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_probe_enable_partitions(b, 1);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering r = blkid_do_safeprobe(b);
458a2f85e8ae08c534bf8d030fbeeb791893422bTom Gundersen if (r == 1)
458a2f85e8ae08c534bf8d030fbeeb791893422bTom Gundersen return 0; /* no results */
458a2f85e8ae08c534bf8d030fbeeb791893422bTom Gundersen else if (r == -2) {
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering log_warning("%s: probe gave ambiguous results, ignoring.", node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
458a2f85e8ae08c534bf8d030fbeeb791893422bTom Gundersen } else if (r != 0)
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL);
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering if (r != 0) {
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering if (errno == 0)
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering return 0; /* No partition table found. */
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering return log_error_errno(errno, "%s: failed to determine partition table type: %m", node);
cb9712492f94153b7ce6fc03d6dd3fd95c87baa5Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering /* We only do this all for GPT... */
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering if (!streq_ptr(pttype, "gpt")) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s: not a GPT partition table, ignoring.", node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return 0;
fa041593fe04b12ffd7e81d8b3598a7a6f313fb3Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering errno = 0;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering pl = blkid_probe_get_partitions(b);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!pl) {
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (errno == 0)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return log_oom();
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek return log_error_errno(errno, "%s: failed to list partitions: %m", node);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering }
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering e = udev_enumerate_new(udev);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!e)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return log_oom();
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_parent(e, parent);
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek if (r < 0)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_add_match_subsystem(e, "block");
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek if (r < 0)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering r = udev_enumerate_scan_devices(e);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek return log_error_errno(r, "%s: failed to enumerate partitions: %m", node);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering first = udev_enumerate_get_list_entry(e);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering udev_list_entry_foreach(item, first) {
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *q;
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering unsigned long long flags;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering const char *stype, *subnode;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering sd_id128_t type_id;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering blkid_partition pp;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering dev_t qn;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering int nr;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek if (!q)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering qn = udev_device_get_devnum(q);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (major(qn) == 0)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (qn == devnum)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (qn == pn)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering subnode = udev_device_get_devnode(q);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!subnode)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering continue;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering pp = blkid_partlist_devno_to_partition(pl, qn);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!pp)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering continue;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering nr = blkid_partition_get_partno(pp);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (nr < 0)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering continue;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering stype = blkid_partition_get_type_string(pp);
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (!stype)
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering continue;
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (sd_id128_from_string(stype, &type_id) < 0)
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek continue;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering flags = blkid_partition_get_flags(pp);
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (sd_id128_equal(type_id, GPT_SWAP)) {
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers if (flags & GPT_FLAG_NO_AUTO)
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers continue;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering if (flags & GPT_FLAG_READ_ONLY) {
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode);
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering continue;
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering }
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering k = add_swap(subnode);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (k < 0)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = k;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers } else if (sd_id128_equal(type_id, GPT_ESP)) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers /* We only care for the first /boot partition */
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (boot && nr >= boot_nr)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers continue;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering /* Note that we do not honour the "no-auto"
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering * flag for the ESP, as it is often unset, to
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering * hide it from Windows. */
dd2c31bb04776ed8a9e9117028e987762f56c027Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers boot_nr = nr;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack r = free_and_strdup(&boot, subnode);
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack if (r < 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers return log_oom();
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering } else if (sd_id128_equal(type_id, GPT_HOME)) {
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers if (flags & GPT_FLAG_NO_AUTO)
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers continue;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering /* We only care for the first /home partition */
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (home && nr >= home_nr)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering continue;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering home_nr = nr;
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering home_rw = !(flags & GPT_FLAG_READ_ONLY),
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack r = free_and_strdup(&home, subnode);
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack if (r < 0)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering return log_oom();
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering } else if (sd_id128_equal(type_id, GPT_SRV)) {
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers if (flags & GPT_FLAG_NO_AUTO)
0238d4c660e732dd03ba0cdb54a29ec5870ee849Kay Sievers continue;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering /* We only care for the first /srv partition */
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (srv && nr >= srv_nr)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering continue;
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering srv_nr = nr;
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering srv_rw = !(flags & GPT_FLAG_READ_ONLY),
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack r = free_and_strdup(&srv, subnode);
2fc09a9cdd1ad25bc7c53a23d5301eb952e1ce3dDaniel Mack if (r < 0)
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering return log_oom();
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (boot) {
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers k = add_boot(boot);
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers if (k < 0)
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers r = k;
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers }
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (home) {
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering k = probe_and_add_mount("home", home, "/home", home_rw, "Home Partition", SPECIAL_LOCAL_FS_TARGET);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (k < 0)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = k;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering }
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering if (srv) {
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering k = probe_and_add_mount("srv", srv, "/srv", srv_rw, "Server Data Partition", SPECIAL_LOCAL_FS_TARGET);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (k < 0)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = k;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poetteringstatic int get_block_device(const char *path, dev_t *dev) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering struct stat st;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering struct statfs sfs;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(path);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering assert(dev);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering /* Get's the block device directly backing a file system. If
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering * the block device is encrypted, returns the device mapper
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering * block device. */
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (lstat(path, &st))
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering if (major(st.st_dev) != 0) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering *dev = st.st_dev;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 1;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering if (statfs(path, &sfs) < 0)
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return -errno;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
c51cf05646a11c65daf65c1123c77efb068f4f7bZbigniew Jędrzejewski-Szmek if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
f9ac15442e4132f00eca5495d53c17062aae13e0Lennart Poettering return btrfs_get_block_device(path, dev);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering return 0;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poetteringstatic int get_block_device_harder(const char *path, dev_t *dev) {
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering _cleanup_closedir_ DIR *d = NULL;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering _cleanup_free_ char *p = NULL, *t = NULL;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering struct dirent *de, *found = NULL;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering const char *q;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering unsigned maj, min;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering dev_t dt;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering int r;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering assert(path);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering assert(dev);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering /* Gets the backing block device for a file system, and
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering * handles LUKS encrypted file systems, looking for its
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering * immediate parent, if there is one. */
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering r = get_block_device(path, &dt);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (r <= 0)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return r;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return -ENOMEM;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering d = opendir(p);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (!d) {
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (errno == ENOENT)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering goto fallback;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return -errno;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering }
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering FOREACH_DIRENT_ALL(de, d, return -errno) {
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (STR_IN_SET(de->d_name, ".", ".."))
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering continue;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering continue;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (found) /* Don't try to support multiple backing block devices */
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering goto fallback;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering found = de;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering }
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (!found)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering goto fallback;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering q = strjoina(p, "/", found->d_name, "/dev");
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering r = read_one_line_file(q, &t);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (r == -ENOENT)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering goto fallback;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (r < 0)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return r;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (sscanf(t, "%u:%u", &maj, &min) != 2)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return -EINVAL;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering if (maj == 0)
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering goto fallback;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering *dev = makedev(maj, min);
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return 1;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poetteringfallback:
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering *dev = dt;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering return 1;
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering}
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic int parse_proc_cmdline_item(const char *key, const char *value) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering assert(key);
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (STR_IN_SET(key, "systemd.gpt_auto", "rd.systemd.gpt_auto") && value) {
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = parse_boolean(value);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (r < 0)
d2a623823f8d83c97c35fcd28f90e8cd59066f8aZbigniew Jędrzejewski-Szmek log_warning("Failed to parse gpt-auto switch \"%s\". Ignoring.", value);
8086ffacdb1bfec5ec115d24626538bda6cc372eZbigniew Jędrzejewski-Szmek else
8086ffacdb1bfec5ec115d24626538bda6cc372eZbigniew Jędrzejewski-Szmek arg_enabled = r;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering } else if (streq(key, "root") && value) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering /* Disable root disk logic if there's a root= value
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering * specified (unless it happens to be "gpt-auto") */
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering arg_root_enabled = streq(value, "gpt-auto");
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering } else if (streq(key, "rw") && !value)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering arg_root_rw = true;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering else if (streq(key, "ro") && !value)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering arg_root_rw = false;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return 0;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering}
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic int add_root_mount(void) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering#ifdef ENABLE_EFI
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int r;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (!is_efi_boot()) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_debug("Not a EFI boot, not creating root mount.");
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return 0;
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek }
9a5cb1371b6d8b0a04bd08665bcf9b06cb40c64cZbigniew Jędrzejewski-Szmek
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = efi_loader_get_device_part_uuid(NULL);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (r == -ENOENT) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_debug("EFI loader partition unknown, exiting.");
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return 0;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt } else if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_error_errno(r, "Failed to read ESP partition UUID: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering /* OK, we have an ESP partition, this is fantastic, so let's
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering * wait for a root device to show up. A udev rule will create
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering * the link for us under the right name. */
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return add_mount(
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering "root",
98b2f766b24c84fc49a4df954717b1f96bbce00dLennart Poettering "/dev/gpt-auto-root",
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering in_initrd() ? "/sysroot" : "/",
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering NULL,
cca1dfddd4ce4357113663532696488427cc54e4Lennart Poettering arg_root_rw,
59512f21d77d984cf1363fb0d1770218c5e17020Kay Sievers NULL,
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering "Root Partition",
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering#else
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return 0;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering#endif
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering}
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringstatic int add_mounts(void) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering dev_t devno;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int r;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering r = get_block_device_harder("/", &devno);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt if (r < 0)
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt return log_error_errno(r, "Failed to determine block device of root file system: %m");
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt else if (r == 0) {
c6ba0c184d297a454baf387663668db77f79c1b5Lennart Poettering r = get_block_device_harder("/usr", &devno);
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger if (r < 0)
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger return log_error_errno(r, "Failed to determine block device of /usr file system: %m");
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger else if (r == 0) {
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger log_debug("Neither root nor /usr file system are on a (single) block device.");
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger return 0;
eafe88e34a0698d2f4ebb747ab4911e35d0dfe4cTobias Hunger }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
61331eab0a53cd9b8446eab6d1ebf1a046d8efc1Lennart Poettering return enumerate_partitions(devno);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering}
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poetteringint main(int argc, char *argv[]) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int r = 0;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (argc > 1 && argc != 4) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_error("This program takes three or no arguments.");
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return EXIT_FAILURE;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering }
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (argc > 1)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering arg_dest = argv[3];
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_set_target(LOG_TARGET_SAFE);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_parse_environment();
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_open();
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering umask(0022);
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
75f86906c52735c98dc0aa7e24b773edb42ee814Lennart Poettering if (detect_container() > 0) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_debug("In a container, exiting.");
e48fdd84432bbf9c2ecc339183258c7c33116032Lennart Poettering return EXIT_SUCCESS;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering }
3db604b907323b8df0fc810216f6112056d26a02Lennart Poettering
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering r = parse_proc_cmdline(parse_proc_cmdline_item);
b5884878a2874447b2a9f07f324a7cd909d96d48Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (!arg_enabled) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering log_debug("Disabled, exiting.");
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return EXIT_SUCCESS;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering }
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (arg_root_enabled)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = add_root_mount();
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (!in_initrd()) {
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering int k;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering k = add_mounts();
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering if (k < 0)
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering r = k;
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering }
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering
73b80ec2d999c45ce13f3e034704249d80829f7eLennart Poettering return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1a14a53cfded6e78c6e8dfb73fdff0039971d642Lennart Poettering}