1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/ioctl.h>
26 #include <sys/statfs.h>
27 #include <blkid/blkid.h>
29 #ifdef HAVE_LINUX_BTRFS_H
30 #include <linux/btrfs.h>
35 #include "path-util.h"
39 #include "udev-util.h"
41 #include "unit-name.h"
43 #include "generator.h"
47 static const char *arg_dest = "/tmp";
49 DEFINE_TRIVIAL_CLEANUP_FUNC(blkid_probe, blkid_free_probe);
50 #define _cleanup_blkid_freep_probe_ _cleanup_(blkid_free_probep)
52 static int verify_gpt_partition(const char *node, sd_id128_t *type, unsigned *nr, char **fstype) {
53 _cleanup_blkid_freep_probe_ blkid_probe b = NULL;
58 b = blkid_new_probe_from_filename(node);
60 return errno != 0 ? -errno : -ENOMEM;
62 blkid_probe_enable_superblocks(b, 1);
63 blkid_probe_set_superblocks_flags(b, BLKID_SUBLKS_TYPE);
64 blkid_probe_enable_partitions(b, 1);
65 blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS);
68 r = blkid_do_safeprobe(b);
69 if (r == -2 || r == 1) /* no result or uncertain */
72 return errno ? -errno : -EIO;
75 r = blkid_probe_lookup_value(b, "PART_ENTRY_SCHEME", &v, NULL);
77 /* return 0 if we're not on GPT */
78 return errno ? -errno : 0;
80 if (strcmp(v, "gpt") != 0)
85 r = blkid_probe_lookup_value(b, "PART_ENTRY_TYPE", &v, NULL);
87 return errno ? -errno : -EIO;
89 r = sd_id128_from_string(v, type);
96 r = blkid_probe_lookup_value(b, "PART_ENTRY_NUMBER", &v, NULL);
98 return errno ? -errno : -EIO;
100 r = safe_atou(v, nr);
108 r = blkid_probe_lookup_value(b, "TYPE", &v, NULL);
125 static int add_swap(const char *path, const char *fstype) {
126 _cleanup_free_ char *name = NULL, *unit = NULL, *lnk = NULL;
127 _cleanup_fclose_ FILE *f = NULL;
129 log_debug("Adding swap: %s %s", path, fstype);
131 name = unit_name_from_path(path, ".swap");
135 unit = strjoin(arg_dest, "/", name, NULL);
139 f = fopen(unit, "wxe");
141 log_error("Failed to create unit file %s: %m", unit);
146 "# Automatically generated by systemd-gpt-auto-generator\n\n"
148 "Description=Swap Partition\n\n"
155 log_error("Failed to write unit file %s: %m", unit);
159 lnk = strjoin(arg_dest, "/" SPECIAL_SWAP_TARGET ".wants/", name, NULL);
163 mkdir_parents_label(lnk, 0755);
164 if (symlink(unit, lnk) < 0) {
165 log_error("Failed to create symlink %s: %m", lnk);
172 static int add_cryptsetup(const char *id, const char *what, char **device) {
173 _cleanup_free_ char *e = NULL, *n = NULL, *p = NULL, *d = NULL, *to = NULL;
174 _cleanup_fclose_ FILE *f = NULL;
182 d = unit_name_from_path(what, ".device");
186 e = unit_name_escape(id);
190 n = unit_name_build("systemd-cryptsetup", e, ".service");
194 p = strjoin(arg_dest, "/", n, NULL);
200 log_error("Failed to create unit file %s: %m", p);
205 "# Automatically generated by systemd-gpt-auto-generator\n\n"
207 "Description=Cryptography Setup for %%I\n"
208 "Documentation=man:systemd-cryptsetup@.service(8)\n"
209 "DefaultDependencies=no\n"
210 "Conflicts=umount.target\n"
211 "BindsTo=dev-mapper-%%i.device %s\n"
212 "Before=umount.target cryptsetup.target\n"
214 "IgnoreOnIsolate=true\n"
215 "After=systemd-readahead-collect.service systemd-readahead-replay.service\n\n"
218 "RemainAfterExit=yes\n"
219 "TimeoutSec=0\n" /* the binary handles timeouts anyway */
220 "ExecStart=" SYSTEMD_CRYPTSETUP_PATH " attach '%s' '%s'\n"
221 "ExecStop=" SYSTEMD_CRYPTSETUP_PATH " detach '%s'\n",
228 log_error("Failed to write file %s: %m", p);
232 from = strappenda("../", n);
234 to = strjoin(arg_dest, "/", d, ".wants/", n, NULL);
238 mkdir_parents_label(to, 0755);
239 if (symlink(from, to) < 0) {
240 log_error("Failed to create symlink %s: %m", to);
245 to = strjoin(arg_dest, "/cryptsetup.target.requires/", n, NULL);
249 mkdir_parents_label(to, 0755);
250 if (symlink(from, to) < 0) {
251 log_error("Failed to create symlink %s: %m", to);
256 to = strjoin(arg_dest, "/dev-mapper-", e, ".device.requires/", n, NULL);
260 mkdir_parents_label(to, 0755);
261 if (symlink(from, to) < 0) {
262 log_error("Failed to create symlink %s: %m", to);
267 p = strjoin(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf", NULL);
271 mkdir_parents_label(p, 0755);
272 r = write_string_file(p,
273 "# Automatically generated by systemd-gpt-auto-generator\n\n"
275 "JobTimeoutSec=0\n"); /* the binary handles timeouts anyway */
277 log_error("Failed to write device drop-in: %s", strerror(-r));
281 ret = strappend("/dev/mapper/", id);
289 static int add_mount(const char *id, const char *what, const char *where, const char *fstype, const char *description) {
290 _cleanup_free_ char *unit = NULL, *lnk = NULL, *crypto_what = NULL, *p = NULL;
291 _cleanup_fclose_ FILE *f = NULL;
300 if (dir_is_empty(where) <= 0) {
301 log_debug("%s already populated, ignoring.", where);
305 log_debug("Adding %s: %s %s", where, what, fstype);
307 if (streq(fstype, "crypto_LUKS")) {
309 r = add_cryptsetup(id, what, &crypto_what);
317 unit = unit_name_from_path(where, ".mount");
321 p = strjoin(arg_dest, "/", unit, NULL);
327 log_error("Failed to create unit file %s: %m", unit);
332 "# Automatically generated by systemd-gpt-auto-generator\n\n"
337 r = generator_write_fsck_deps(f, arg_dest, what, where, fstype);
356 log_error("Failed to write unit file %s: %m", unit);
360 lnk = strjoin(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".requires/", unit, NULL);
364 mkdir_parents_label(lnk, 0755);
365 if (symlink(unit, lnk) < 0) {
366 log_error("Failed to create symlink %s: %m", lnk);
373 static int enumerate_partitions(struct udev *udev, dev_t dev) {
374 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
375 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
376 _cleanup_free_ char *home = NULL, *home_fstype = NULL, *srv = NULL, *srv_fstype = NULL;
377 unsigned home_nr = (unsigned) -1, srv_nr = (unsigned )-1;
378 struct udev_list_entry *first, *item;
379 struct udev_device *parent = NULL;
382 e = udev_enumerate_new(udev);
386 d = udev_device_new_from_devnum(udev, 'b', dev);
390 parent = udev_device_get_parent(d);
394 r = udev_enumerate_add_match_parent(e, parent);
398 r = udev_enumerate_add_match_subsystem(e, "block");
402 r = udev_enumerate_scan_devices(e);
404 log_error("Failed to enumerate partitions on /dev/block/%u:%u: %s", major(dev), minor(dev), strerror(-r));
408 first = udev_enumerate_get_list_entry(e);
409 udev_list_entry_foreach(item, first) {
410 _cleanup_udev_device_unref_ struct udev_device *q;
411 _cleanup_free_ char *fstype = NULL;
412 const char *node = NULL;
416 q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
420 if (udev_device_get_devnum(q) == udev_device_get_devnum(d))
423 if (udev_device_get_devnum(q) == udev_device_get_devnum(parent))
426 node = udev_device_get_devnode(q);
430 r = verify_gpt_partition(node, &type_id, &nr, &fstype);
432 /* skip child devices which are not detected properly */
435 log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
441 if (sd_id128_equal(type_id, GPT_SWAP))
442 add_swap(node, fstype);
444 else if (sd_id128_equal(type_id, GPT_HOME)) {
446 /* We only care for the first /home partition */
447 if (home && nr >= home_nr)
458 home_fstype = fstype;
461 } else if (sd_id128_equal(type_id, GPT_SRV)) {
463 /* We only care for the first /srv partition */
464 if (srv && nr >= srv_nr)
480 if (home && home_fstype)
481 add_mount("home", home, "/home", home_fstype, "Home Partition");
483 if (srv && srv_fstype)
484 add_mount("srv", srv, "/srv", srv_fstype, "Server Data Partition");
489 static int get_btrfs_block_device(const char *path, dev_t *dev) {
490 struct btrfs_ioctl_fs_info_args fsi = {};
491 _cleanup_close_ int fd = -1;
497 fd = open(path, O_DIRECTORY|O_CLOEXEC);
501 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
504 /* We won't do this for btrfs RAID */
505 if (fsi.num_devices != 1)
508 for (id = 1; id <= fsi.max_id; id++) {
509 struct btrfs_ioctl_dev_info_args di = {
514 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
521 if (stat((char*) di.path, &st) < 0)
524 if (!S_ISBLK(st.st_mode))
527 if (major(st.st_rdev) == 0)
537 static int get_block_device(const char *path, dev_t *dev) {
544 if (lstat(path, &st))
547 if (major(st.st_dev) != 0) {
552 if (statfs(path, &sfs) < 0)
555 if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
556 return get_btrfs_block_device(path, dev);
561 static int devno_to_devnode(struct udev *udev, dev_t devno, char **ret) {
562 _cleanup_udev_device_unref_ struct udev_device *d;
566 d = udev_device_new_from_devnum(udev, 'b', devno);
570 t = udev_device_get_devnode(d);
582 int main(int argc, char *argv[]) {
583 _cleanup_udev_unref_ struct udev *udev = NULL;
584 _cleanup_free_ char *node = NULL;
588 if (argc > 1 && argc != 4) {
589 log_error("This program takes three or no arguments.");
596 log_set_target(LOG_TARGET_SAFE);
597 log_parse_environment();
603 log_debug("In initrd, exiting.");
607 if (detect_container(NULL) > 0) {
608 log_debug("In a container, exiting.");
612 r = get_block_device("/", &devno);
614 log_error("Failed to determine block device of root file system: %s", strerror(-r));
617 log_debug("Root file system not on a (single) block device.");
627 r = devno_to_devnode(udev, devno, &node);
629 log_error("Failed to determine block device node from major/minor: %s", strerror(-r));
633 log_debug("Root device %s.", node);
635 r = verify_gpt_partition(node, NULL, NULL, NULL);
637 log_error("Failed to verify GPT partition %s: %s", node, strerror(-r));
641 log_debug("Not a GPT disk, exiting.");
645 r = enumerate_partitions(udev, devno);