summaryrefslogtreecommitdiff
path: root/src/grp-initutils
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-08-17 01:33:02 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-08-17 01:33:02 -0400
commit610d801297fe7e46c319e6da4e6571aaded630dd (patch)
treed27f6d077694b84ed9881c99b2894701932ca6e1 /src/grp-initutils
parent7648bff2717c24e9f5c90ec9e4588eda510aba9d (diff)
more
Diffstat (limited to 'src/grp-initutils')
-rw-r--r--src/grp-initutils/Makefile43
-rw-r--r--src/grp-initutils/systemd-backlight/Makefile43
-rw-r--r--src/grp-initutils/systemd-backlight/backlight.c434
-rw-r--r--src/grp-initutils/systemd-binfmt/Makefile56
-rw-r--r--src/grp-initutils/systemd-binfmt/binfmt.c203
-rw-r--r--src/grp-initutils/systemd-detect-virt/Makefile36
-rw-r--r--src/grp-initutils/systemd-detect-virt/detect-virt.c169
-rw-r--r--src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.bash40
-rw-r--r--src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.zsh11
-rw-r--r--src/grp-initutils/systemd-firstboot/Makefile47
-rw-r--r--src/grp-initutils/systemd-firstboot/firstboot.c870
-rw-r--r--src/grp-initutils/systemd-fsck/Makefile33
-rw-r--r--src/grp-initutils/systemd-fsck/fsck.c487
-rw-r--r--src/grp-initutils/systemd-quotacheck/Makefile48
-rw-r--r--src/grp-initutils/systemd-quotacheck/quotacheck.c124
-rw-r--r--src/grp-initutils/systemd-random-seed/Makefile50
-rw-r--r--src/grp-initutils/systemd-random-seed/random-seed.c176
-rw-r--r--src/grp-initutils/systemd-rfkill/Makefile46
-rw-r--r--src/grp-initutils/systemd-rfkill/rfkill.c427
-rw-r--r--src/grp-initutils/systemd-sleep/Makefile35
-rw-r--r--src/grp-initutils/systemd-sleep/sleep.c215
-rw-r--r--src/grp-initutils/systemd-sysctl/50-default.sysctl40
-rw-r--r--src/grp-initutils/systemd-sysctl/Makefile33
-rw-r--r--src/grp-initutils/systemd-sysctl/sysctl.c287
-rw-r--r--src/grp-initutils/systemd-sysusers/Makefile61
-rw-r--r--src/grp-initutils/systemd-sysusers/basic.sysusers.in36
-rw-r--r--src/grp-initutils/systemd-sysusers/sysusers.c1919
-rw-r--r--src/grp-initutils/systemd-tmpfiles/Makefile84
-rw-r--r--src/grp-initutils/systemd-tmpfiles/systemd-tmpfiles.completion.zsh13
-rw-r--r--src/grp-initutils/systemd-tmpfiles/tmpfiles.c2344
-rw-r--r--src/grp-initutils/systemd-update-done/Makefile34
-rw-r--r--src/grp-initutils/systemd-update-done/update-done.c115
-rw-r--r--src/grp-initutils/systemd-update-utmp/Makefile42
-rw-r--r--src/grp-initutils/systemd-update-utmp/update-utmp.c283
-rw-r--r--src/grp-initutils/systemd-user-sessions/Makefile48
-rw-r--r--src/grp-initutils/systemd-user-sessions/user-sessions.c84
-rw-r--r--src/grp-initutils/systemd-vconsole-setup/.gitignore1
-rw-r--r--src/grp-initutils/systemd-vconsole-setup/90-vconsole.rules.in10
-rw-r--r--src/grp-initutils/systemd-vconsole-setup/Makefile50
-rw-r--r--src/grp-initutils/systemd-vconsole-setup/vconsole-setup.c333
40 files changed, 0 insertions, 9410 deletions
diff --git a/src/grp-initutils/Makefile b/src/grp-initutils/Makefile
deleted file mode 100644
index 0bc22bb42c..0000000000
--- a/src/grp-initutils/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-nested.subdirs += systemd-backlight
-nested.subdirs += systemd-binfmt
-nested.subdirs += systemd-detect-virt
-nested.subdirs += systemd-firstboot
-nested.subdirs += systemd-fsck
-nested.subdirs += systemd-quotacheck
-nested.subdirs += systemd-random-seed
-nested.subdirs += systemd-rfkill
-nested.subdirs += systemd-sleep
-nested.subdirs += systemd-sysctl
-nested.subdirs += systemd-sysusers
-nested.subdirs += systemd-tmpfiles
-nested.subdirs += systemd-update-done
-nested.subdirs += systemd-update-utmp
-nested.subdirs += systemd-user-sessions
-nested.subdirs += systemd-vconsole-setup
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-backlight/Makefile b/src/grp-initutils/systemd-backlight/Makefile
deleted file mode 100644
index cf55ac4db9..0000000000
--- a/src/grp-initutils/systemd-backlight/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_BACKLIGHT),)
-rootlibexec_PROGRAMS += \
- systemd-backlight
-
-nodist_systemunit_DATA += \
- units/systemd-backlight@.service
-
-systemd_backlight_SOURCES = \
- src/backlight/backlight.c
-
-systemd_backlight_LDADD = \
- libshared.la
-endif # ENABLE_BACKLIGHT
-
-EXTRA_DIST += \
- units/systemd-backlight@.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-backlight/backlight.c b/src/grp-initutils/systemd-backlight/backlight.c
deleted file mode 100644
index aa8d852024..0000000000
--- a/src/grp-initutils/systemd-backlight/backlight.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <libudev.h>
-
-#include "basic/alloc-util.h"
-#include "basic/def.h"
-#include "basic/escape.h"
-#include "basic/fileio.h"
-#include "basic/mkdir.h"
-#include "basic/parse-util.h"
-#include "basic/proc-cmdline.h"
-#include "basic/string-util.h"
-#include "basic/util.h"
-#include "shared/udev-util.h"
-
-static struct udev_device *find_pci_or_platform_parent(struct udev_device *device) {
- struct udev_device *parent;
- const char *subsystem, *sysname;
-
- assert(device);
-
- parent = udev_device_get_parent(device);
- if (!parent)
- return NULL;
-
- subsystem = udev_device_get_subsystem(parent);
- if (!subsystem)
- return NULL;
-
- sysname = udev_device_get_sysname(parent);
- if (!sysname)
- return NULL;
-
- if (streq(subsystem, "drm")) {
- const char *c;
-
- c = startswith(sysname, "card");
- if (!c)
- return NULL;
-
- c += strspn(c, DIGITS);
- if (*c == '-') {
- /* A connector DRM device, let's ignore all but LVDS and eDP! */
-
- if (!startswith(c, "-LVDS-") &&
- !startswith(c, "-Embedded DisplayPort-"))
- return NULL;
- }
-
- } else if (streq(subsystem, "pci")) {
- const char *value;
-
- value = udev_device_get_sysattr_value(parent, "class");
- if (value) {
- unsigned long class = 0;
-
- if (safe_atolu(value, &class) < 0) {
- log_warning("Cannot parse PCI class %s of device %s:%s.",
- value, subsystem, sysname);
- return NULL;
- }
-
- /* Graphics card */
- if (class == 0x30000)
- return parent;
- }
-
- } else if (streq(subsystem, "platform"))
- return parent;
-
- return find_pci_or_platform_parent(parent);
-}
-
-static bool same_device(struct udev_device *a, struct udev_device *b) {
- assert(a);
- assert(b);
-
- if (!streq_ptr(udev_device_get_subsystem(a), udev_device_get_subsystem(b)))
- return false;
-
- if (!streq_ptr(udev_device_get_sysname(a), udev_device_get_sysname(b)))
- return false;
-
- return true;
-}
-
-static bool validate_device(struct udev *udev, struct udev_device *device) {
- _cleanup_udev_enumerate_unref_ struct udev_enumerate *enumerate = NULL;
- struct udev_list_entry *item = NULL, *first = NULL;
- struct udev_device *parent;
- const char *v, *subsystem;
- int r;
-
- assert(udev);
- assert(device);
-
- /* Verify whether we should actually care for a specific
- * backlight device. For backlight devices there might be
- * multiple ways to access the same control: "firmware"
- * (i.e. ACPI), "platform" (i.e. via the machine's EC) and
- * "raw" (via the graphics card). In general we should prefer
- * "firmware" (i.e. ACPI) or "platform" access over "raw"
- * access, in order not to confuse the BIOS/EC, and
- * compatibility with possible low-level hotkey handling of
- * screen brightness. The kernel will already make sure to
- * expose only one of "firmware" and "platform" for the same
- * device to userspace. However, we still need to make sure
- * that we use "raw" only if no "firmware" or "platform"
- * device for the same device exists. */
-
- subsystem = udev_device_get_subsystem(device);
- if (!streq_ptr(subsystem, "backlight"))
- return true;
-
- v = udev_device_get_sysattr_value(device, "type");
- if (!streq_ptr(v, "raw"))
- return true;
-
- parent = find_pci_or_platform_parent(device);
- if (!parent)
- return true;
-
- subsystem = udev_device_get_subsystem(parent);
- if (!subsystem)
- return true;
-
- enumerate = udev_enumerate_new(udev);
- if (!enumerate)
- return true;
-
- r = udev_enumerate_add_match_subsystem(enumerate, "backlight");
- if (r < 0)
- return true;
-
- r = udev_enumerate_scan_devices(enumerate);
- if (r < 0)
- return true;
-
- first = udev_enumerate_get_list_entry(enumerate);
- udev_list_entry_foreach(item, first) {
- _cleanup_udev_device_unref_ struct udev_device *other;
- struct udev_device *other_parent;
- const char *other_subsystem;
-
- other = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
- if (!other)
- return true;
-
- if (same_device(device, other))
- continue;
-
- v = udev_device_get_sysattr_value(other, "type");
- if (!streq_ptr(v, "platform") && !streq_ptr(v, "firmware"))
- continue;
-
- /* OK, so there's another backlight device, and it's a
- * platform or firmware device, so, let's see if we
- * can verify it belongs to the same device as
- * ours. */
- other_parent = find_pci_or_platform_parent(other);
- if (!other_parent)
- continue;
-
- if (same_device(parent, other_parent)) {
- /* Both have the same PCI parent, that means
- * we are out. */
- log_debug("Skipping backlight device %s, since device %s is on same PCI device and takes precedence.",
- udev_device_get_sysname(device),
- udev_device_get_sysname(other));
- return false;
- }
-
- other_subsystem = udev_device_get_subsystem(other_parent);
- if (streq_ptr(other_subsystem, "platform") && streq_ptr(subsystem, "pci")) {
- /* The other is connected to the platform bus
- * and we are a PCI device, that also means we
- * are out. */
- log_debug("Skipping backlight device %s, since device %s is a platform device and takes precedence.",
- udev_device_get_sysname(device),
- udev_device_get_sysname(other));
- return false;
- }
- }
-
- return true;
-}
-
-static unsigned get_max_brightness(struct udev_device *device) {
- int r;
- const char *max_brightness_str;
- unsigned max_brightness;
-
- max_brightness_str = udev_device_get_sysattr_value(device, "max_brightness");
- if (!max_brightness_str) {
- log_warning("Failed to read 'max_brightness' attribute.");
- return 0;
- }
-
- r = safe_atou(max_brightness_str, &max_brightness);
- if (r < 0) {
- log_warning_errno(r, "Failed to parse 'max_brightness' \"%s\": %m", max_brightness_str);
- return 0;
- }
-
- if (max_brightness <= 0) {
- log_warning("Maximum brightness is 0, ignoring device.");
- return 0;
- }
-
- return max_brightness;
-}
-
-/* Some systems turn the backlight all the way off at the lowest levels.
- * clamp_brightness clamps the saved brightness to at least 1 or 5% of
- * max_brightness in case of 'backlight' subsystem. This avoids preserving
- * an unreadably dim screen, which would otherwise force the user to
- * disable state restoration. */
-static void clamp_brightness(struct udev_device *device, char **value, unsigned max_brightness) {
- int r;
- unsigned brightness, new_brightness, min_brightness;
- const char *subsystem;
-
- r = safe_atou(*value, &brightness);
- if (r < 0) {
- log_warning_errno(r, "Failed to parse brightness \"%s\": %m", *value);
- return;
- }
-
- subsystem = udev_device_get_subsystem(device);
- if (streq_ptr(subsystem, "backlight"))
- min_brightness = MAX(1U, max_brightness/20);
- else
- min_brightness = 0;
-
- new_brightness = CLAMP(brightness, min_brightness, max_brightness);
- if (new_brightness != brightness) {
- char *old_value = *value;
-
- r = asprintf(value, "%u", new_brightness);
- if (r < 0) {
- log_oom();
- return;
- }
-
- log_info("Saved brightness %s %s to %s.", old_value,
- new_brightness > brightness ?
- "too low; increasing" : "too high; decreasing",
- *value);
-
- free(old_value);
- }
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
- _cleanup_free_ char *saved = NULL, *ss = NULL, *escaped_ss = NULL, *escaped_sysname = NULL, *escaped_path_id = NULL;
- const char *sysname, *path_id;
- unsigned max_brightness;
- int r;
-
- if (argc != 3) {
- log_error("This program requires two arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = mkdir_p("/var/lib/systemd/backlight", 0755);
- if (r < 0) {
- log_error_errno(r, "Failed to create backlight directory /var/lib/systemd/backlight: %m");
- return EXIT_FAILURE;
- }
-
- udev = udev_new();
- if (!udev) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- sysname = strchr(argv[2], ':');
- if (!sysname) {
- log_error("Requires a subsystem and sysname pair specifying a backlight device.");
- return EXIT_FAILURE;
- }
-
- ss = strndup(argv[2], sysname - argv[2]);
- if (!ss) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- sysname++;
-
- if (!streq(ss, "backlight") && !streq(ss, "leds")) {
- log_error("Not a backlight or LED device: '%s:%s'", ss, sysname);
- return EXIT_FAILURE;
- }
-
- errno = 0;
- device = udev_device_new_from_subsystem_sysname(udev, ss, sysname);
- if (!device) {
- if (errno > 0)
- log_error_errno(errno, "Failed to get backlight or LED device '%s:%s': %m", ss, sysname);
- else
- log_oom();
-
- return EXIT_FAILURE;
- }
-
- /* If max_brightness is 0, then there is no actual backlight
- * device. This happens on desktops with Asus mainboards
- * that load the eeepc-wmi module.
- */
- max_brightness = get_max_brightness(device);
- if (max_brightness == 0)
- return EXIT_SUCCESS;
-
- escaped_ss = cescape(ss);
- if (!escaped_ss) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- escaped_sysname = cescape(sysname);
- if (!escaped_sysname) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- path_id = udev_device_get_property_value(device, "ID_PATH");
- if (path_id) {
- escaped_path_id = cescape(path_id);
- if (!escaped_path_id) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- saved = strjoin("/var/lib/systemd/backlight/", escaped_path_id, ":", escaped_ss, ":", escaped_sysname, NULL);
- } else
- saved = strjoin("/var/lib/systemd/backlight/", escaped_ss, ":", escaped_sysname, NULL);
-
- if (!saved) {
- log_oom();
- return EXIT_FAILURE;
- }
-
- /* If there are multiple conflicting backlight devices, then
- * their probing at boot-time might happen in any order. This
- * means the validity checking of the device then is not
- * reliable, since it might not see other devices conflicting
- * with a specific backlight. To deal with this, we will
- * actively delete backlight state files at shutdown (where
- * device probing should be complete), so that the validity
- * check at boot time doesn't have to be reliable. */
-
- if (streq(argv[1], "load")) {
- _cleanup_free_ char *value = NULL;
- const char *clamp;
-
- if (shall_restore_state() == 0)
- return EXIT_SUCCESS;
-
- if (!validate_device(udev, device))
- return EXIT_SUCCESS;
-
- r = read_one_line_file(saved, &value);
- if (r < 0) {
-
- if (r == -ENOENT)
- return EXIT_SUCCESS;
-
- log_error_errno(r, "Failed to read %s: %m", saved);
- return EXIT_FAILURE;
- }
-
- clamp = udev_device_get_property_value(device, "ID_BACKLIGHT_CLAMP");
- if (!clamp || parse_boolean(clamp) != 0) /* default to clamping */
- clamp_brightness(device, &value, max_brightness);
-
- r = udev_device_set_sysattr_value(device, "brightness", value);
- if (r < 0) {
- log_error_errno(r, "Failed to write system 'brightness' attribute: %m");
- return EXIT_FAILURE;
- }
-
- } else if (streq(argv[1], "save")) {
- const char *value;
-
- if (!validate_device(udev, device)) {
- unlink(saved);
- return EXIT_SUCCESS;
- }
-
- value = udev_device_get_sysattr_value(device, "brightness");
- if (!value) {
- log_error("Failed to read system 'brightness' attribute");
- return EXIT_FAILURE;
- }
-
- r = write_string_file(saved, value, WRITE_STRING_FILE_CREATE);
- if (r < 0) {
- log_error_errno(r, "Failed to write %s: %m", saved);
- return EXIT_FAILURE;
- }
-
- } else {
- log_error("Unknown verb %s.", argv[1]);
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-binfmt/Makefile b/src/grp-initutils/systemd-binfmt/Makefile
deleted file mode 100644
index 3e5c1ac270..0000000000
--- a/src/grp-initutils/systemd-binfmt/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_BINFMT),)
-systemd_binfmt_SOURCES = \
- src/binfmt/binfmt.c
-
-systemd_binfmt_LDADD = \
- libshared.la
-
-rootlibexec_PROGRAMS += \
- systemd-binfmt
-
-dist_systemunit_DATA += \
- units/proc-sys-fs-binfmt_misc.automount \
- units/proc-sys-fs-binfmt_misc.mount
-
-nodist_systemunit_DATA += \
- units/systemd-binfmt.service
-
-INSTALL_DIRS += \
- $(prefix)/lib/binfmt.d \
- $(sysconfdir)/binfmt.d
-
-SYSINIT_TARGET_WANTS += \
- systemd-binfmt.service \
- proc-sys-fs-binfmt_misc.automount
-
-endif # ENABLE_BINFMT
-
-EXTRA_DIST += \
- units/systemd-binfmt.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-binfmt/binfmt.c b/src/grp-initutils/systemd-binfmt/binfmt.c
deleted file mode 100644
index 39bbdb5335..0000000000
--- a/src/grp-initutils/systemd-binfmt/binfmt.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "basic/alloc-util.h"
-#include "basic/conf-files.h"
-#include "basic/def.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/log.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/util.h"
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("binfmt.d");
-
-static int delete_rule(const char *rule) {
- _cleanup_free_ char *x = NULL, *fn = NULL;
- char *e;
-
- assert(rule[0]);
-
- x = strdup(rule);
- if (!x)
- return log_oom();
-
- e = strchrnul(x+1, x[0]);
- *e = 0;
-
- fn = strappend("/proc/sys/fs/binfmt_misc/", x+1);
- if (!fn)
- return log_oom();
-
- return write_string_file(fn, "-1", 0);
-}
-
-static int apply_rule(const char *rule) {
- int r;
-
- delete_rule(rule);
-
- r = write_string_file("/proc/sys/fs/binfmt_misc/register", rule, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to add binary format: %m");
-
- return 0;
-}
-
-static int apply_file(const char *path, bool ignore_enoent) {
- _cleanup_fclose_ FILE *f = NULL;
- int r;
-
- assert(path);
-
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
- if (r < 0) {
- if (ignore_enoent && r == -ENOENT)
- return 0;
-
- return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
- }
-
- log_debug("apply: %s", path);
- for (;;) {
- char l[LINE_MAX], *p;
- int k;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
- }
-
- p = strstrip(l);
- if (!*p)
- continue;
- if (strchr(COMMENTS "\n", *p))
- continue;
-
- k = apply_rule(p);
- if (k < 0 && r == 0)
- r = k;
- }
-
- return r;
-}
-
-static void help(void) {
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Registers binary formats.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- {}
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r, k;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = 0;
-
- if (argc > optind) {
- int i;
-
- for (i = optind; i < argc; i++) {
- k = apply_file(argv[i], false);
- if (k < 0 && r == 0)
- r = k;
- }
- } else {
- _cleanup_strv_free_ char **files = NULL;
- char **f;
-
- r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
- goto finish;
- }
-
- /* Flush out all rules */
- write_string_file("/proc/sys/fs/binfmt_misc/status", "-1", 0);
-
- STRV_FOREACH(f, files) {
- k = apply_file(*f, true);
- if (k < 0 && r == 0)
- r = k;
- }
- }
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-detect-virt/Makefile b/src/grp-initutils/systemd-detect-virt/Makefile
deleted file mode 100644
index 7b9b9f667b..0000000000
--- a/src/grp-initutils/systemd-detect-virt/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-bin_PROGRAMS += systemd-detect-virt
-systemd_detect_virt_SOURCES = \
- src/detect-virt/detect-virt.c
-
-systemd_detect_virt_LDADD = \
- libshared.la
-
-INSTALL_EXEC_HOOKS += \
- systemd-detect-virt-install-hook
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-detect-virt/detect-virt.c b/src/grp-initutils/systemd-detect-virt/detect-virt.c
deleted file mode 100644
index 06cdab5297..0000000000
--- a/src/grp-initutils/systemd-detect-virt/detect-virt.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include "basic/util.h"
-#include "basic/virt.h"
-
-static bool arg_quiet = false;
-static enum {
- ANY_VIRTUALIZATION,
- ONLY_VM,
- ONLY_CONTAINER,
- ONLY_CHROOT,
-} arg_mode = ANY_VIRTUALIZATION;
-
-static void help(void) {
- printf("%s [OPTIONS...]\n\n"
- "Detect execution in a virtualized environment.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -c --container Only detect whether we are run in a container\n"
- " -v --vm Only detect whether we are run in a VM\n"
- " -r --chroot Detect whether we are run in a chroot() environment\n"
- " -q --quiet Don't output anything, just set return value\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "container", no_argument, NULL, 'c' },
- { "vm", no_argument, NULL, 'v' },
- { "chroot", no_argument, NULL, 'r' },
- { "quiet", no_argument, NULL, 'q' },
- {}
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "hqcvr", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case 'q':
- arg_quiet = true;
- break;
-
- case 'c':
- arg_mode = ONLY_CONTAINER;
- break;
-
- case 'v':
- arg_mode = ONLY_VM;
- break;
-
- case 'r':
- arg_mode = ONLY_CHROOT;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (optind < argc) {
- log_error("%s takes no arguments.", program_invocation_short_name);
- return -EINVAL;
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- /* This is mostly intended to be used for scripts which want
- * to detect whether we are being run in a virtualized
- * environment or not */
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- switch (arg_mode) {
-
- case ONLY_VM:
- r = detect_vm();
- if (r < 0) {
- log_error_errno(r, "Failed to check for VM: %m");
- return EXIT_FAILURE;
- }
-
- break;
-
- case ONLY_CONTAINER:
- r = detect_container();
- if (r < 0) {
- log_error_errno(r, "Failed to check for container: %m");
- return EXIT_FAILURE;
- }
-
- break;
-
- case ONLY_CHROOT:
- r = running_in_chroot();
- if (r < 0) {
- log_error_errno(r, "Failed to check for chroot() environment: %m");
- return EXIT_FAILURE;
- }
-
- return r ? EXIT_SUCCESS : EXIT_FAILURE;
-
- case ANY_VIRTUALIZATION:
- default:
- r = detect_virtualization();
- if (r < 0) {
- log_error_errno(r, "Failed to check for virtualization: %m");
- return EXIT_FAILURE;
- }
-
- break;
- }
-
- if (!arg_quiet)
- puts(virtualization_to_string(r));
-
- return r != VIRTUALIZATION_NONE ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.bash b/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.bash
deleted file mode 100644
index df06c29841..0000000000
--- a/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.bash
+++ /dev/null
@@ -1,40 +0,0 @@
-# systemd-detect-virt(1) completion -*- shell-script -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2014 Thomas H.P. Andersen
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-
-__contains_word() {
- local w word=$1; shift
- for w in "$@"; do
- [[ $w = "$word" ]] && return
- done
-}
-
-_systemd_detect_virt() {
- local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
- local i verb comps
-
- local -A OPTS=(
- [STANDALONE]='-h --help --version -c --container -v --vm -q --quiet'
- )
-
- _init_completion || return
-
- COMPREPLY=( $(compgen -W '${OPTS[*]}' -- "$cur") )
-}
-
-complete -F _systemd_detect_virt systemd-detect-virt
diff --git a/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.zsh b/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.zsh
deleted file mode 100644
index a0c7df727c..0000000000
--- a/src/grp-initutils/systemd-detect-virt/systemd-detect-virt.completion.zsh
+++ /dev/null
@@ -1,11 +0,0 @@
-#compdef systemd-detect-virt
-
-local curcontext="$curcontext" state lstate line
-_arguments \
- {-h,--help}'[Show this help]' \
- '--version[Show package version]' \
- {-c,--container}'[Only detect whether we are run in a container]' \
- {-v,--vm}'[Only detect whether we are run in a VM]' \
- {-q,--quiet}"[Don't output anything, just set return value]"
-
-#vim: set ft=zsh sw=4 ts=4 et
diff --git a/src/grp-initutils/systemd-firstboot/Makefile b/src/grp-initutils/systemd-firstboot/Makefile
deleted file mode 100644
index b94b344bb9..0000000000
--- a/src/grp-initutils/systemd-firstboot/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_FIRSTBOOT),)
-systemd_firstboot_SOURCES = \
- src/firstboot/firstboot.c
-
-systemd_firstboot_LDADD = \
- libshared.la \
- -lcrypt
-
-rootbin_PROGRAMS += \
- systemd-firstboot
-
-nodist_systemunit_DATA += \
- units/systemd-firstboot.service
-
-SYSINIT_TARGET_WANTS += \
- systemd-firstboot.service
-endif # ENABLE_FIRSTBOOT
-
-EXTRA_DIST += \
- units/systemd-firstboot.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-firstboot/firstboot.c b/src/grp-initutils/systemd-firstboot/firstboot.c
deleted file mode 100644
index d2059a943f..0000000000
--- a/src/grp-initutils/systemd-firstboot/firstboot.c
+++ /dev/null
@@ -1,870 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <fcntl.h>
-#include <getopt.h>
-#include <shadow.h>
-#include <unistd.h>
-
-#include "basic/alloc-util.h"
-#include "basic/copy.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/fs-util.h"
-#include "basic/hostname-util.h"
-#include "basic/locale-util.h"
-#include "basic/mkdir.h"
-#include "basic/parse-util.h"
-#include "basic/path-util.h"
-#include "basic/random-util.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/terminal-util.h"
-#include "basic/time-util.h"
-#include "basic/umask-util.h"
-#include "basic/user-util.h"
-#include "shared/ask-password-api.h"
-
-static char *arg_root = NULL;
-static char *arg_locale = NULL; /* $LANG */
-static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
-static char *arg_timezone = NULL;
-static char *arg_hostname = NULL;
-static sd_id128_t arg_machine_id = {};
-static char *arg_root_password = NULL;
-static bool arg_prompt_locale = false;
-static bool arg_prompt_timezone = false;
-static bool arg_prompt_hostname = false;
-static bool arg_prompt_root_password = false;
-static bool arg_copy_locale = false;
-static bool arg_copy_timezone = false;
-static bool arg_copy_root_password = false;
-
-static bool press_any_key(void) {
- char k = 0;
- bool need_nl = true;
-
- printf("-- Press any key to proceed --");
- fflush(stdout);
-
- (void) read_one_char(stdin, &k, USEC_INFINITY, &need_nl);
-
- if (need_nl)
- putchar('\n');
-
- return k != 'q';
-}
-
-static void print_welcome(void) {
- _cleanup_free_ char *pretty_name = NULL;
- const char *os_release = NULL;
- static bool done = false;
- int r;
-
- if (done)
- return;
-
- os_release = prefix_roota(arg_root, "/etc/os-release");
- r = parse_env_file(os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- if (r == -ENOENT) {
-
- os_release = prefix_roota(arg_root, "/usr/lib/os-release");
- r = parse_env_file(os_release, NEWLINE,
- "PRETTY_NAME", &pretty_name,
- NULL);
- }
-
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read os-release file: %m");
-
- printf("\nWelcome to your new installation of %s!\nPlease configure a few basic system settings:\n\n",
- isempty(pretty_name) ? "GNU/Linux" : pretty_name);
-
- press_any_key();
-
- done = true;
-}
-
-static int show_menu(char **x, unsigned n_columns, unsigned width, unsigned percentage) {
- unsigned n, per_column, i, j;
- unsigned break_lines, break_modulo;
-
- assert(n_columns > 0);
-
- n = strv_length(x);
- per_column = (n + n_columns - 1) / n_columns;
-
- break_lines = lines();
- if (break_lines > 2)
- break_lines--;
-
- /* The first page gets two extra lines, since we want to show
- * a title */
- break_modulo = break_lines;
- if (break_modulo > 3)
- break_modulo -= 3;
-
- for (i = 0; i < per_column; i++) {
-
- for (j = 0; j < n_columns; j ++) {
- _cleanup_free_ char *e = NULL;
-
- if (j * per_column + i >= n)
- break;
-
- e = ellipsize(x[j * per_column + i], width, percentage);
- if (!e)
- return log_oom();
-
- printf("%4u) %-*s", j * per_column + i + 1, width, e);
- }
-
- putchar('\n');
-
- /* on the first screen we reserve 2 extra lines for the title */
- if (i % break_lines == break_modulo) {
- if (!press_any_key())
- return 0;
- }
- }
-
- return 0;
-}
-
-static int prompt_loop(const char *text, char **l, bool (*is_valid)(const char *name), char **ret) {
- int r;
-
- assert(text);
- assert(is_valid);
- assert(ret);
-
- for (;;) {
- _cleanup_free_ char *p = NULL;
- unsigned u;
-
- r = ask_string(&p, "%s %s (empty to skip): ", special_glyph(TRIANGULAR_BULLET), text);
- if (r < 0)
- return log_error_errno(r, "Failed to query user: %m");
-
- if (isempty(p)) {
- log_warning("No data entered, skipping.");
- return 0;
- }
-
- r = safe_atou(p, &u);
- if (r >= 0) {
- char *c;
-
- if (u <= 0 || u > strv_length(l)) {
- log_error("Specified entry number out of range.");
- continue;
- }
-
- log_info("Selected '%s'.", l[u-1]);
-
- c = strdup(l[u-1]);
- if (!c)
- return log_oom();
-
- free(*ret);
- *ret = c;
- return 0;
- }
-
- if (!is_valid(p)) {
- log_error("Entered data invalid.");
- continue;
- }
-
- free(*ret);
- *ret = p;
- p = 0;
- return 0;
- }
-}
-
-static int prompt_locale(void) {
- _cleanup_strv_free_ char **locales = NULL;
- int r;
-
- if (arg_locale || arg_locale_messages)
- return 0;
-
- if (!arg_prompt_locale)
- return 0;
-
- r = get_locales(&locales);
- if (r < 0)
- return log_error_errno(r, "Cannot query locales list: %m");
-
- print_welcome();
-
- printf("\nAvailable Locales:\n\n");
- r = show_menu(locales, 3, 22, 60);
- if (r < 0)
- return r;
-
- putchar('\n');
-
- r = prompt_loop("Please enter system locale name or number", locales, locale_is_valid, &arg_locale);
- if (r < 0)
- return r;
-
- if (isempty(arg_locale))
- return 0;
-
- r = prompt_loop("Please enter system message locale name or number", locales, locale_is_valid, &arg_locale_messages);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int process_locale(void) {
- const char *etc_localeconf;
- char* locales[3];
- unsigned i = 0;
- int r;
-
- etc_localeconf = prefix_roota(arg_root, "/etc/locale.conf");
- if (laccess(etc_localeconf, F_OK) >= 0)
- return 0;
-
- if (arg_copy_locale && arg_root) {
-
- mkdir_parents(etc_localeconf, 0755);
- r = copy_file("/etc/locale.conf", etc_localeconf, 0, 0644, 0);
- if (r != -ENOENT) {
- if (r < 0)
- return log_error_errno(r, "Failed to copy %s: %m", etc_localeconf);
-
- log_info("%s copied.", etc_localeconf);
- return 0;
- }
- }
-
- r = prompt_locale();
- if (r < 0)
- return r;
-
- if (!isempty(arg_locale))
- locales[i++] = strjoina("LANG=", arg_locale);
- if (!isempty(arg_locale_messages) && !streq(arg_locale_messages, arg_locale))
- locales[i++] = strjoina("LC_MESSAGES=", arg_locale_messages);
-
- if (i == 0)
- return 0;
-
- locales[i] = NULL;
-
- mkdir_parents(etc_localeconf, 0755);
- r = write_env_file(etc_localeconf, locales);
- if (r < 0)
- return log_error_errno(r, "Failed to write %s: %m", etc_localeconf);
-
- log_info("%s written.", etc_localeconf);
- return 0;
-}
-
-static int prompt_timezone(void) {
- _cleanup_strv_free_ char **zones = NULL;
- int r;
-
- if (arg_timezone)
- return 0;
-
- if (!arg_prompt_timezone)
- return 0;
-
- r = get_timezones(&zones);
- if (r < 0)
- return log_error_errno(r, "Cannot query timezone list: %m");
-
- print_welcome();
-
- printf("\nAvailable Time Zones:\n\n");
- r = show_menu(zones, 3, 22, 30);
- if (r < 0)
- return r;
-
- putchar('\n');
-
- r = prompt_loop("Please enter timezone name or number", zones, timezone_is_valid, &arg_timezone);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int process_timezone(void) {
- const char *etc_localtime, *e;
- int r;
-
- etc_localtime = prefix_roota(arg_root, "/etc/localtime");
- if (laccess(etc_localtime, F_OK) >= 0)
- return 0;
-
- if (arg_copy_timezone && arg_root) {
- _cleanup_free_ char *p = NULL;
-
- r = readlink_malloc("/etc/localtime", &p);
- if (r != -ENOENT) {
- if (r < 0)
- return log_error_errno(r, "Failed to read host timezone: %m");
-
- mkdir_parents(etc_localtime, 0755);
- if (symlink(p, etc_localtime) < 0)
- return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime);
-
- log_info("%s copied.", etc_localtime);
- return 0;
- }
- }
-
- r = prompt_timezone();
- if (r < 0)
- return r;
-
- if (isempty(arg_timezone))
- return 0;
-
- e = strjoina("../usr/share/zoneinfo/", arg_timezone);
-
- mkdir_parents(etc_localtime, 0755);
- if (symlink(e, etc_localtime) < 0)
- return log_error_errno(errno, "Failed to create %s symlink: %m", etc_localtime);
-
- log_info("%s written", etc_localtime);
- return 0;
-}
-
-static int prompt_hostname(void) {
- int r;
-
- if (arg_hostname)
- return 0;
-
- if (!arg_prompt_hostname)
- return 0;
-
- print_welcome();
- putchar('\n');
-
- for (;;) {
- _cleanup_free_ char *h = NULL;
-
- r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", special_glyph(TRIANGULAR_BULLET));
- if (r < 0)
- return log_error_errno(r, "Failed to query hostname: %m");
-
- if (isempty(h)) {
- log_warning("No hostname entered, skipping.");
- break;
- }
-
- if (!hostname_is_valid(h, true)) {
- log_error("Specified hostname invalid.");
- continue;
- }
-
- /* Get rid of the trailing dot that we allow, but don't want to see */
- arg_hostname = hostname_cleanup(h);
- h = NULL;
- break;
- }
-
- return 0;
-}
-
-static int process_hostname(void) {
- const char *etc_hostname;
- int r;
-
- etc_hostname = prefix_roota(arg_root, "/etc/hostname");
- if (laccess(etc_hostname, F_OK) >= 0)
- return 0;
-
- r = prompt_hostname();
- if (r < 0)
- return r;
-
- if (isempty(arg_hostname))
- return 0;
-
- mkdir_parents(etc_hostname, 0755);
- r = write_string_file(etc_hostname, arg_hostname, WRITE_STRING_FILE_CREATE);
- if (r < 0)
- return log_error_errno(r, "Failed to write %s: %m", etc_hostname);
-
- log_info("%s written.", etc_hostname);
- return 0;
-}
-
-static int process_machine_id(void) {
- const char *etc_machine_id;
- char id[SD_ID128_STRING_MAX];
- int r;
-
- etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
- if (laccess(etc_machine_id, F_OK) >= 0)
- return 0;
-
- if (sd_id128_equal(arg_machine_id, SD_ID128_NULL))
- return 0;
-
- mkdir_parents(etc_machine_id, 0755);
- r = write_string_file(etc_machine_id, sd_id128_to_string(arg_machine_id, id), WRITE_STRING_FILE_CREATE);
- if (r < 0)
- return log_error_errno(r, "Failed to write machine id: %m");
-
- log_info("%s written.", etc_machine_id);
- return 0;
-}
-
-static int prompt_root_password(void) {
- const char *msg1, *msg2, *etc_shadow;
- int r;
-
- if (arg_root_password)
- return 0;
-
- if (!arg_prompt_root_password)
- return 0;
-
- etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (laccess(etc_shadow, F_OK) >= 0)
- return 0;
-
- print_welcome();
- putchar('\n');
-
- msg1 = strjoina(special_glyph(TRIANGULAR_BULLET), " Please enter a new root password (empty to skip): ");
- msg2 = strjoina(special_glyph(TRIANGULAR_BULLET), " Please enter new root password again: ");
-
- for (;;) {
- _cleanup_string_free_erase_ char *a = NULL, *b = NULL;
-
- r = ask_password_tty(msg1, NULL, 0, 0, NULL, &a);
- if (r < 0)
- return log_error_errno(r, "Failed to query root password: %m");
-
- if (isempty(a)) {
- log_warning("No password entered, skipping.");
- break;
- }
-
- r = ask_password_tty(msg2, NULL, 0, 0, NULL, &b);
- if (r < 0)
- return log_error_errno(r, "Failed to query root password: %m");
-
- if (!streq(a, b)) {
- log_error("Entered passwords did not match, please try again.");
- continue;
- }
-
- arg_root_password = a;
- a = NULL;
- break;
- }
-
- return 0;
-}
-
-static int write_root_shadow(const char *path, const struct spwd *p) {
- _cleanup_fclose_ FILE *f = NULL;
- assert(path);
- assert(p);
-
- RUN_WITH_UMASK(0777)
- f = fopen(path, "wex");
- if (!f)
- return -errno;
-
- errno = 0;
- if (putspent(p, f) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return fflush_and_check(f);
-}
-
-static int process_root_password(void) {
-
- static const char table[] =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789"
- "./";
-
- struct spwd item = {
- .sp_namp = (char*) "root",
- .sp_min = -1,
- .sp_max = -1,
- .sp_warn = -1,
- .sp_inact = -1,
- .sp_expire = -1,
- .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
- };
-
- _cleanup_close_ int lock = -1;
- char salt[3+16+1+1];
- uint8_t raw[16];
- unsigned i;
- char *j;
-
- const char *etc_shadow;
- int r;
-
- etc_shadow = prefix_roota(arg_root, "/etc/shadow");
- if (laccess(etc_shadow, F_OK) >= 0)
- return 0;
-
- mkdir_parents(etc_shadow, 0755);
-
- lock = take_etc_passwd_lock(arg_root);
- if (lock < 0)
- return log_error_errno(lock, "Failed to take a lock: %m");
-
- if (arg_copy_root_password && arg_root) {
- struct spwd *p;
-
- errno = 0;
- p = getspnam("root");
- if (p || errno != ENOENT) {
- if (!p) {
- if (!errno)
- errno = EIO;
-
- return log_error_errno(errno, "Failed to find shadow entry for root: %m");
- }
-
- r = write_root_shadow(etc_shadow, p);
- if (r < 0)
- return log_error_errno(r, "Failed to write %s: %m", etc_shadow);
-
- log_info("%s copied.", etc_shadow);
- return 0;
- }
- }
-
- r = prompt_root_password();
- if (r < 0)
- return r;
-
- if (!arg_root_password)
- return 0;
-
- r = dev_urandom(raw, 16);
- if (r < 0)
- return log_error_errno(r, "Failed to get salt: %m");
-
- /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */
- assert_cc(sizeof(table) == 64 + 1);
- j = stpcpy(salt, "$6$");
- for (i = 0; i < 16; i++)
- j[i] = table[raw[i] & 63];
- j[i++] = '$';
- j[i] = 0;
-
- errno = 0;
- item.sp_pwdp = crypt(arg_root_password, salt);
- if (!item.sp_pwdp) {
- if (!errno)
- errno = EINVAL;
-
- return log_error_errno(errno, "Failed to encrypt password: %m");
- }
-
- item.sp_lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
-
- r = write_root_shadow(etc_shadow, &item);
- if (r < 0)
- return log_error_errno(r, "Failed to write %s: %m", etc_shadow);
-
- log_info("%s written.", etc_shadow);
- return 0;
-}
-
-static void help(void) {
- printf("%s [OPTIONS...]\n\n"
- "Configures basic settings of the system.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --root=PATH Operate on an alternate filesystem root\n"
- " --locale=LOCALE Set primary locale (LANG=)\n"
- " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
- " --timezone=TIMEZONE Set timezone\n"
- " --hostname=NAME Set host name\n"
- " --machine-ID=ID Set machine ID\n"
- " --root-password=PASSWORD Set root password\n"
- " --root-password-file=FILE Set root password from file\n"
- " --prompt-locale Prompt the user for locale settings\n"
- " --prompt-timezone Prompt the user for timezone\n"
- " --prompt-hostname Prompt the user for hostname\n"
- " --prompt-root-password Prompt the user for root password\n"
- " --prompt Prompt for all of the above\n"
- " --copy-locale Copy locale from host\n"
- " --copy-timezone Copy timezone from host\n"
- " --copy-root-password Copy root password from host\n"
- " --copy Copy locale, timezone, root password\n"
- " --setup-machine-id Generate a new random machine ID\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ROOT,
- ARG_LOCALE,
- ARG_LOCALE_MESSAGES,
- ARG_TIMEZONE,
- ARG_HOSTNAME,
- ARG_MACHINE_ID,
- ARG_ROOT_PASSWORD,
- ARG_ROOT_PASSWORD_FILE,
- ARG_PROMPT,
- ARG_PROMPT_LOCALE,
- ARG_PROMPT_TIMEZONE,
- ARG_PROMPT_HOSTNAME,
- ARG_PROMPT_ROOT_PASSWORD,
- ARG_COPY,
- ARG_COPY_LOCALE,
- ARG_COPY_TIMEZONE,
- ARG_COPY_ROOT_PASSWORD,
- ARG_SETUP_MACHINE_ID,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- { "locale", required_argument, NULL, ARG_LOCALE },
- { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
- { "timezone", required_argument, NULL, ARG_TIMEZONE },
- { "hostname", required_argument, NULL, ARG_HOSTNAME },
- { "machine-id", required_argument, NULL, ARG_MACHINE_ID },
- { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD },
- { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE },
- { "prompt", no_argument, NULL, ARG_PROMPT },
- { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE },
- { "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE },
- { "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME },
- { "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD },
- { "copy", no_argument, NULL, ARG_COPY },
- { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE },
- { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE },
- { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD },
- { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
- {}
- };
-
- int r, c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
- if (r < 0)
- return r;
- break;
-
- case ARG_LOCALE:
- if (!locale_is_valid(optarg)) {
- log_error("Locale %s is not valid.", optarg);
- return -EINVAL;
- }
-
- r = free_and_strdup(&arg_locale, optarg);
- if (r < 0)
- return log_oom();
-
- break;
-
- case ARG_LOCALE_MESSAGES:
- if (!locale_is_valid(optarg)) {
- log_error("Locale %s is not valid.", optarg);
- return -EINVAL;
- }
-
- r = free_and_strdup(&arg_locale_messages, optarg);
- if (r < 0)
- return log_oom();
-
- break;
-
- case ARG_TIMEZONE:
- if (!timezone_is_valid(optarg)) {
- log_error("Timezone %s is not valid.", optarg);
- return -EINVAL;
- }
-
- r = free_and_strdup(&arg_timezone, optarg);
- if (r < 0)
- return log_oom();
-
- break;
-
- case ARG_ROOT_PASSWORD:
- r = free_and_strdup(&arg_root_password, optarg);
- if (r < 0)
- return log_oom();
- break;
-
- case ARG_ROOT_PASSWORD_FILE:
- arg_root_password = mfree(arg_root_password);
-
- r = read_one_line_file(optarg, &arg_root_password);
- if (r < 0)
- return log_error_errno(r, "Failed to read %s: %m", optarg);
-
- break;
-
- case ARG_HOSTNAME:
- if (!hostname_is_valid(optarg, true)) {
- log_error("Host name %s is not valid.", optarg);
- return -EINVAL;
- }
-
- hostname_cleanup(optarg);
- r = free_and_strdup(&arg_hostname, optarg);
- if (r < 0)
- return log_oom();
-
- break;
-
- case ARG_MACHINE_ID:
- if (sd_id128_from_string(optarg, &arg_machine_id) < 0) {
- log_error("Failed to parse machine id %s.", optarg);
- return -EINVAL;
- }
-
- break;
-
- case ARG_PROMPT:
- arg_prompt_locale = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true;
- break;
-
- case ARG_PROMPT_LOCALE:
- arg_prompt_locale = true;
- break;
-
- case ARG_PROMPT_TIMEZONE:
- arg_prompt_timezone = true;
- break;
-
- case ARG_PROMPT_HOSTNAME:
- arg_prompt_hostname = true;
- break;
-
- case ARG_PROMPT_ROOT_PASSWORD:
- arg_prompt_root_password = true;
- break;
-
- case ARG_COPY:
- arg_copy_locale = arg_copy_timezone = arg_copy_root_password = true;
- break;
-
- case ARG_COPY_LOCALE:
- arg_copy_locale = true;
- break;
-
- case ARG_COPY_TIMEZONE:
- arg_copy_timezone = true;
- break;
-
- case ARG_COPY_ROOT_PASSWORD:
- arg_copy_root_password = true;
- break;
-
- case ARG_SETUP_MACHINE_ID:
-
- r = sd_id128_randomize(&arg_machine_id);
- if (r < 0)
- return log_error_errno(r, "Failed to generate randomized machine ID: %m");
-
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = process_locale();
- if (r < 0)
- goto finish;
-
- r = process_timezone();
- if (r < 0)
- goto finish;
-
- r = process_hostname();
- if (r < 0)
- goto finish;
-
- r = process_machine_id();
- if (r < 0)
- goto finish;
-
- r = process_root_password();
- if (r < 0)
- goto finish;
-
-finish:
- free(arg_root);
- free(arg_locale);
- free(arg_locale_messages);
- free(arg_timezone);
- free(arg_hostname);
- string_erase(arg_root_password);
- free(arg_root_password);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-fsck/Makefile b/src/grp-initutils/systemd-fsck/Makefile
deleted file mode 100644
index f29fba4d20..0000000000
--- a/src/grp-initutils/systemd-fsck/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-rootlibexec_PROGRAMS += systemd-fsck
-systemd_fsck_SOURCES = \
- src/fsck/fsck.c
-
-systemd_fsck_LDADD = \
- libshared.la
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-fsck/fsck.c b/src/grp-initutils/systemd-fsck/fsck.c
deleted file mode 100644
index 4ca018763f..0000000000
--- a/src/grp-initutils/systemd-fsck/fsck.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
- Copyright 2014 Holger Hans Peter Freyther
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/file.h>
-#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <systemd/sd-bus.h>
-
-#include "basic/alloc-util.h"
-#include "basic/fd-util.h"
-#include "basic/fs-util.h"
-#include "basic/parse-util.h"
-#include "basic/path-util.h"
-#include "basic/proc-cmdline.h"
-#include "basic/process-util.h"
-#include "basic/signal-util.h"
-#include "basic/socket-util.h"
-#include "basic/special.h"
-#include "basic/stdio-util.h"
-#include "basic/util.h"
-#include "sd-bus/bus-common-errors.h"
-#include "sd-bus/bus-error.h"
-#include "sd-device/device-util.h"
-#include "sd-device/sd-device.h"
-#include "shared/bus-util.h"
-
-/* exit codes as defined in fsck(8) */
-enum {
- FSCK_SUCCESS = 0,
- FSCK_ERROR_CORRECTED = 1,
- FSCK_SYSTEM_SHOULD_REBOOT = 2,
- FSCK_ERRORS_LEFT_UNCORRECTED = 4,
- FSCK_OPERATIONAL_ERROR = 8,
- FSCK_USAGE_OR_SYNTAX_ERROR = 16,
- FSCK_USER_CANCELLED = 32,
- FSCK_SHARED_LIB_ERROR = 128,
-};
-
-static bool arg_skip = false;
-static bool arg_force = false;
-static bool arg_show_progress = false;
-static const char *arg_repair = "-a";
-
-static void start_target(const char *target, const char *mode) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int r;
-
- assert(target);
-
- r = bus_connect_system_systemd(&bus);
- if (r < 0) {
- log_error_errno(r, "Failed to get D-Bus connection: %m");
- return;
- }
-
- log_info("Running request %s/start/replace", target);
-
- /* Start these units only if we can replace base.target with it */
- r = sd_bus_call_method(bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnitReplace",
- &error,
- NULL,
- "sss", "basic.target", target, mode);
-
- /* Don't print a warning if we aren't called during startup */
- if (r < 0 && !sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_JOB))
- log_error("Failed to start unit: %s", bus_error_message(&error, r));
-}
-
-static int parse_proc_cmdline_item(const char *key, const char *value) {
- int r;
-
- assert(key);
-
- if (streq(key, "fsck.mode") && value) {
-
- if (streq(value, "auto"))
- arg_force = arg_skip = false;
- else if (streq(value, "force"))
- arg_force = true;
- else if (streq(value, "skip"))
- arg_skip = true;
- else
- log_warning("Invalid fsck.mode= parameter '%s'. Ignoring.", value);
-
- } else if (streq(key, "fsck.repair") && value) {
-
- if (streq(value, "preen"))
- arg_repair = "-a";
- else {
- r = parse_boolean(value);
- if (r > 0)
- arg_repair = "-y";
- else if (r == 0)
- arg_repair = "-n";
- else
- log_warning("Invalid fsck.repair= parameter '%s'. Ignoring.", value);
- }
- }
-
-#ifdef HAVE_SYSV_COMPAT
- else if (streq(key, "fastboot") && !value) {
- log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
- arg_skip = true;
-
- } else if (streq(key, "forcefsck") && !value) {
- log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
- arg_force = true;
- }
-#endif
-
- return 0;
-}
-
-static void test_files(void) {
-
-#ifdef HAVE_SYSV_COMPAT
- if (access("/fastboot", F_OK) >= 0) {
- log_error("Please pass 'fsck.mode=skip' on the kernel command line rather than creating /fastboot on the root file system.");
- arg_skip = true;
- }
-
- if (access("/forcefsck", F_OK) >= 0) {
- log_error("Please pass 'fsck.mode=force' on the kernel command line rather than creating /forcefsck on the root file system.");
- arg_force = true;
- }
-#endif
-
- arg_show_progress = access("/run/systemd/show-status", F_OK) >= 0;
-}
-
-static double percent(int pass, unsigned long cur, unsigned long max) {
- /* Values stolen from e2fsck */
-
- static const int pass_table[] = {
- 0, 70, 90, 92, 95, 100
- };
-
- if (pass <= 0)
- return 0.0;
-
- if ((unsigned) pass >= ELEMENTSOF(pass_table) || max == 0)
- return 100.0;
-
- return (double) pass_table[pass-1] +
- ((double) pass_table[pass] - (double) pass_table[pass-1]) *
- (double) cur / (double) max;
-}
-
-static int process_progress(int fd) {
- _cleanup_fclose_ FILE *console = NULL, *f = NULL;
- usec_t last = 0;
- bool locked = false;
- int clear = 0, r;
-
- /* No progress pipe to process? Then we are a NOP. */
- if (fd < 0)
- return 0;
-
- f = fdopen(fd, "re");
- if (!f) {
- safe_close(fd);
- return -errno;
- }
-
- console = fopen("/dev/console", "we");
- if (!console)
- return -ENOMEM;
-
- for (;;) {
- int pass, m;
- unsigned long cur, max;
- _cleanup_free_ char *device = NULL;
- double p;
- usec_t t;
-
- if (fscanf(f, "%i %lu %lu %ms", &pass, &cur, &max, &device) != 4) {
-
- if (ferror(f))
- r = log_warning_errno(errno, "Failed to read from progress pipe: %m");
- else if (feof(f))
- r = 0;
- else {
- log_warning("Failed to parse progress pipe data");
- r = -EBADMSG;
- }
- break;
- }
-
- /* Only show one progress counter at max */
- if (!locked) {
- if (flock(fileno(console), LOCK_EX|LOCK_NB) < 0)
- continue;
-
- locked = true;
- }
-
- /* Only update once every 50ms */
- t = now(CLOCK_MONOTONIC);
- if (last + 50 * USEC_PER_MSEC > t)
- continue;
-
- last = t;
-
- p = percent(pass, cur, max);
- fprintf(console, "\r%s: fsck %3.1f%% complete...\r%n", device, p, &m);
- fflush(console);
-
- if (m > clear)
- clear = m;
- }
-
- if (clear > 0) {
- unsigned j;
-
- fputc('\r', console);
- for (j = 0; j < (unsigned) clear; j++)
- fputc(' ', console);
- fputc('\r', console);
- fflush(console);
- }
-
- return r;
-}
-
-static int fsck_progress_socket(void) {
- static const union sockaddr_union sa = {
- .un.sun_family = AF_UNIX,
- .un.sun_path = "/run/systemd/fsck.progress",
- };
-
- int fd, r;
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0)
- return log_warning_errno(errno, "socket(): %m");
-
- if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
- r = log_full_errno(errno == ECONNREFUSED || errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
- errno, "Failed to connect to progress socket %s, ignoring: %m", sa.un.sun_path);
- safe_close(fd);
- return r;
- }
-
- return fd;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_close_pair_ int progress_pipe[2] = { -1, -1 };
- _cleanup_(sd_device_unrefp) sd_device *dev = NULL;
- const char *device, *type;
- bool root_directory;
- siginfo_t status;
- struct stat st;
- int r;
- pid_t pid;
-
- if (argc > 2) {
- log_error("This program expects one or no arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = parse_proc_cmdline(parse_proc_cmdline_item);
- if (r < 0)
- log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
-
- test_files();
-
- if (!arg_force && arg_skip) {
- r = 0;
- goto finish;
- }
-
- if (argc > 1) {
- device = argv[1];
-
- if (stat(device, &st) < 0) {
- r = log_error_errno(errno, "Failed to stat %s: %m", device);
- goto finish;
- }
-
- if (!S_ISBLK(st.st_mode)) {
- log_error("%s is not a block device.", device);
- r = -EINVAL;
- goto finish;
- }
-
- r = sd_device_new_from_devnum(&dev, 'b', st.st_rdev);
- if (r < 0) {
- log_error_errno(r, "Failed to detect device %s: %m", device);
- goto finish;
- }
-
- root_directory = false;
- } else {
- struct timespec times[2];
-
- /* Find root device */
-
- if (stat("/", &st) < 0) {
- r = log_error_errno(errno, "Failed to stat() the root directory: %m");
- goto finish;
- }
-
- /* Virtual root devices don't need an fsck */
- if (major(st.st_dev) == 0) {
- log_debug("Root directory is virtual or btrfs, skipping check.");
- r = 0;
- goto finish;
- }
-
- /* check if we are already writable */
- times[0] = st.st_atim;
- times[1] = st.st_mtim;
-
- if (utimensat(AT_FDCWD, "/", times, 0) == 0) {
- log_info("Root directory is writable, skipping check.");
- r = 0;
- goto finish;
- }
-
- r = sd_device_new_from_devnum(&dev, 'b', st.st_dev);
- if (r < 0) {
- log_error_errno(r, "Failed to detect root device: %m");
- goto finish;
- }
-
- r = sd_device_get_devname(dev, &device);
- if (r < 0) {
- log_error_errno(r, "Failed to detect device node of root directory: %m");
- goto finish;
- }
-
- root_directory = true;
- }
-
- r = sd_device_get_property_value(dev, "ID_FS_TYPE", &type);
- if (r >= 0) {
- r = fsck_exists(type);
- if (r < 0)
- log_warning_errno(r, "Couldn't detect if fsck.%s may be used for %s, proceeding: %m", type, device);
- else if (r == 0) {
- log_info("fsck.%s doesn't exist, not checking file system on %s.", type, device);
- goto finish;
- }
- }
-
- if (arg_show_progress) {
- if (pipe(progress_pipe) < 0) {
- r = log_error_errno(errno, "pipe(): %m");
- goto finish;
- }
- }
-
- pid = fork();
- if (pid < 0) {
- r = log_error_errno(errno, "fork(): %m");
- goto finish;
- }
- if (pid == 0) {
- char dash_c[sizeof("-C")-1 + DECIMAL_STR_MAX(int) + 1];
- int progress_socket = -1;
- const char *cmdline[9];
- int i = 0;
-
- /* Child */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
- /* Close the reading side of the progress pipe */
- progress_pipe[0] = safe_close(progress_pipe[0]);
-
- /* Try to connect to a progress management daemon, if there is one */
- progress_socket = fsck_progress_socket();
- if (progress_socket >= 0) {
- /* If this worked we close the progress pipe early, and just use the socket */
- progress_pipe[1] = safe_close(progress_pipe[1]);
- xsprintf(dash_c, "-C%i", progress_socket);
- } else if (progress_pipe[1] >= 0) {
- /* Otherwise if we have the progress pipe to our own local handle, we use it */
- xsprintf(dash_c, "-C%i", progress_pipe[1]);
- } else
- dash_c[0] = 0;
-
- cmdline[i++] = "/sbin/fsck";
- cmdline[i++] = arg_repair;
- cmdline[i++] = "-T";
-
- /*
- * Since util-linux v2.25 fsck uses /run/fsck/<diskname>.lock files.
- * The previous versions use flock for the device and conflict with
- * udevd, see https://bugs.freedesktop.org/show_bug.cgi?id=79576#c5
- */
- cmdline[i++] = "-l";
-
- if (!root_directory)
- cmdline[i++] = "-M";
-
- if (arg_force)
- cmdline[i++] = "-f";
-
- if (!isempty(dash_c))
- cmdline[i++] = dash_c;
-
- cmdline[i++] = device;
- cmdline[i++] = NULL;
-
- execv(cmdline[0], (char**) cmdline);
- _exit(FSCK_OPERATIONAL_ERROR);
- }
-
- progress_pipe[1] = safe_close(progress_pipe[1]);
- (void) process_progress(progress_pipe[0]);
- progress_pipe[0] = -1;
-
- r = wait_for_terminate(pid, &status);
- if (r < 0) {
- log_error_errno(r, "waitid(): %m");
- goto finish;
- }
-
- if (status.si_code != CLD_EXITED || (status.si_status & ~1)) {
-
- if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED)
- log_error("fsck terminated by signal %s.", signal_to_string(status.si_status));
- else if (status.si_code == CLD_EXITED)
- log_error("fsck failed with error code %i.", status.si_status);
- else
- log_error("fsck failed due to unknown reason.");
-
- r = -EINVAL;
-
- if (status.si_code == CLD_EXITED && (status.si_status & FSCK_SYSTEM_SHOULD_REBOOT) && root_directory)
- /* System should be rebooted. */
- start_target(SPECIAL_REBOOT_TARGET, "replace-irreversibly");
- else if (status.si_code == CLD_EXITED && (status.si_status & (FSCK_SYSTEM_SHOULD_REBOOT | FSCK_ERRORS_LEFT_UNCORRECTED)))
- /* Some other problem */
- start_target(SPECIAL_EMERGENCY_TARGET, "replace");
- else {
- log_warning("Ignoring error.");
- r = 0;
- }
-
- } else
- r = 0;
-
- if (status.si_code == CLD_EXITED && (status.si_status & FSCK_ERROR_CORRECTED))
- (void) touch("/run/systemd/quotacheck");
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-quotacheck/Makefile b/src/grp-initutils/systemd-quotacheck/Makefile
deleted file mode 100644
index bb3d8dce6b..0000000000
--- a/src/grp-initutils/systemd-quotacheck/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_QUOTACHECK),)
-rootlibexec_PROGRAMS += \
- systemd-quotacheck
-
-nodist_systemunit_DATA += \
- units/systemd-quotacheck.service
-
-systemd_quotacheck_SOURCES = \
- src/quotacheck/quotacheck.c
-
-systemd_quotacheck_LDADD = \
- libshared.la
-endif # ENABLE_QUOTACHECK
-
-EXTRA_DIST += \
- units/systemd-quotacheck.service.in
-
-nodist_systemunit_DATA += \
- units/quotaon.service
-
-sd.CPPFLAGS += -DQUOTACHECK=\"$(QUOTACHECK)\"
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-quotacheck/quotacheck.c b/src/grp-initutils/systemd-quotacheck/quotacheck.c
deleted file mode 100644
index 3c2292b0c4..0000000000
--- a/src/grp-initutils/systemd-quotacheck/quotacheck.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include "basic/proc-cmdline.h"
-#include "basic/process-util.h"
-#include "basic/signal-util.h"
-#include "basic/string-util.h"
-#include "basic/util.h"
-
-static bool arg_skip = false;
-static bool arg_force = false;
-
-static int parse_proc_cmdline_item(const char *key, const char *value) {
-
- if (streq(key, "quotacheck.mode") && value) {
-
- if (streq(value, "auto"))
- arg_force = arg_skip = false;
- else if (streq(value, "force"))
- arg_force = true;
- else if (streq(value, "skip"))
- arg_skip = true;
- else
- log_warning("Invalid quotacheck.mode= parameter '%s'. Ignoring.", value);
- }
-
-#ifdef HAVE_SYSV_COMPAT
- else if (streq(key, "forcequotacheck") && !value) {
- log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line.");
- arg_force = true;
- }
-#endif
-
- return 0;
-}
-
-static void test_files(void) {
-
-#ifdef HAVE_SYSV_COMPAT
- if (access("/forcequotacheck", F_OK) >= 0) {
- log_error("Please pass 'quotacheck.mode=force' on the kernel command line rather than creating /forcequotacheck on the root file system.");
- arg_force = true;
- }
-#endif
-}
-
-int main(int argc, char *argv[]) {
-
- static const char * const cmdline[] = {
- QUOTACHECK,
- "-anug",
- NULL
- };
-
- pid_t pid;
- int r;
-
- if (argc > 1) {
- log_error("This program takes no arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = parse_proc_cmdline(parse_proc_cmdline_item);
- if (r < 0)
- log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
-
- test_files();
-
- if (!arg_force) {
- if (arg_skip)
- return EXIT_SUCCESS;
-
- if (access("/run/systemd/quotacheck", F_OK) < 0)
- return EXIT_SUCCESS;
- }
-
- pid = fork();
- if (pid < 0) {
- log_error_errno(errno, "fork(): %m");
- return EXIT_FAILURE;
- } else if (pid == 0) {
-
- /* Child */
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
- assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
-
- execv(cmdline[0], (char**) cmdline);
- _exit(1); /* Operational error */
- }
-
- r = wait_for_terminate_and_warn("quotacheck", pid, true);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-random-seed/Makefile b/src/grp-initutils/systemd-random-seed/Makefile
deleted file mode 100644
index 489a8ab007..0000000000
--- a/src/grp-initutils/systemd-random-seed/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_RANDOMSEED),)
-rootlibexec_PROGRAMS += \
- systemd-random-seed
-
-nodist_systemunit_DATA += \
- units/systemd-random-seed.service
-
-systemd_random_seed_SOURCES = \
- src/random-seed/random-seed.c
-
-systemd_random_seed_LDADD = \
- libshared.la
-
-SYSINIT_TARGET_WANTS += \
- systemd-random-seed.service
-
-endif # ENABLE_RANDOMSEED
-
-EXTRA_DIST += \
- units/systemd-random-seed.service.in
-
-sd.CPPFLAGS += -DRANDOM_SEED_DIR=\"$(localstatedir)/lib/systemd/\"
-sd.CPPFLAGS += -DRANDOM_SEED=\"$(localstatedir)/lib/systemd/random-seed\"
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-random-seed/random-seed.c b/src/grp-initutils/systemd-random-seed/random-seed.c
deleted file mode 100644
index 7fea6069f3..0000000000
--- a/src/grp-initutils/systemd-random-seed/random-seed.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "basic/alloc-util.h"
-#include "basic/fd-util.h"
-#include "basic/io-util.h"
-#include "basic/log.h"
-#include "basic/mkdir.h"
-#include "basic/string-util.h"
-#include "basic/util.h"
-
-#define POOL_SIZE_MIN 512
-
-int main(int argc, char *argv[]) {
- _cleanup_close_ int seed_fd = -1, random_fd = -1;
- _cleanup_free_ void* buf = NULL;
- size_t buf_size = 0;
- ssize_t k;
- int r, open_rw_error;
- FILE *f;
- bool refresh_seed_file = true;
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- /* Read pool size, if possible */
- f = fopen("/proc/sys/kernel/random/poolsize", "re");
- if (f) {
- if (fscanf(f, "%zu", &buf_size) > 0)
- /* poolsize is in bits on 2.6, but we want bytes */
- buf_size /= 8;
-
- fclose(f);
- }
-
- if (buf_size <= POOL_SIZE_MIN)
- buf_size = POOL_SIZE_MIN;
-
- buf = malloc(buf_size);
- if (!buf) {
- r = log_oom();
- goto finish;
- }
-
- r = mkdir_parents_label(RANDOM_SEED, 0755);
- if (r < 0) {
- log_error_errno(r, "Failed to create directory " RANDOM_SEED_DIR ": %m");
- goto finish;
- }
-
- /* When we load the seed we read it and write it to the device
- * and then immediately update the saved seed with new data,
- * to make sure the next boot gets seeded differently. */
-
- if (streq(argv[1], "load")) {
-
- seed_fd = open(RANDOM_SEED, O_RDWR|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
- open_rw_error = -errno;
- if (seed_fd < 0) {
- refresh_seed_file = false;
-
- seed_fd = open(RANDOM_SEED, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (seed_fd < 0) {
- bool missing = errno == ENOENT;
-
- log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
- open_rw_error, "Failed to open " RANDOM_SEED " for writing: %m");
- r = log_full_errno(missing ? LOG_DEBUG : LOG_ERR,
- errno, "Failed to open " RANDOM_SEED " for reading: %m");
- if (missing)
- r = 0;
-
- goto finish;
- }
- }
-
- random_fd = open("/dev/urandom", O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
- if (random_fd < 0) {
- random_fd = open("/dev/urandom", O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600);
- if (random_fd < 0) {
- r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
- goto finish;
- }
- }
-
- k = loop_read(seed_fd, buf, buf_size, false);
- if (k < 0)
- r = log_error_errno(k, "Failed to read seed from " RANDOM_SEED ": %m");
- else if (k == 0) {
- r = 0;
- log_debug("Seed file " RANDOM_SEED " not yet initialized, proceeding.");
- } else {
- (void) lseek(seed_fd, 0, SEEK_SET);
-
- r = loop_write(random_fd, buf, (size_t) k, false);
- if (r < 0)
- log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
- }
-
- } else if (streq(argv[1], "save")) {
-
- seed_fd = open(RANDOM_SEED, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_CREAT, 0600);
- if (seed_fd < 0) {
- r = log_error_errno(errno, "Failed to open " RANDOM_SEED ": %m");
- goto finish;
- }
-
- random_fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (random_fd < 0) {
- r = log_error_errno(errno, "Failed to open /dev/urandom: %m");
- goto finish;
- }
-
- } else {
- log_error("Unknown verb '%s'.", argv[1]);
- r = -EINVAL;
- goto finish;
- }
-
- if (refresh_seed_file) {
-
- /* This is just a safety measure. Given that we are root and
- * most likely created the file ourselves the mode and owner
- * should be correct anyway. */
- (void) fchmod(seed_fd, 0600);
- (void) fchown(seed_fd, 0, 0);
-
- k = loop_read(random_fd, buf, buf_size, false);
- if (k < 0) {
- r = log_error_errno(k, "Failed to read new seed from /dev/urandom: %m");
- goto finish;
- }
- if (k == 0) {
- log_error("Got EOF while reading from /dev/urandom.");
- r = -EIO;
- goto finish;
- }
-
- r = loop_write(seed_fd, buf, (size_t) k, false);
- if (r < 0)
- log_error_errno(r, "Failed to write new random seed file: %m");
- }
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-rfkill/Makefile b/src/grp-initutils/systemd-rfkill/Makefile
deleted file mode 100644
index 2b4430b712..0000000000
--- a/src/grp-initutils/systemd-rfkill/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_RFKILL),)
-rootlibexec_PROGRAMS += \
- systemd-rfkill
-
-nodist_systemunit_DATA += \
- units/systemd-rfkill.service
-
-dist_systemunit_DATA += \
- units/systemd-rfkill.socket
-
-systemd_rfkill_SOURCES = \
- src/rfkill/rfkill.c
-
-systemd_rfkill_LDADD = \
- libshared.la
-endif # ENABLE_RFKILL
-
-EXTRA_DIST += \
- units/systemd-rfkill.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-rfkill/rfkill.c b/src/grp-initutils/systemd-rfkill/rfkill.c
deleted file mode 100644
index 86779e9ac8..0000000000
--- a/src/grp-initutils/systemd-rfkill/rfkill.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2013 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <poll.h>
-
-#include <linux/rfkill.h>
-
-#include <libudev.h>
-#include <systemd/sd-daemon.h>
-
-#include "basic/alloc-util.h"
-#include "basic/escape.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/io-util.h"
-#include "basic/mkdir.h"
-#include "basic/parse-util.h"
-#include "basic/proc-cmdline.h"
-#include "basic/string-table.h"
-#include "basic/string-util.h"
-#include "basic/util.h"
-#include "shared/udev-util.h"
-
-#define EXIT_USEC (5 * USEC_PER_SEC)
-
-static const char* const rfkill_type_table[NUM_RFKILL_TYPES] = {
- [RFKILL_TYPE_ALL] = "all",
- [RFKILL_TYPE_WLAN] = "wlan",
- [RFKILL_TYPE_BLUETOOTH] = "bluetooth",
- [RFKILL_TYPE_UWB] = "uwb",
- [RFKILL_TYPE_WIMAX] = "wimax",
- [RFKILL_TYPE_WWAN] = "wwan",
- [RFKILL_TYPE_GPS] = "gps",
- [RFKILL_TYPE_FM] = "fm",
- [RFKILL_TYPE_NFC] = "nfc",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type, int);
-
-static int find_device(
- struct udev *udev,
- const struct rfkill_event *event,
- struct udev_device **ret) {
-
- _cleanup_free_ char *sysname = NULL;
- struct udev_device *device;
- const char *name;
-
- assert(udev);
- assert(event);
- assert(ret);
-
- if (asprintf(&sysname, "rfkill%i", event->idx) < 0)
- return log_oom();
-
- device = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname);
- if (!device)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open device: %m");
-
- name = udev_device_get_sysattr_value(device, "name");
- if (!name) {
- log_debug("Device has no name, ignoring.");
- udev_device_unref(device);
- return -ENOENT;
- }
-
- log_debug("Operating on rfkill device '%s'.", name);
-
- *ret = device;
- return 0;
-}
-
-static int wait_for_initialized(
- struct udev *udev,
- struct udev_device *device,
- struct udev_device **ret) {
-
- _cleanup_udev_monitor_unref_ struct udev_monitor *monitor = NULL;
- struct udev_device *d;
- const char *sysname;
- int watch_fd, r;
-
- assert(udev);
- assert(device);
- assert(ret);
-
- if (udev_device_get_is_initialized(device) != 0) {
- *ret = udev_device_ref(device);
- return 0;
- }
-
- assert_se(sysname = udev_device_get_sysname(device));
-
- /* Wait until the device is initialized, so that we can get
- * access to the ID_PATH property */
-
- monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (!monitor)
- return log_error_errno(errno, "Failed to acquire monitor: %m");
-
- r = udev_monitor_filter_add_match_subsystem_devtype(monitor, "rfkill", NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to add rfkill udev match to monitor: %m");
-
- r = udev_monitor_enable_receiving(monitor);
- if (r < 0)
- return log_error_errno(r, "Failed to enable udev receiving: %m");
-
- watch_fd = udev_monitor_get_fd(monitor);
- if (watch_fd < 0)
- return log_error_errno(watch_fd, "Failed to get watch fd: %m");
-
- /* Check again, maybe things changed */
- d = udev_device_new_from_subsystem_sysname(udev, "rfkill", sysname);
- if (!d)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, "Failed to open device: %m");
-
- if (udev_device_get_is_initialized(d) != 0) {
- *ret = d;
- return 0;
- }
-
- for (;;) {
- _cleanup_udev_device_unref_ struct udev_device *t = NULL;
-
- r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
- if (r == -EINTR)
- continue;
- if (r < 0)
- return log_error_errno(r, "Failed to watch udev monitor: %m");
-
- t = udev_monitor_receive_device(monitor);
- if (!t)
- continue;
-
- if (streq_ptr(udev_device_get_sysname(device), sysname)) {
- *ret = udev_device_ref(t);
- return 0;
- }
- }
-}
-
-static int determine_state_file(
- struct udev *udev,
- const struct rfkill_event *event,
- struct udev_device *d,
- char **ret) {
-
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
- const char *path_id, *type;
- char *state_file;
- int r;
-
- assert(event);
- assert(d);
- assert(ret);
-
- r = wait_for_initialized(udev, d, &device);
- if (r < 0)
- return r;
-
- assert_se(type = rfkill_type_to_string(event->type));
-
- path_id = udev_device_get_property_value(device, "ID_PATH");
- if (path_id) {
- _cleanup_free_ char *escaped_path_id = NULL;
-
- escaped_path_id = cescape(path_id);
- if (!escaped_path_id)
- return log_oom();
-
- state_file = strjoin("/var/lib/systemd/rfkill/", escaped_path_id, ":", type, NULL);
- } else
- state_file = strjoin("/var/lib/systemd/rfkill/", type, NULL);
-
- if (!state_file)
- return log_oom();
-
- *ret = state_file;
- return 0;
-}
-
-static int load_state(
- int rfkill_fd,
- struct udev *udev,
- const struct rfkill_event *event) {
-
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
- _cleanup_free_ char *state_file = NULL, *value = NULL;
- struct rfkill_event we;
- ssize_t l;
- int b, r;
-
- assert(rfkill_fd >= 0);
- assert(udev);
- assert(event);
-
- if (shall_restore_state() == 0)
- return 0;
-
- r = find_device(udev, event, &device);
- if (r < 0)
- return r;
-
- r = determine_state_file(udev, event, device, &state_file);
- if (r < 0)
- return r;
-
- r = read_one_line_file(state_file, &value);
- if (r == -ENOENT) {
- /* No state file? Then save the current state */
-
- r = write_string_file(state_file, one_zero(event->soft), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
- if (r < 0)
- return log_error_errno(r, "Failed to write state file %s: %m", state_file);
-
- log_debug("Saved state '%s' to %s.", one_zero(event->soft), state_file);
- return 0;
- }
- if (r < 0)
- return log_error_errno(r, "Failed to read state file %s: %m", state_file);
-
- b = parse_boolean(value);
- if (b < 0)
- return log_error_errno(b, "Failed to parse state file %s: %m", state_file);
-
- we = (struct rfkill_event) {
- .op = RFKILL_OP_CHANGE,
- .idx = event->idx,
- .soft = b,
- };
-
- l = write(rfkill_fd, &we, sizeof(we));
- if (l < 0)
- return log_error_errno(errno, "Failed to restore rfkill state for %i: %m", event->idx);
- if (l != sizeof(we)) {
- log_error("Couldn't write rfkill event structure, too short.");
- return -EIO;
- }
-
- log_debug("Loaded state '%s' from %s.", one_zero(b), state_file);
- return 0;
-}
-
-static int save_state(
- int rfkill_fd,
- struct udev *udev,
- const struct rfkill_event *event) {
-
- _cleanup_udev_device_unref_ struct udev_device *device = NULL;
- _cleanup_free_ char *state_file = NULL;
- int r;
-
- assert(rfkill_fd >= 0);
- assert(udev);
- assert(event);
-
- r = find_device(udev, event, &device);
- if (r < 0)
- return r;
-
- r = determine_state_file(udev, event, device, &state_file);
- if (r < 0)
- return r;
-
- r = write_string_file(state_file, one_zero(event->soft), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC);
- if (r < 0)
- return log_error_errno(r, "Failed to write state file %s: %m", state_file);
-
- log_debug("Saved state '%s' to %s.", one_zero(event->soft), state_file);
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_udev_unref_ struct udev *udev = NULL;
- _cleanup_close_ int rfkill_fd = -1;
- bool ready = false;
- int r, n;
-
- if (argc > 1) {
- log_error("This program requires no arguments.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- udev = udev_new();
- if (!udev) {
- r = log_oom();
- goto finish;
- }
-
- r = mkdir_p("/var/lib/systemd/rfkill", 0755);
- if (r < 0) {
- log_error_errno(r, "Failed to create rfkill directory: %m");
- goto finish;
- }
-
- n = sd_listen_fds(false);
- if (n < 0) {
- r = log_error_errno(n, "Failed to determine whether we got any file descriptors passed: %m");
- goto finish;
- }
- if (n > 1) {
- log_error("Got too many file descriptors.");
- r = -EINVAL;
- goto finish;
- }
-
- if (n == 0) {
- rfkill_fd = open("/dev/rfkill", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
- if (rfkill_fd < 0) {
- if (errno == ENOENT) {
- log_debug_errno(errno, "Missing rfkill subsystem, or no device present, exiting.");
- r = 0;
- goto finish;
- }
-
- r = log_error_errno(errno, "Failed to open /dev/rfkill: %m");
- goto finish;
- }
- } else {
- rfkill_fd = SD_LISTEN_FDS_START;
-
- r = fd_nonblock(rfkill_fd, 1);
- if (r < 0) {
- log_error_errno(r, "Failed to make /dev/rfkill socket non-blocking: %m");
- goto finish;
- }
- }
-
- for (;;) {
- struct rfkill_event event;
- const char *type;
- ssize_t l;
-
- l = read(rfkill_fd, &event, sizeof(event));
- if (l < 0) {
- if (errno == EAGAIN) {
-
- if (!ready) {
- /* Notify manager that we are
- * now finished with
- * processing whatever was
- * queued */
- (void) sd_notify(false, "READY=1");
- ready = true;
- }
-
- /* Hang around for a bit, maybe there's more coming */
-
- r = fd_wait_for_event(rfkill_fd, POLLIN, EXIT_USEC);
- if (r == -EINTR)
- continue;
- if (r < 0) {
- log_error_errno(r, "Failed to poll() on device: %m");
- goto finish;
- }
- if (r > 0)
- continue;
-
- log_debug("All events read and idle, exiting.");
- break;
- }
-
- log_error_errno(errno, "Failed to read from /dev/rfkill: %m");
- }
-
- if (l != RFKILL_EVENT_SIZE_V1) {
- log_error("Read event structure of invalid size.");
- r = -EIO;
- goto finish;
- }
-
- type = rfkill_type_to_string(event.type);
- if (!type) {
- log_debug("An rfkill device of unknown type %i discovered, ignoring.", event.type);
- continue;
- }
-
- switch (event.op) {
-
- case RFKILL_OP_ADD:
- log_debug("A new rfkill device has been added with index %i and type %s.", event.idx, type);
- (void) load_state(rfkill_fd, udev, &event);
- break;
-
- case RFKILL_OP_DEL:
- log_debug("An rfkill device has been removed with index %i and type %s", event.idx, type);
- break;
-
- case RFKILL_OP_CHANGE:
- log_debug("An rfkill device has changed state with index %i and type %s", event.idx, type);
- (void) save_state(rfkill_fd, udev, &event);
- break;
-
- default:
- log_debug("Unknown event %i from /dev/rfkill for index %i and type %s, ignoring.", event.op, event.idx, type);
- break;
- }
- }
-
- r = 0;
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-sleep/Makefile b/src/grp-initutils/systemd-sleep/Makefile
deleted file mode 100644
index 6097d09f88..0000000000
--- a/src/grp-initutils/systemd-sleep/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-rootlibexec_PROGRAMS += systemd-sleep
-systemd_sleep_SOURCES = \
- src/sleep/sleep.c
-
-systemd_sleep_LDADD = \
- libshared.la
-
-sd.CPPFLAGS += -DSYSTEM_SLEEP_PATH=\"$(systemsleepdir)\"
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-sleep/sleep.c b/src/grp-initutils/systemd-sleep/sleep.c
deleted file mode 100644
index e9e84bc893..0000000000
--- a/src/grp-initutils/systemd-sleep/sleep.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2012 Lennart Poettering
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <stdio.h>
-
-#include <systemd/sd-messages.h>
-
-#include "basic/def.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/log.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/util.h"
-#include "shared/sleep-config.h"
-
-static char* arg_verb = NULL;
-
-static int write_mode(char **modes) {
- int r = 0;
- char **mode;
-
- STRV_FOREACH(mode, modes) {
- int k;
-
- k = write_string_file("/sys/power/disk", *mode, 0);
- if (k == 0)
- return 0;
-
- log_debug_errno(k, "Failed to write '%s' to /sys/power/disk: %m",
- *mode);
- if (r == 0)
- r = k;
- }
-
- if (r < 0)
- log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");
-
- return r;
-}
-
-static int write_state(FILE **f, char **states) {
- char **state;
- int r = 0;
-
- STRV_FOREACH(state, states) {
- int k;
-
- k = write_string_stream(*f, *state, true);
- if (k == 0)
- return 0;
- log_debug_errno(k, "Failed to write '%s' to /sys/power/state: %m",
- *state);
- if (r == 0)
- r = k;
-
- fclose(*f);
- *f = fopen("/sys/power/state", "we");
- if (!*f)
- return log_error_errno(errno, "Failed to open /sys/power/state: %m");
- }
-
- return r;
-}
-
-static int execute(char **modes, char **states) {
-
- char *arguments[] = {
- NULL,
- (char*) "pre",
- arg_verb,
- NULL
- };
- static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
-
- int r;
- _cleanup_fclose_ FILE *f = NULL;
-
- /* This file is opened first, so that if we hit an error,
- * we can abort before modifying any state. */
- f = fopen("/sys/power/state", "we");
- if (!f)
- return log_error_errno(errno, "Failed to open /sys/power/state: %m");
-
- /* Configure the hibernation mode */
- r = write_mode(modes);
- if (r < 0)
- return r;
-
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
-
- log_struct(LOG_INFO,
- LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_START),
- LOG_MESSAGE("Suspending system..."),
- "SLEEP=%s", arg_verb,
- NULL);
-
- r = write_state(&f, states);
- if (r < 0)
- return r;
-
- log_struct(LOG_INFO,
- LOG_MESSAGE_ID(SD_MESSAGE_SLEEP_STOP),
- LOG_MESSAGE("System resumed."),
- "SLEEP=%s", arg_verb,
- NULL);
-
- arguments[1] = (char*) "post";
- execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments);
-
- return r;
-}
-
-static void help(void) {
- printf("%s COMMAND\n\n"
- "Suspend the system, hibernate the system, or both.\n\n"
- "Commands:\n"
- " -h --help Show this help and exit\n"
- " --version Print version string and exit\n"
- " suspend Suspend the system\n"
- " hibernate Hibernate the system\n"
- " hybrid-sleep Both hibernate and suspend the system\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- {}
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
- switch(c) {
- case 'h':
- help();
- return 0; /* done */
-
- case ARG_VERSION:
- return version();
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (argc - optind != 1) {
- log_error("Usage: %s COMMAND",
- program_invocation_short_name);
- return -EINVAL;
- }
-
- arg_verb = argv[optind];
-
- if (!streq(arg_verb, "suspend") &&
- !streq(arg_verb, "hibernate") &&
- !streq(arg_verb, "hybrid-sleep")) {
- log_error("Unknown command '%s'.", arg_verb);
- return -EINVAL;
- }
-
- return 1 /* work to do */;
-}
-
-int main(int argc, char *argv[]) {
- _cleanup_strv_free_ char **modes = NULL, **states = NULL;
- int r;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- r = parse_sleep_config(arg_verb, &modes, &states);
- if (r < 0)
- goto finish;
-
- r = execute(modes, states);
-
-finish:
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-sysctl/50-default.sysctl b/src/grp-initutils/systemd-sysctl/50-default.sysctl
deleted file mode 100644
index def151bb84..0000000000
--- a/src/grp-initutils/systemd-sysctl/50-default.sysctl
+++ /dev/null
@@ -1,40 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-# See sysctl.d(5) and core(5) for for documentation.
-
-# To override settings in this file, create a local file in /etc
-# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
-# there.
-
-# System Request functionality of the kernel (SYNC)
-#
-# Use kernel.sysrq = 1 to allow all keys.
-# See http://fedoraproject.org/wiki/QA/Sysrq for a list of values and keys.
-kernel.sysrq = 16
-
-# Append the PID to the core filename
-kernel.core_uses_pid = 1
-
-# Source route verification
-net.ipv4.conf.default.rp_filter = 1
-net.ipv4.conf.all.rp_filter = 1
-
-# Do not accept source routing
-net.ipv4.conf.default.accept_source_route = 0
-net.ipv4.conf.all.accept_source_route = 0
-
-# Promote secondary addresses when the primary address is removed
-net.ipv4.conf.default.promote_secondaries = 1
-net.ipv4.conf.all.promote_secondaries = 1
-
-# Fair Queue CoDel packet scheduler to fight bufferbloat
-net.core.default_qdisc = fq_codel
-
-# Enable hard and soft link protection
-fs.protected_hardlinks = 1
-fs.protected_symlinks = 1
diff --git a/src/grp-initutils/systemd-sysctl/Makefile b/src/grp-initutils/systemd-sysctl/Makefile
deleted file mode 100644
index 3af80e7bef..0000000000
--- a/src/grp-initutils/systemd-sysctl/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-rootlibexec_PROGRAMS += systemd-sysctl
-systemd_sysctl_SOURCES = \
- src/sysctl/sysctl.c
-
-systemd_sysctl_LDADD = \
- libshared.la
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-sysctl/sysctl.c b/src/grp-initutils/systemd-sysctl/sysctl.c
deleted file mode 100644
index c44aa0aabb..0000000000
--- a/src/grp-initutils/systemd-sysctl/sysctl.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "basic/conf-files.h"
-#include "basic/def.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/hashmap.h"
-#include "basic/log.h"
-#include "basic/path-util.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/util.h"
-#include "shared/sysctl-util.h"
-
-static char **arg_prefixes = NULL;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysctl.d");
-
-static int apply_all(Hashmap *sysctl_options) {
- char *property, *value;
- Iterator i;
- int r = 0;
-
- HASHMAP_FOREACH_KEY(value, property, sysctl_options, i) {
- int k;
-
- k = sysctl_write(property, value);
- if (k < 0) {
- log_full_errno(k == -ENOENT ? LOG_INFO : LOG_WARNING, k,
- "Couldn't write '%s' to '%s', ignoring: %m", value, property);
-
- if (r == 0 && k != -ENOENT)
- r = k;
- }
- }
-
- return r;
-}
-
-static int parse_file(Hashmap *sysctl_options, const char *path, bool ignore_enoent) {
- _cleanup_fclose_ FILE *f = NULL;
- int r;
-
- assert(path);
-
- r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
- if (r < 0) {
- if (ignore_enoent && r == -ENOENT)
- return 0;
-
- return log_error_errno(r, "Failed to open file '%s', ignoring: %m", path);
- }
-
- log_debug("Parsing %s", path);
- while (!feof(f)) {
- char l[LINE_MAX], *p, *value, *new_value, *property, *existing;
- void *v;
- int k;
-
- if (!fgets(l, sizeof(l), f)) {
- if (feof(f))
- break;
-
- return log_error_errno(errno, "Failed to read file '%s', ignoring: %m", path);
- }
-
- p = strstrip(l);
- if (!*p)
- continue;
-
- if (strchr(COMMENTS "\n", *p))
- continue;
-
- value = strchr(p, '=');
- if (!value) {
- log_error("Line is not an assignment in file '%s': %s", path, value);
-
- if (r == 0)
- r = -EINVAL;
- continue;
- }
-
- *value = 0;
- value++;
-
- p = sysctl_normalize(strstrip(p));
- value = strstrip(value);
-
- if (!strv_isempty(arg_prefixes)) {
- char **i, *t;
- STRV_FOREACH(i, arg_prefixes) {
- t = path_startswith(*i, "/proc/sys/");
- if (t == NULL)
- t = *i;
- if (path_startswith(p, t))
- goto found;
- }
- /* not found */
- continue;
- }
-
-found:
- existing = hashmap_get2(sysctl_options, p, &v);
- if (existing) {
- if (streq(value, existing))
- continue;
-
- log_debug("Overwriting earlier assignment of %s in file '%s'.", p, path);
- free(hashmap_remove(sysctl_options, p));
- free(v);
- }
-
- property = strdup(p);
- if (!property)
- return log_oom();
-
- new_value = strdup(value);
- if (!new_value) {
- free(property);
- return log_oom();
- }
-
- k = hashmap_put(sysctl_options, property, new_value);
- if (k < 0) {
- log_error_errno(k, "Failed to add sysctl variable %s to hashmap: %m", property);
- free(property);
- free(new_value);
- return k;
- }
- }
-
- return r;
-}
-
-static void help(void) {
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Applies kernel sysctl settings.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --prefix=PATH Only apply rules with the specified prefix\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_PREFIX
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "prefix", required_argument, NULL, ARG_PREFIX },
- {}
- };
-
- int c;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_PREFIX: {
- char *p;
-
- /* We used to require people to specify absolute paths
- * in /proc/sys in the past. This is kinda useless, but
- * we need to keep compatibility. We now support any
- * sysctl name available. */
- sysctl_normalize(optarg);
-
- if (startswith(optarg, "/proc/sys"))
- p = strdup(optarg);
- else
- p = strappend("/proc/sys/", optarg);
- if (!p)
- return log_oom();
-
- if (strv_consume(&arg_prefixes, p) < 0)
- return log_oom();
-
- break;
- }
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
- int r = 0, k;
- Hashmap *sysctl_options;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- sysctl_options = hashmap_new(&string_hash_ops);
- if (!sysctl_options) {
- r = log_oom();
- goto finish;
- }
-
- r = 0;
-
- if (argc > optind) {
- int i;
-
- for (i = optind; i < argc; i++) {
- k = parse_file(sysctl_options, argv[i], false);
- if (k < 0 && r == 0)
- r = k;
- }
- } else {
- _cleanup_strv_free_ char **files = NULL;
- char **f;
-
- r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to enumerate sysctl.d files: %m");
- goto finish;
- }
-
- STRV_FOREACH(f, files) {
- k = parse_file(sysctl_options, *f, true);
- if (k < 0 && r == 0)
- r = k;
- }
- }
-
- k = apply_all(sysctl_options);
- if (k < 0 && r == 0)
- r = k;
-
-finish:
- hashmap_free_free_free(sysctl_options);
- strv_free(arg_prefixes);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-sysusers/Makefile b/src/grp-initutils/systemd-sysusers/Makefile
deleted file mode 100644
index 4753ca75d0..0000000000
--- a/src/grp-initutils/systemd-sysusers/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_SYSUSERS),)
-systemd_sysusers_SOURCES = \
- src/sysusers/sysusers.c
-
-systemd_sysusers_LDADD = \
- libshared.la
-
-rootbin_PROGRAMS += \
- systemd-sysusers
-
-nodist_systemunit_DATA += \
- units/systemd-sysusers.service
-
-SYSINIT_TARGET_WANTS += \
- systemd-sysusers.service
-
-nodist_sysusers_DATA = \
- sysusers.d/systemd.conf \
- sysusers.d/basic.conf
-
-ifneq ($(HAVE_REMOTE),)
-nodist_sysusers_DATA += \
- sysusers.d/systemd-remote.conf
-endif # HAVE_REMOTE
-
-INSTALL_DIRS += \
- $(sysusersdir)
-endif # ENABLE_SYSUSERS
-
-EXTRA_DIST += \
- units/systemd-sysusers.service.in \
- sysusers.d/systemd.conf.m4 \
- sysusers.d/systemd-remote.conf.m4 \
- sysusers.d/basic.conf.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-sysusers/basic.sysusers.in b/src/grp-initutils/systemd-sysusers/basic.sysusers.in
deleted file mode 100644
index b2dc5ebd4f..0000000000
--- a/src/grp-initutils/systemd-sysusers/basic.sysusers.in
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-# The superuser
-u root 0 "Super User" /root
-
-# The nobody user for NFS file systems
-u nobody 65534 "Nobody" -
-
-# Administrator group: can *see* more than normal users
-g adm - - -
-
-# Administrator group: can *do* more than normal users
-g wheel - - -
-
-# Access to certain kernel and userspace facilities
-g kmem - - -
-g tty @TTY_GID@ - -
-g utmp - - -
-
-# Hardware access groups
-g audio - - -
-g cdrom - - -
-g dialout - - -
-g disk - - -
-g input - - -
-g lp - - -
-g tape - - -
-g video - - -
-
-# Default group for normal users
-g users - - -
diff --git a/src/grp-initutils/systemd-sysusers/sysusers.c b/src/grp-initutils/systemd-sysusers/sysusers.c
deleted file mode 100644
index a71d777720..0000000000
--- a/src/grp-initutils/systemd-sysusers/sysusers.c
+++ /dev/null
@@ -1,1919 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-#include <grp.h>
-#include <gshadow.h>
-#include <pwd.h>
-#include <shadow.h>
-#include <utmp.h>
-
-#include "basic/alloc-util.h"
-#include "basic/conf-files.h"
-#include "basic/copy.h"
-#include "basic/def.h"
-#include "basic/fd-util.h"
-#include "basic/fileio-label.h"
-#include "basic/formats-util.h"
-#include "basic/hashmap.h"
-#include "basic/path-util.h"
-#include "basic/selinux-util.h"
-#include "basic/smack-util.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/user-util.h"
-#include "basic/utf8.h"
-#include "basic/util.h"
-#include "shared/specifier.h"
-#include "shared/uid-range.h"
-
-typedef enum ItemType {
- ADD_USER = 'u',
- ADD_GROUP = 'g',
- ADD_MEMBER = 'm',
- ADD_RANGE = 'r',
-} ItemType;
-typedef struct Item {
- ItemType type;
-
- char *name;
- char *uid_path;
- char *gid_path;
- char *description;
- char *home;
-
- gid_t gid;
- uid_t uid;
-
- bool gid_set:1;
- bool uid_set:1;
-
- bool todo_user:1;
- bool todo_group:1;
-} Item;
-
-static char *arg_root = NULL;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d");
-
-static Hashmap *users = NULL, *groups = NULL;
-static Hashmap *todo_uids = NULL, *todo_gids = NULL;
-static Hashmap *members = NULL;
-
-static Hashmap *database_uid = NULL, *database_user = NULL;
-static Hashmap *database_gid = NULL, *database_group = NULL;
-
-static uid_t search_uid = UID_INVALID;
-static UidRange *uid_range = NULL;
-static unsigned n_uid_range = 0;
-
-static int load_user_database(void) {
- _cleanup_fclose_ FILE *f = NULL;
- const char *passwd_path;
- struct passwd *pw;
- int r;
-
- passwd_path = prefix_roota(arg_root, "/etc/passwd");
- f = fopen(passwd_path, "re");
- if (!f)
- return errno == ENOENT ? 0 : -errno;
-
- r = hashmap_ensure_allocated(&database_user, &string_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&database_uid, NULL);
- if (r < 0)
- return r;
-
- errno = 0;
- while ((pw = fgetpwent(f))) {
- char *n;
- int k, q;
-
- n = strdup(pw->pw_name);
- if (!n)
- return -ENOMEM;
-
- k = hashmap_put(database_user, n, UID_TO_PTR(pw->pw_uid));
- if (k < 0 && k != -EEXIST) {
- free(n);
- return k;
- }
-
- q = hashmap_put(database_uid, UID_TO_PTR(pw->pw_uid), n);
- if (q < 0 && q != -EEXIST) {
- if (k < 0)
- free(n);
- return q;
- }
-
- if (q < 0 && k < 0)
- free(n);
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
-
- return 0;
-}
-
-static int load_group_database(void) {
- _cleanup_fclose_ FILE *f = NULL;
- const char *group_path;
- struct group *gr;
- int r;
-
- group_path = prefix_roota(arg_root, "/etc/group");
- f = fopen(group_path, "re");
- if (!f)
- return errno == ENOENT ? 0 : -errno;
-
- r = hashmap_ensure_allocated(&database_group, &string_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&database_gid, NULL);
- if (r < 0)
- return r;
-
- errno = 0;
- while ((gr = fgetgrent(f))) {
- char *n;
- int k, q;
-
- n = strdup(gr->gr_name);
- if (!n)
- return -ENOMEM;
-
- k = hashmap_put(database_group, n, GID_TO_PTR(gr->gr_gid));
- if (k < 0 && k != -EEXIST) {
- free(n);
- return k;
- }
-
- q = hashmap_put(database_gid, GID_TO_PTR(gr->gr_gid), n);
- if (q < 0 && q != -EEXIST) {
- if (k < 0)
- free(n);
- return q;
- }
-
- if (q < 0 && k < 0)
- free(n);
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
-
- return 0;
-}
-
-static int make_backup(const char *target, const char *x) {
- _cleanup_close_ int src = -1;
- _cleanup_fclose_ FILE *dst = NULL;
- char *backup, *temp;
- struct timespec ts[2];
- struct stat st;
- int r;
-
- src = open(x, O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (src < 0) {
- if (errno == ENOENT) /* No backup necessary... */
- return 0;
-
- return -errno;
- }
-
- if (fstat(src, &st) < 0)
- return -errno;
-
- r = fopen_temporary_label(target, x, &dst, &temp);
- if (r < 0)
- return r;
-
- r = copy_bytes(src, fileno(dst), (uint64_t) -1, true);
- if (r < 0)
- goto fail;
-
- /* Don't fail on chmod() or chown(). If it stays owned by us
- * and/or unreadable by others, then it isn't too bad... */
-
- backup = strjoina(x, "-");
-
- /* Copy over the access mask */
- if (fchmod(fileno(dst), st.st_mode & 07777) < 0)
- log_warning_errno(errno, "Failed to change mode on %s: %m", backup);
-
- if (fchown(fileno(dst), st.st_uid, st.st_gid)< 0)
- log_warning_errno(errno, "Failed to change ownership of %s: %m", backup);
-
- ts[0] = st.st_atim;
- ts[1] = st.st_mtim;
- if (futimens(fileno(dst), ts) < 0)
- log_warning_errno(errno, "Failed to fix access and modification time of %s: %m", backup);
-
- if (rename(temp, backup) < 0)
- goto fail;
-
- return 0;
-
-fail:
- unlink(temp);
- return r;
-}
-
-static int putgrent_with_members(const struct group *gr, FILE *group) {
- char **a;
-
- assert(gr);
- assert(group);
-
- a = hashmap_get(members, gr->gr_name);
- if (a) {
- _cleanup_strv_free_ char **l = NULL;
- bool added = false;
- char **i;
-
- l = strv_copy(gr->gr_mem);
- if (!l)
- return -ENOMEM;
-
- STRV_FOREACH(i, a) {
- if (strv_find(l, *i))
- continue;
-
- if (strv_extend(&l, *i) < 0)
- return -ENOMEM;
-
- added = true;
- }
-
- if (added) {
- struct group t;
-
- strv_uniq(l);
- strv_sort(l);
-
- t = *gr;
- t.gr_mem = l;
-
- errno = 0;
- if (putgrent(&t, group) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 1;
- }
- }
-
- errno = 0;
- if (putgrent(gr, group) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 0;
-}
-
-static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) {
- char **a;
-
- assert(sg);
- assert(gshadow);
-
- a = hashmap_get(members, sg->sg_namp);
- if (a) {
- _cleanup_strv_free_ char **l = NULL;
- bool added = false;
- char **i;
-
- l = strv_copy(sg->sg_mem);
- if (!l)
- return -ENOMEM;
-
- STRV_FOREACH(i, a) {
- if (strv_find(l, *i))
- continue;
-
- if (strv_extend(&l, *i) < 0)
- return -ENOMEM;
-
- added = true;
- }
-
- if (added) {
- struct sgrp t;
-
- strv_uniq(l);
- strv_sort(l);
-
- t = *sg;
- t.sg_mem = l;
-
- errno = 0;
- if (putsgent(&t, gshadow) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 1;
- }
- }
-
- errno = 0;
- if (putsgent(sg, gshadow) != 0)
- return errno > 0 ? -errno : -EIO;
-
- return 0;
-}
-
-static int sync_rights(FILE *from, FILE *to) {
- struct stat st;
-
- if (fstat(fileno(from), &st) < 0)
- return -errno;
-
- if (fchmod(fileno(to), st.st_mode & 07777) < 0)
- return -errno;
-
- if (fchown(fileno(to), st.st_uid, st.st_gid) < 0)
- return -errno;
-
- return 0;
-}
-
-static int rename_and_apply_smack(const char *temp_path, const char *dest_path) {
- int r = 0;
- if (rename(temp_path, dest_path) < 0)
- return -errno;
-
-#ifdef SMACK_RUN_LABEL
- r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL);
- if (r < 0)
- return r;
-#endif
- return r;
-}
-
-static int write_files(void) {
-
- _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL;
- _cleanup_free_ char *passwd_tmp = NULL, *group_tmp = NULL, *shadow_tmp = NULL, *gshadow_tmp = NULL;
- const char *passwd_path = NULL, *group_path = NULL, *shadow_path = NULL, *gshadow_path = NULL;
- bool group_changed = false;
- Iterator iterator;
- Item *i;
- int r;
-
- if (hashmap_size(todo_gids) > 0 || hashmap_size(members) > 0) {
- _cleanup_fclose_ FILE *original = NULL;
-
- /* First we update the actual group list file */
- group_path = prefix_roota(arg_root, "/etc/group");
- r = fopen_temporary_label("/etc/group", group_path, &group, &group_tmp);
- if (r < 0)
- goto finish;
-
- original = fopen(group_path, "re");
- if (original) {
- struct group *gr;
-
- r = sync_rights(original, group);
- if (r < 0)
- goto finish;
-
- errno = 0;
- while ((gr = fgetgrent(original))) {
- /* Safety checks against name and GID
- * collisions. Normally, this should
- * be unnecessary, but given that we
- * look at the entries anyway here,
- * let's make an extra verification
- * step that we don't generate
- * duplicate entries. */
-
- i = hashmap_get(groups, gr->gr_name);
- if (i && i->todo_group) {
- log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name);
- r = -EEXIST;
- goto finish;
- }
-
- if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) {
- log_error("%s: Detected collision for GID " GID_FMT ".", group_path, gr->gr_gid);
- r = -EEXIST;
- goto finish;
- }
-
- r = putgrent_with_members(gr, group);
- if (r < 0)
- goto finish;
- if (r > 0)
- group_changed = true;
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT)) {
- r = -errno;
- goto finish;
- }
-
- } else if (errno != ENOENT) {
- r = -errno;
- goto finish;
- } else if (fchmod(fileno(group), 0644) < 0) {
- r = -errno;
- goto finish;
- }
-
- HASHMAP_FOREACH(i, todo_gids, iterator) {
- struct group n = {
- .gr_name = i->name,
- .gr_gid = i->gid,
- .gr_passwd = (char*) "x",
- };
-
- r = putgrent_with_members(&n, group);
- if (r < 0)
- goto finish;
-
- group_changed = true;
- }
-
- r = fflush_and_check(group);
- if (r < 0)
- goto finish;
-
- if (original) {
- fclose(original);
- original = NULL;
- }
-
- /* OK, now also update the shadow file for the group list */
- gshadow_path = prefix_roota(arg_root, "/etc/gshadow");
- r = fopen_temporary_label("/etc/gshadow", gshadow_path, &gshadow, &gshadow_tmp);
- if (r < 0)
- goto finish;
-
- original = fopen(gshadow_path, "re");
- if (original) {
- struct sgrp *sg;
-
- r = sync_rights(original, gshadow);
- if (r < 0)
- goto finish;
-
- errno = 0;
- while ((sg = fgetsgent(original))) {
-
- i = hashmap_get(groups, sg->sg_namp);
- if (i && i->todo_group) {
- log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp);
- r = -EEXIST;
- goto finish;
- }
-
- r = putsgent_with_members(sg, gshadow);
- if (r < 0)
- goto finish;
- if (r > 0)
- group_changed = true;
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT)) {
- r = -errno;
- goto finish;
- }
-
- } else if (errno != ENOENT) {
- r = -errno;
- goto finish;
- } else if (fchmod(fileno(gshadow), 0000) < 0) {
- r = -errno;
- goto finish;
- }
-
- HASHMAP_FOREACH(i, todo_gids, iterator) {
- struct sgrp n = {
- .sg_namp = i->name,
- .sg_passwd = (char*) "!!",
- };
-
- r = putsgent_with_members(&n, gshadow);
- if (r < 0)
- goto finish;
-
- group_changed = true;
- }
-
- r = fflush_and_check(gshadow);
- if (r < 0)
- goto finish;
- }
-
- if (hashmap_size(todo_uids) > 0) {
- _cleanup_fclose_ FILE *original = NULL;
- long lstchg;
-
- /* First we update the user database itself */
- passwd_path = prefix_roota(arg_root, "/etc/passwd");
- r = fopen_temporary_label("/etc/passwd", passwd_path, &passwd, &passwd_tmp);
- if (r < 0)
- goto finish;
-
- original = fopen(passwd_path, "re");
- if (original) {
- struct passwd *pw;
-
- r = sync_rights(original, passwd);
- if (r < 0)
- goto finish;
-
- errno = 0;
- while ((pw = fgetpwent(original))) {
-
- i = hashmap_get(users, pw->pw_name);
- if (i && i->todo_user) {
- log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name);
- r = -EEXIST;
- goto finish;
- }
-
- if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) {
- log_error("%s: Detected collision for UID " UID_FMT ".", passwd_path, pw->pw_uid);
- r = -EEXIST;
- goto finish;
- }
-
- errno = 0;
- if (putpwent(pw, passwd) < 0) {
- r = errno ? -errno : -EIO;
- goto finish;
- }
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT)) {
- r = -errno;
- goto finish;
- }
-
- } else if (errno != ENOENT) {
- r = -errno;
- goto finish;
- } else if (fchmod(fileno(passwd), 0644) < 0) {
- r = -errno;
- goto finish;
- }
-
- HASHMAP_FOREACH(i, todo_uids, iterator) {
- struct passwd n = {
- .pw_name = i->name,
- .pw_uid = i->uid,
- .pw_gid = i->gid,
- .pw_gecos = i->description,
-
- /* "x" means the password is stored in
- * the shadow file */
- .pw_passwd = (char*) "x",
-
- /* We default to the root directory as home */
- .pw_dir = i->home ? i->home : (char*) "/",
-
- /* Initialize the shell to nologin,
- * with one exception: for root we
- * patch in something special */
- .pw_shell = i->uid == 0 ? (char*) "/bin/sh" : (char*) "/sbin/nologin",
- };
-
- errno = 0;
- if (putpwent(&n, passwd) != 0) {
- r = errno ? -errno : -EIO;
- goto finish;
- }
- }
-
- r = fflush_and_check(passwd);
- if (r < 0)
- goto finish;
-
- if (original) {
- fclose(original);
- original = NULL;
- }
-
- /* The we update the shadow database */
- shadow_path = prefix_roota(arg_root, "/etc/shadow");
- r = fopen_temporary_label("/etc/shadow", shadow_path, &shadow, &shadow_tmp);
- if (r < 0)
- goto finish;
-
- lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
-
- original = fopen(shadow_path, "re");
- if (original) {
- struct spwd *sp;
-
- r = sync_rights(original, shadow);
- if (r < 0)
- goto finish;
-
- errno = 0;
- while ((sp = fgetspent(original))) {
-
- i = hashmap_get(users, sp->sp_namp);
- if (i && i->todo_user) {
- /* we will update the existing entry */
- sp->sp_lstchg = lstchg;
-
- /* only the /etc/shadow stage is left, so we can
- * safely remove the item from the todo set */
- i->todo_user = false;
- hashmap_remove(todo_uids, UID_TO_PTR(i->uid));
- }
-
- errno = 0;
- if (putspent(sp, shadow) < 0) {
- r = errno ? -errno : -EIO;
- goto finish;
- }
-
- errno = 0;
- }
- if (!IN_SET(errno, 0, ENOENT)) {
- r = -errno;
- goto finish;
- }
- } else if (errno != ENOENT) {
- r = -errno;
- goto finish;
- } else if (fchmod(fileno(shadow), 0000) < 0) {
- r = -errno;
- goto finish;
- }
-
- HASHMAP_FOREACH(i, todo_uids, iterator) {
- struct spwd n = {
- .sp_namp = i->name,
- .sp_pwdp = (char*) "!!",
- .sp_lstchg = lstchg,
- .sp_min = -1,
- .sp_max = -1,
- .sp_warn = -1,
- .sp_inact = -1,
- .sp_expire = -1,
- .sp_flag = (unsigned long) -1, /* this appears to be what everybody does ... */
- };
-
- errno = 0;
- if (putspent(&n, shadow) != 0) {
- r = errno ? -errno : -EIO;
- goto finish;
- }
- }
-
- r = fflush_and_check(shadow);
- if (r < 0)
- goto finish;
- }
-
- /* Make a backup of the old files */
- if (group_changed) {
- if (group) {
- r = make_backup("/etc/group", group_path);
- if (r < 0)
- goto finish;
- }
- if (gshadow) {
- r = make_backup("/etc/gshadow", gshadow_path);
- if (r < 0)
- goto finish;
- }
- }
-
- if (passwd) {
- r = make_backup("/etc/passwd", passwd_path);
- if (r < 0)
- goto finish;
- }
- if (shadow) {
- r = make_backup("/etc/shadow", shadow_path);
- if (r < 0)
- goto finish;
- }
-
- /* And make the new files count */
- if (group_changed) {
- if (group) {
- r = rename_and_apply_smack(group_tmp, group_path);
- if (r < 0)
- goto finish;
-
- group_tmp = mfree(group_tmp);
- }
- if (gshadow) {
- r = rename_and_apply_smack(gshadow_tmp, gshadow_path);
- if (r < 0)
- goto finish;
-
- gshadow_tmp = mfree(gshadow_tmp);
- }
- }
-
- if (passwd) {
- r = rename_and_apply_smack(passwd_tmp, passwd_path);
- if (r < 0)
- goto finish;
-
- passwd_tmp = mfree(passwd_tmp);
- }
- if (shadow) {
- r = rename_and_apply_smack(shadow_tmp, shadow_path);
- if (r < 0)
- goto finish;
-
- shadow_tmp = mfree(shadow_tmp);
- }
-
- r = 0;
-
-finish:
- if (passwd_tmp)
- unlink(passwd_tmp);
- if (shadow_tmp)
- unlink(shadow_tmp);
- if (group_tmp)
- unlink(group_tmp);
- if (gshadow_tmp)
- unlink(gshadow_tmp);
-
- return r;
-}
-
-static int uid_is_ok(uid_t uid, const char *name) {
- struct passwd *p;
- struct group *g;
- const char *n;
- Item *i;
-
- /* Let's see if we already have assigned the UID a second time */
- if (hashmap_get(todo_uids, UID_TO_PTR(uid)))
- return 0;
-
- /* Try to avoid using uids that are already used by a group
- * that doesn't have the same name as our new user. */
- i = hashmap_get(todo_gids, GID_TO_PTR(uid));
- if (i && !streq(i->name, name))
- return 0;
-
- /* Let's check the files directly */
- if (hashmap_contains(database_uid, UID_TO_PTR(uid)))
- return 0;
-
- n = hashmap_get(database_gid, GID_TO_PTR(uid));
- if (n && !streq(n, name))
- return 0;
-
- /* Let's also check via NSS, to avoid UID clashes over LDAP and such, just in case */
- if (!arg_root) {
- errno = 0;
- p = getpwuid(uid);
- if (p)
- return 0;
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
-
- errno = 0;
- g = getgrgid((gid_t) uid);
- if (g) {
- if (!streq(g->gr_name, name))
- return 0;
- } else if (!IN_SET(errno, 0, ENOENT))
- return -errno;
- }
-
- return 1;
-}
-
-static int root_stat(const char *p, struct stat *st) {
- const char *fix;
-
- fix = prefix_roota(arg_root, p);
- if (stat(fix, st) < 0)
- return -errno;
-
- return 0;
-}
-
-static int read_id_from_file(Item *i, uid_t *_uid, gid_t *_gid) {
- struct stat st;
- bool found_uid = false, found_gid = false;
- uid_t uid = 0;
- gid_t gid = 0;
-
- assert(i);
-
- /* First, try to get the gid directly */
- if (_gid && i->gid_path && root_stat(i->gid_path, &st) >= 0) {
- gid = st.st_gid;
- found_gid = true;
- }
-
- /* Then, try to get the uid directly */
- if ((_uid || (_gid && !found_gid))
- && i->uid_path
- && root_stat(i->uid_path, &st) >= 0) {
-
- uid = st.st_uid;
- found_uid = true;
-
- /* If we need the gid, but had no success yet, also derive it from the uid path */
- if (_gid && !found_gid) {
- gid = st.st_gid;
- found_gid = true;
- }
- }
-
- /* If that didn't work yet, then let's reuse the gid as uid */
- if (_uid && !found_uid && i->gid_path) {
-
- if (found_gid) {
- uid = (uid_t) gid;
- found_uid = true;
- } else if (root_stat(i->gid_path, &st) >= 0) {
- uid = (uid_t) st.st_gid;
- found_uid = true;
- }
- }
-
- if (_uid) {
- if (!found_uid)
- return 0;
-
- *_uid = uid;
- }
-
- if (_gid) {
- if (!found_gid)
- return 0;
-
- *_gid = gid;
- }
-
- return 1;
-}
-
-static int add_user(Item *i) {
- void *z;
- int r;
-
- assert(i);
-
- /* Check the database directly */
- z = hashmap_get(database_user, i->name);
- if (z) {
- log_debug("User %s already exists.", i->name);
- i->uid = PTR_TO_UID(z);
- i->uid_set = true;
- return 0;
- }
-
- if (!arg_root) {
- struct passwd *p;
-
- /* Also check NSS */
- errno = 0;
- p = getpwnam(i->name);
- if (p) {
- log_debug("User %s already exists.", i->name);
- i->uid = p->pw_uid;
- i->uid_set = true;
-
- r = free_and_strdup(&i->description, p->pw_gecos);
- if (r < 0)
- return log_oom();
-
- return 0;
- }
- if (!IN_SET(errno, 0, ENOENT))
- return log_error_errno(errno, "Failed to check if user %s already exists: %m", i->name);
- }
-
- /* Try to use the suggested numeric uid */
- if (i->uid_set) {
- r = uid_is_ok(i->uid, i->name);
- if (r < 0)
- return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
- if (r == 0) {
- log_debug("Suggested user ID " UID_FMT " for %s already used.", i->uid, i->name);
- i->uid_set = false;
- }
- }
-
- /* If that didn't work, try to read it from the specified path */
- if (!i->uid_set) {
- uid_t c;
-
- if (read_id_from_file(i, &c, NULL) > 0) {
-
- if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c))
- log_debug("User ID " UID_FMT " of file not suitable for %s.", c, i->name);
- else {
- r = uid_is_ok(c, i->name);
- if (r < 0)
- return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
- else if (r > 0) {
- i->uid = c;
- i->uid_set = true;
- } else
- log_debug("User ID " UID_FMT " of file for %s is already used.", c, i->name);
- }
- }
- }
-
- /* Otherwise, try to reuse the group ID */
- if (!i->uid_set && i->gid_set) {
- r = uid_is_ok((uid_t) i->gid, i->name);
- if (r < 0)
- return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
- if (r > 0) {
- i->uid = (uid_t) i->gid;
- i->uid_set = true;
- }
- }
-
- /* And if that didn't work either, let's try to find a free one */
- if (!i->uid_set) {
- for (;;) {
- r = uid_range_next_lower(uid_range, n_uid_range, &search_uid);
- if (r < 0) {
- log_error("No free user ID available for %s.", i->name);
- return r;
- }
-
- r = uid_is_ok(search_uid, i->name);
- if (r < 0)
- return log_error_errno(r, "Failed to verify uid " UID_FMT ": %m", i->uid);
- else if (r > 0)
- break;
- }
-
- i->uid_set = true;
- i->uid = search_uid;
- }
-
- r = hashmap_ensure_allocated(&todo_uids, NULL);
- if (r < 0)
- return log_oom();
-
- r = hashmap_put(todo_uids, UID_TO_PTR(i->uid), i);
- if (r < 0)
- return log_oom();
-
- i->todo_user = true;
- log_info("Creating user %s (%s) with uid " UID_FMT " and gid " GID_FMT ".", i->name, strna(i->description), i->uid, i->gid);
-
- return 0;
-}
-
-static int gid_is_ok(gid_t gid) {
- struct group *g;
- struct passwd *p;
-
- if (hashmap_get(todo_gids, GID_TO_PTR(gid)))
- return 0;
-
- /* Avoid reusing gids that are already used by a different user */
- if (hashmap_get(todo_uids, UID_TO_PTR(gid)))
- return 0;
-
- if (hashmap_contains(database_gid, GID_TO_PTR(gid)))
- return 0;
-
- if (hashmap_contains(database_uid, UID_TO_PTR(gid)))
- return 0;
-
- if (!arg_root) {
- errno = 0;
- g = getgrgid(gid);
- if (g)
- return 0;
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
-
- errno = 0;
- p = getpwuid((uid_t) gid);
- if (p)
- return 0;
- if (!IN_SET(errno, 0, ENOENT))
- return -errno;
- }
-
- return 1;
-}
-
-static int add_group(Item *i) {
- void *z;
- int r;
-
- assert(i);
-
- /* Check the database directly */
- z = hashmap_get(database_group, i->name);
- if (z) {
- log_debug("Group %s already exists.", i->name);
- i->gid = PTR_TO_GID(z);
- i->gid_set = true;
- return 0;
- }
-
- /* Also check NSS */
- if (!arg_root) {
- struct group *g;
-
- errno = 0;
- g = getgrnam(i->name);
- if (g) {
- log_debug("Group %s already exists.", i->name);
- i->gid = g->gr_gid;
- i->gid_set = true;
- return 0;
- }
- if (!IN_SET(errno, 0, ENOENT))
- return log_error_errno(errno, "Failed to check if group %s already exists: %m", i->name);
- }
-
- /* Try to use the suggested numeric gid */
- if (i->gid_set) {
- r = gid_is_ok(i->gid);
- if (r < 0)
- return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
- if (r == 0) {
- log_debug("Suggested group ID " GID_FMT " for %s already used.", i->gid, i->name);
- i->gid_set = false;
- }
- }
-
- /* Try to reuse the numeric uid, if there's one */
- if (!i->gid_set && i->uid_set) {
- r = gid_is_ok((gid_t) i->uid);
- if (r < 0)
- return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
- if (r > 0) {
- i->gid = (gid_t) i->uid;
- i->gid_set = true;
- }
- }
-
- /* If that didn't work, try to read it from the specified path */
- if (!i->gid_set) {
- gid_t c;
-
- if (read_id_from_file(i, NULL, &c) > 0) {
-
- if (c <= 0 || !uid_range_contains(uid_range, n_uid_range, c))
- log_debug("Group ID " GID_FMT " of file not suitable for %s.", c, i->name);
- else {
- r = gid_is_ok(c);
- if (r < 0)
- return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
- else if (r > 0) {
- i->gid = c;
- i->gid_set = true;
- } else
- log_debug("Group ID " GID_FMT " of file for %s already used.", c, i->name);
- }
- }
- }
-
- /* And if that didn't work either, let's try to find a free one */
- if (!i->gid_set) {
- for (;;) {
- /* We look for new GIDs in the UID pool! */
- r = uid_range_next_lower(uid_range, n_uid_range, &search_uid);
- if (r < 0) {
- log_error("No free group ID available for %s.", i->name);
- return r;
- }
-
- r = gid_is_ok(search_uid);
- if (r < 0)
- return log_error_errno(r, "Failed to verify gid " GID_FMT ": %m", i->gid);
- else if (r > 0)
- break;
- }
-
- i->gid_set = true;
- i->gid = search_uid;
- }
-
- r = hashmap_ensure_allocated(&todo_gids, NULL);
- if (r < 0)
- return log_oom();
-
- r = hashmap_put(todo_gids, GID_TO_PTR(i->gid), i);
- if (r < 0)
- return log_oom();
-
- i->todo_group = true;
- log_info("Creating group %s with gid " GID_FMT ".", i->name, i->gid);
-
- return 0;
-}
-
-static int process_item(Item *i) {
- int r;
-
- assert(i);
-
- switch (i->type) {
-
- case ADD_USER:
- r = add_group(i);
- if (r < 0)
- return r;
-
- return add_user(i);
-
- case ADD_GROUP: {
- Item *j;
-
- j = hashmap_get(users, i->name);
- if (j) {
- /* There's already user to be created for this
- * name, let's process that in one step */
-
- if (i->gid_set) {
- j->gid = i->gid;
- j->gid_set = true;
- }
-
- if (i->gid_path) {
- r = free_and_strdup(&j->gid_path, i->gid_path);
- if (r < 0)
- return log_oom();
- }
-
- return 0;
- }
-
- return add_group(i);
- }
-
- default:
- assert_not_reached("Unknown item type");
- }
-}
-
-static void item_free(Item *i) {
-
- if (!i)
- return;
-
- free(i->name);
- free(i->uid_path);
- free(i->gid_path);
- free(i->description);
- free(i);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Item*, item_free);
-
-static int add_implicit(void) {
- char *g, **l;
- Iterator iterator;
- int r;
-
- /* Implicitly create additional users and groups, if they were listed in "m" lines */
-
- HASHMAP_FOREACH_KEY(l, g, members, iterator) {
- Item *i;
- char **m;
-
- i = hashmap_get(groups, g);
- if (!i) {
- _cleanup_(item_freep) Item *j = NULL;
-
- r = hashmap_ensure_allocated(&groups, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- j = new0(Item, 1);
- if (!j)
- return log_oom();
-
- j->type = ADD_GROUP;
- j->name = strdup(g);
- if (!j->name)
- return log_oom();
-
- r = hashmap_put(groups, j->name, j);
- if (r < 0)
- return log_oom();
-
- log_debug("Adding implicit group '%s' due to m line", j->name);
- j = NULL;
- }
-
- STRV_FOREACH(m, l) {
-
- i = hashmap_get(users, *m);
- if (!i) {
- _cleanup_(item_freep) Item *j = NULL;
-
- r = hashmap_ensure_allocated(&users, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- j = new0(Item, 1);
- if (!j)
- return log_oom();
-
- j->type = ADD_USER;
- j->name = strdup(*m);
- if (!j->name)
- return log_oom();
-
- r = hashmap_put(users, j->name, j);
- if (r < 0)
- return log_oom();
-
- log_debug("Adding implicit user '%s' due to m line", j->name);
- j = NULL;
- }
- }
- }
-
- return 0;
-}
-
-static bool item_equal(Item *a, Item *b) {
- assert(a);
- assert(b);
-
- if (a->type != b->type)
- return false;
-
- if (!streq_ptr(a->name, b->name))
- return false;
-
- if (!streq_ptr(a->uid_path, b->uid_path))
- return false;
-
- if (!streq_ptr(a->gid_path, b->gid_path))
- return false;
-
- if (!streq_ptr(a->description, b->description))
- return false;
-
- if (a->uid_set != b->uid_set)
- return false;
-
- if (a->uid_set && a->uid != b->uid)
- return false;
-
- if (a->gid_set != b->gid_set)
- return false;
-
- if (a->gid_set && a->gid != b->gid)
- return false;
-
- if (!streq_ptr(a->home, b->home))
- return false;
-
- return true;
-}
-
-static bool valid_user_group_name(const char *u) {
- const char *i;
- long sz;
-
- if (isempty(u))
- return false;
-
- if (!(u[0] >= 'a' && u[0] <= 'z') &&
- !(u[0] >= 'A' && u[0] <= 'Z') &&
- u[0] != '_')
- return false;
-
- for (i = u+1; *i; i++) {
- if (!(*i >= 'a' && *i <= 'z') &&
- !(*i >= 'A' && *i <= 'Z') &&
- !(*i >= '0' && *i <= '9') &&
- *i != '_' &&
- *i != '-')
- return false;
- }
-
- sz = sysconf(_SC_LOGIN_NAME_MAX);
- assert_se(sz > 0);
-
- if ((size_t) (i-u) > (size_t) sz)
- return false;
-
- if ((size_t) (i-u) > UT_NAMESIZE - 1)
- return false;
-
- return true;
-}
-
-static bool valid_gecos(const char *d) {
-
- if (!d)
- return false;
-
- if (!utf8_is_valid(d))
- return false;
-
- if (string_has_cc(d, NULL))
- return false;
-
- /* Colons are used as field separators, and hence not OK */
- if (strchr(d, ':'))
- return false;
-
- return true;
-}
-
-static bool valid_home(const char *p) {
-
- if (isempty(p))
- return false;
-
- if (!utf8_is_valid(p))
- return false;
-
- if (string_has_cc(p, NULL))
- return false;
-
- if (!path_is_absolute(p))
- return false;
-
- if (!path_is_safe(p))
- return false;
-
- /* Colons are used as field separators, and hence not OK */
- if (strchr(p, ':'))
- return false;
-
- return true;
-}
-
-static int parse_line(const char *fname, unsigned line, const char *buffer) {
-
- static const Specifier specifier_table[] = {
- { 'm', specifier_machine_id, NULL },
- { 'b', specifier_boot_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'v', specifier_kernel_release, NULL },
- {}
- };
-
- _cleanup_free_ char *action = NULL, *name = NULL, *id = NULL, *resolved_name = NULL, *resolved_id = NULL, *description = NULL, *home = NULL;
- _cleanup_(item_freep) Item *i = NULL;
- Item *existing;
- Hashmap *h;
- int r;
- const char *p;
-
- assert(fname);
- assert(line >= 1);
- assert(buffer);
-
- /* Parse columns */
- p = buffer;
- r = extract_many_words(&p, NULL, EXTRACT_QUOTES, &action, &name, &id, &description, &home, NULL);
- if (r < 0) {
- log_error("[%s:%u] Syntax error.", fname, line);
- return r;
- }
- if (r < 2) {
- log_error("[%s:%u] Missing action and name columns.", fname, line);
- return -EINVAL;
- }
- if (!isempty(p)) {
- log_error("[%s:%u] Trailing garbage.", fname, line);
- return -EINVAL;
- }
-
- /* Verify action */
- if (strlen(action) != 1) {
- log_error("[%s:%u] Unknown modifier '%s'", fname, line, action);
- return -EINVAL;
- }
-
- if (!IN_SET(action[0], ADD_USER, ADD_GROUP, ADD_MEMBER, ADD_RANGE)) {
- log_error("[%s:%u] Unknown command command type '%c'.", fname, line, action[0]);
- return -EBADMSG;
- }
-
- /* Verify name */
- if (isempty(name) || streq(name, "-"))
- name = mfree(name);
-
- if (name) {
- r = specifier_printf(name, specifier_table, NULL, &resolved_name);
- if (r < 0) {
- log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, name);
- return r;
- }
-
- if (!valid_user_group_name(resolved_name)) {
- log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_name);
- return -EINVAL;
- }
- }
-
- /* Verify id */
- if (isempty(id) || streq(id, "-"))
- id = mfree(id);
-
- if (id) {
- r = specifier_printf(id, specifier_table, NULL, &resolved_id);
- if (r < 0) {
- log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, name);
- return r;
- }
- }
-
- /* Verify description */
- if (isempty(description) || streq(description, "-"))
- description = mfree(description);
-
- if (description) {
- if (!valid_gecos(description)) {
- log_error("[%s:%u] '%s' is not a valid GECOS field.", fname, line, description);
- return -EINVAL;
- }
- }
-
- /* Verify home */
- if (isempty(home) || streq(home, "-"))
- home = mfree(home);
-
- if (home) {
- if (!valid_home(home)) {
- log_error("[%s:%u] '%s' is not a valid home directory field.", fname, line, home);
- return -EINVAL;
- }
- }
-
- switch (action[0]) {
-
- case ADD_RANGE:
- if (resolved_name) {
- log_error("[%s:%u] Lines of type 'r' don't take a name field.", fname, line);
- return -EINVAL;
- }
-
- if (!resolved_id) {
- log_error("[%s:%u] Lines of type 'r' require a ID range in the third field.", fname, line);
- return -EINVAL;
- }
-
- if (description) {
- log_error("[%s:%u] Lines of type 'r' don't take a GECOS field.", fname, line);
- return -EINVAL;
- }
-
- if (home) {
- log_error("[%s:%u] Lines of type 'r' don't take a home directory field.", fname, line);
- return -EINVAL;
- }
-
- r = uid_range_add_str(&uid_range, &n_uid_range, resolved_id);
- if (r < 0) {
- log_error("[%s:%u] Invalid UID range %s.", fname, line, resolved_id);
- return -EINVAL;
- }
-
- return 0;
-
- case ADD_MEMBER: {
- char **l;
-
- /* Try to extend an existing member or group item */
- if (!name) {
- log_error("[%s:%u] Lines of type 'm' require a user name in the second field.", fname, line);
- return -EINVAL;
- }
-
- if (!resolved_id) {
- log_error("[%s:%u] Lines of type 'm' require a group name in the third field.", fname, line);
- return -EINVAL;
- }
-
- if (!valid_user_group_name(resolved_id)) {
- log_error("[%s:%u] '%s' is not a valid user or group name.", fname, line, resolved_id);
- return -EINVAL;
- }
-
- if (description) {
- log_error("[%s:%u] Lines of type 'm' don't take a GECOS field.", fname, line);
- return -EINVAL;
- }
-
- if (home) {
- log_error("[%s:%u] Lines of type 'm' don't take a home directory field.", fname, line);
- return -EINVAL;
- }
-
- r = hashmap_ensure_allocated(&members, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- l = hashmap_get(members, resolved_id);
- if (l) {
- /* A list for this group name already exists, let's append to it */
- r = strv_push(&l, resolved_name);
- if (r < 0)
- return log_oom();
-
- resolved_name = NULL;
-
- assert_se(hashmap_update(members, resolved_id, l) >= 0);
- } else {
- /* No list for this group name exists yet, create one */
-
- l = new0(char *, 2);
- if (!l)
- return -ENOMEM;
-
- l[0] = resolved_name;
- l[1] = NULL;
-
- r = hashmap_put(members, resolved_id, l);
- if (r < 0) {
- free(l);
- return log_oom();
- }
-
- resolved_id = resolved_name = NULL;
- }
-
- return 0;
- }
-
- case ADD_USER:
- if (!name) {
- log_error("[%s:%u] Lines of type 'u' require a user name in the second field.", fname, line);
- return -EINVAL;
- }
-
- r = hashmap_ensure_allocated(&users, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- i = new0(Item, 1);
- if (!i)
- return log_oom();
-
- if (resolved_id) {
- if (path_is_absolute(resolved_id)) {
- i->uid_path = resolved_id;
- resolved_id = NULL;
-
- path_kill_slashes(i->uid_path);
- } else {
- r = parse_uid(resolved_id, &i->uid);
- if (r < 0) {
- log_error("Failed to parse UID: %s", id);
- return -EBADMSG;
- }
-
- i->uid_set = true;
- }
- }
-
- i->description = description;
- description = NULL;
-
- i->home = home;
- home = NULL;
-
- h = users;
- break;
-
- case ADD_GROUP:
- if (!name) {
- log_error("[%s:%u] Lines of type 'g' require a user name in the second field.", fname, line);
- return -EINVAL;
- }
-
- if (description) {
- log_error("[%s:%u] Lines of type 'g' don't take a GECOS field.", fname, line);
- return -EINVAL;
- }
-
- if (home) {
- log_error("[%s:%u] Lines of type 'g' don't take a home directory field.", fname, line);
- return -EINVAL;
- }
-
- r = hashmap_ensure_allocated(&groups, &string_hash_ops);
- if (r < 0)
- return log_oom();
-
- i = new0(Item, 1);
- if (!i)
- return log_oom();
-
- if (resolved_id) {
- if (path_is_absolute(resolved_id)) {
- i->gid_path = resolved_id;
- resolved_id = NULL;
-
- path_kill_slashes(i->gid_path);
- } else {
- r = parse_gid(resolved_id, &i->gid);
- if (r < 0) {
- log_error("Failed to parse GID: %s", id);
- return -EBADMSG;
- }
-
- i->gid_set = true;
- }
- }
-
- h = groups;
- break;
-
- default:
- return -EBADMSG;
- }
-
- i->type = action[0];
- i->name = resolved_name;
- resolved_name = NULL;
-
- existing = hashmap_get(h, i->name);
- if (existing) {
-
- /* Two identical items are fine */
- if (!item_equal(existing, i))
- log_warning("Two or more conflicting lines for %s configured, ignoring.", i->name);
-
- return 0;
- }
-
- r = hashmap_put(h, i->name, i);
- if (r < 0)
- return log_oom();
-
- i = NULL;
- return 0;
-}
-
-static int read_config_file(const char *fn, bool ignore_enoent) {
- _cleanup_fclose_ FILE *rf = NULL;
- FILE *f = NULL;
- char line[LINE_MAX];
- unsigned v = 0;
- int r = 0;
-
- assert(fn);
-
- if (streq(fn, "-"))
- f = stdin;
- else {
- r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &rf);
- if (r < 0) {
- if (ignore_enoent && r == -ENOENT)
- return 0;
-
- return log_error_errno(r, "Failed to open '%s', ignoring: %m", fn);
- }
-
- f = rf;
- }
-
- FOREACH_LINE(line, f, break) {
- char *l;
- int k;
-
- v++;
-
- l = strstrip(line);
- if (*l == '#' || *l == 0)
- continue;
-
- k = parse_line(fn, v, l);
- if (k < 0 && r == 0)
- r = k;
- }
-
- if (ferror(f)) {
- log_error_errno(errno, "Failed to read from file %s: %m", fn);
- if (r == 0)
- r = -EIO;
- }
-
- return r;
-}
-
-static void free_database(Hashmap *by_name, Hashmap *by_id) {
- char *name;
-
- for (;;) {
- name = hashmap_first(by_id);
- if (!name)
- break;
-
- hashmap_remove(by_name, name);
-
- hashmap_steal_first_key(by_id);
- free(name);
- }
-
- while ((name = hashmap_steal_first_key(by_name)))
- free(name);
-
- hashmap_free(by_name);
- hashmap_free(by_id);
-}
-
-static void help(void) {
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Creates system user accounts.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --root=PATH Operate on an alternate filesystem root\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_ROOT,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "root", required_argument, NULL, ARG_ROOT },
- {}
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
- if (r < 0)
- return r;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- return 1;
-}
-
-int main(int argc, char *argv[]) {
-
- _cleanup_close_ int lock = -1;
- Iterator iterator;
- int r, k;
- Item *i;
- char *n;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- r = mac_selinux_init();
- if (r < 0) {
- log_error_errno(r, "SELinux setup failed: %m");
- goto finish;
- }
-
- if (optind < argc) {
- int j;
-
- for (j = optind; j < argc; j++) {
- k = read_config_file(argv[j], false);
- if (k < 0 && r == 0)
- r = k;
- }
- } else {
- _cleanup_strv_free_ char **files = NULL;
- char **f;
-
- r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to enumerate sysusers.d files: %m");
- goto finish;
- }
-
- STRV_FOREACH(f, files) {
- k = read_config_file(*f, true);
- if (k < 0 && r == 0)
- r = k;
- }
- }
-
- if (!uid_range) {
- /* Default to default range of 1..SYSTEMD_UID_MAX */
- r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX);
- if (r < 0) {
- log_oom();
- goto finish;
- }
- }
-
- r = add_implicit();
- if (r < 0)
- goto finish;
-
- lock = take_etc_passwd_lock(arg_root);
- if (lock < 0) {
- log_error_errno(lock, "Failed to take lock: %m");
- goto finish;
- }
-
- r = load_user_database();
- if (r < 0) {
- log_error_errno(r, "Failed to load user database: %m");
- goto finish;
- }
-
- r = load_group_database();
- if (r < 0) {
- log_error_errno(r, "Failed to read group database: %m");
- goto finish;
- }
-
- HASHMAP_FOREACH(i, groups, iterator)
- process_item(i);
-
- HASHMAP_FOREACH(i, users, iterator)
- process_item(i);
-
- r = write_files();
- if (r < 0)
- log_error_errno(r, "Failed to write files: %m");
-
-finish:
- while ((i = hashmap_steal_first(groups)))
- item_free(i);
-
- while ((i = hashmap_steal_first(users)))
- item_free(i);
-
- while ((n = hashmap_first_key(members))) {
- strv_free(hashmap_steal_first(members));
- free(n);
- }
-
- hashmap_free(groups);
- hashmap_free(users);
- hashmap_free(members);
- hashmap_free(todo_uids);
- hashmap_free(todo_gids);
-
- free_database(database_user, database_uid);
- free_database(database_group, database_gid);
-
- free(arg_root);
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-tmpfiles/Makefile b/src/grp-initutils/systemd-tmpfiles/Makefile
deleted file mode 100644
index d12c910883..0000000000
--- a/src/grp-initutils/systemd-tmpfiles/Makefile
+++ /dev/null
@@ -1,84 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_TMPFILES),)
-systemd_tmpfiles_SOURCES = \
- src/tmpfiles/tmpfiles.c
-
-systemd_tmpfiles_LDADD = \
- libshared.la
-
-rootbin_PROGRAMS += \
- systemd-tmpfiles
-
-dist_systemunit_DATA += \
- units/systemd-tmpfiles-clean.timer
-
-nodist_systemunit_DATA += \
- units/systemd-tmpfiles-setup-dev.service \
- units/systemd-tmpfiles-setup.service \
- units/systemd-tmpfiles-clean.service
-
-nodist_tmpfiles_DATA = \
- tmpfiles.d/systemd.conf \
- tmpfiles.d/etc.conf
-
-dist_tmpfiles_DATA = \
- tmpfiles.d/systemd-nologin.conf \
- tmpfiles.d/tmp.conf \
- tmpfiles.d/x11.conf \
- tmpfiles.d/var.conf \
- tmpfiles.d/home.conf \
- tmpfiles.d/systemd-nspawn.conf \
- tmpfiles.d/journal-nocow.conf
-
-ifneq ($(HAVE_SYSV_COMPAT),)
-dist_tmpfiles_DATA += \
- tmpfiles.d/legacy.conf
-endif # HAVE_SYSV_COMPAT
-
-SYSINIT_TARGET_WANTS += \
- systemd-tmpfiles-setup-dev.service \
- systemd-tmpfiles-setup.service
-
-dist_zshcompletion_data += \
- shell-completion/zsh/_systemd-tmpfiles
-
-TIMERS_TARGET_WANTS += \
- systemd-tmpfiles-clean.timer
-
-INSTALL_DIRS += \
- $(tmpfilesdir) \
- $(sysconfdir)/tmpfiles.d
-endif # ENABLE_TMPFILES
-
-EXTRA_DIST += \
- tmpfiles.d/systemd.conf.m4 \
- tmpfiles.d/etc.conf.m4 \
- units/systemd-tmpfiles-setup-dev.service.in \
- units/systemd-tmpfiles-setup.service.in \
- units/systemd-tmpfiles-clean.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-tmpfiles/systemd-tmpfiles.completion.zsh b/src/grp-initutils/systemd-tmpfiles/systemd-tmpfiles.completion.zsh
deleted file mode 100644
index 6ff02e5d98..0000000000
--- a/src/grp-initutils/systemd-tmpfiles/systemd-tmpfiles.completion.zsh
+++ /dev/null
@@ -1,13 +0,0 @@
-#compdef systemd-tmpfiles
-
-_arguments \
- {-h,--help}'[Show help]' \
- '--version[Show package version]' \
- '--create[Create, set ownership/permissions based on the config files.]' \
- '--clean[Clean up all files and directories with an age parameter configured.]' \
- '--remove[All files and directories marked with r, R in the configuration files are removed.]' \
- '--boot[Execute actions only safe at boot]' \
- '--prefix=[Only apply rules that apply to paths with the specified prefix.]' \
- '--exclude-prefix=[Ignore rules that apply to paths with the specified prefix.]' \
- '--root=[Operate on an alternate filesystem root]:directory:_directories' \
- '*::files:_files'
diff --git a/src/grp-initutils/systemd-tmpfiles/tmpfiles.c b/src/grp-initutils/systemd-tmpfiles/tmpfiles.c
deleted file mode 100644
index f865b9cc3e..0000000000
--- a/src/grp-initutils/systemd-tmpfiles/tmpfiles.c
+++ /dev/null
@@ -1,2344 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering, Kay Sievers
- Copyright 2015 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <fnmatch.h>
-#include <getopt.h>
-#include <glob.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/xattr.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <linux/fs.h>
-
-#include "basic/alloc-util.h"
-#include "basic/btrfs-util.h"
-#include "basic/capability-util.h"
-#include "basic/chattr-util.h"
-#include "basic/conf-files.h"
-#include "basic/copy.h"
-#include "basic/def.h"
-#include "basic/escape.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/formats-util.h"
-#include "basic/fs-util.h"
-#include "basic/glob-util.h"
-#include "basic/io-util.h"
-#include "basic/label.h"
-#include "basic/log.h"
-#include "basic/macro.h"
-#include "basic/missing.h"
-#include "basic/mkdir.h"
-#include "basic/mount-util.h"
-#include "basic/parse-util.h"
-#include "basic/path-util.h"
-#include "basic/rm-rf.h"
-#include "basic/selinux-util.h"
-#include "basic/set.h"
-#include "basic/stat-util.h"
-#include "basic/stdio-util.h"
-#include "basic/string-table.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/umask-util.h"
-#include "basic/user-util.h"
-#include "basic/util.h"
-#include "shared/acl-util.h"
-#include "shared/specifier.h"
-
-/* This reads all files listed in /etc/tmpfiles.d/?*.conf and creates
- * them in the file system. This is intended to be used to create
- * properly owned directories beneath /tmp, /var/tmp, /run, which are
- * volatile and hence need to be recreated on bootup. */
-
-typedef enum ItemType {
- /* These ones take file names */
- CREATE_FILE = 'f',
- TRUNCATE_FILE = 'F',
- CREATE_DIRECTORY = 'd',
- TRUNCATE_DIRECTORY = 'D',
- CREATE_SUBVOLUME = 'v',
- CREATE_SUBVOLUME_INHERIT_QUOTA = 'q',
- CREATE_SUBVOLUME_NEW_QUOTA = 'Q',
- CREATE_FIFO = 'p',
- CREATE_SYMLINK = 'L',
- CREATE_CHAR_DEVICE = 'c',
- CREATE_BLOCK_DEVICE = 'b',
- COPY_FILES = 'C',
-
- /* These ones take globs */
- WRITE_FILE = 'w',
- EMPTY_DIRECTORY = 'e',
- SET_XATTR = 't',
- RECURSIVE_SET_XATTR = 'T',
- SET_ACL = 'a',
- RECURSIVE_SET_ACL = 'A',
- SET_ATTRIBUTE = 'h',
- RECURSIVE_SET_ATTRIBUTE = 'H',
- IGNORE_PATH = 'x',
- IGNORE_DIRECTORY_PATH = 'X',
- REMOVE_PATH = 'r',
- RECURSIVE_REMOVE_PATH = 'R',
- RELABEL_PATH = 'z',
- RECURSIVE_RELABEL_PATH = 'Z',
- ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
-} ItemType;
-
-typedef struct Item {
- ItemType type;
-
- char *path;
- char *argument;
- char **xattrs;
-#ifdef HAVE_ACL
- acl_t acl_access;
- acl_t acl_default;
-#endif
- uid_t uid;
- gid_t gid;
- mode_t mode;
- usec_t age;
-
- dev_t major_minor;
- unsigned attribute_value;
- unsigned attribute_mask;
-
- bool uid_set:1;
- bool gid_set:1;
- bool mode_set:1;
- bool age_set:1;
- bool mask_perms:1;
- bool attribute_set:1;
-
- bool keep_first_level:1;
-
- bool force:1;
-
- bool done:1;
-} Item;
-
-typedef struct ItemArray {
- Item *items;
- size_t count;
- size_t size;
-} ItemArray;
-
-static bool arg_create = false;
-static bool arg_clean = false;
-static bool arg_remove = false;
-static bool arg_boot = false;
-
-static char **arg_include_prefixes = NULL;
-static char **arg_exclude_prefixes = NULL;
-static char *arg_root = NULL;
-
-static const char conf_file_dirs[] = CONF_PATHS_NULSTR("tmpfiles.d");
-
-#define MAX_DEPTH 256
-
-static OrderedHashmap *items = NULL, *globs = NULL;
-static Set *unix_sockets = NULL;
-
-static const Specifier specifier_table[] = {
- { 'm', specifier_machine_id, NULL },
- { 'b', specifier_boot_id, NULL },
- { 'H', specifier_host_name, NULL },
- { 'v', specifier_kernel_release, NULL },
- {}
-};
-
-static bool needs_glob(ItemType t) {
- return IN_SET(t,
- WRITE_FILE,
- IGNORE_PATH,
- IGNORE_DIRECTORY_PATH,
- REMOVE_PATH,
- RECURSIVE_REMOVE_PATH,
- EMPTY_DIRECTORY,
- ADJUST_MODE,
- RELABEL_PATH,
- RECURSIVE_RELABEL_PATH,
- SET_XATTR,
- RECURSIVE_SET_XATTR,
- SET_ACL,
- RECURSIVE_SET_ACL,
- SET_ATTRIBUTE,
- RECURSIVE_SET_ATTRIBUTE);
-}
-
-static bool takes_ownership(ItemType t) {
- return IN_SET(t,
- CREATE_FILE,
- TRUNCATE_FILE,
- CREATE_DIRECTORY,
- EMPTY_DIRECTORY,
- TRUNCATE_DIRECTORY,
- CREATE_SUBVOLUME,
- CREATE_SUBVOLUME_INHERIT_QUOTA,
- CREATE_SUBVOLUME_NEW_QUOTA,
- CREATE_FIFO,
- CREATE_SYMLINK,
- CREATE_CHAR_DEVICE,
- CREATE_BLOCK_DEVICE,
- COPY_FILES,
- WRITE_FILE,
- IGNORE_PATH,
- IGNORE_DIRECTORY_PATH,
- REMOVE_PATH,
- RECURSIVE_REMOVE_PATH);
-}
-
-static struct Item* find_glob(OrderedHashmap *h, const char *match) {
- ItemArray *j;
- Iterator i;
-
- ORDERED_HASHMAP_FOREACH(j, h, i) {
- unsigned n;
-
- for (n = 0; n < j->count; n++) {
- Item *item = j->items + n;
-
- if (fnmatch(item->path, match, FNM_PATHNAME|FNM_PERIOD) == 0)
- return item;
- }
- }
-
- return NULL;
-}
-
-static void load_unix_sockets(void) {
- _cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
-
- if (unix_sockets)
- return;
-
- /* We maintain a cache of the sockets we found in
- * /proc/net/unix to speed things up a little. */
-
- unix_sockets = set_new(&string_hash_ops);
- if (!unix_sockets)
- return;
-
- f = fopen("/proc/net/unix", "re");
- if (!f)
- return;
-
- /* Skip header */
- if (!fgets(line, sizeof(line), f))
- goto fail;
-
- for (;;) {
- char *p, *s;
- int k;
-
- if (!fgets(line, sizeof(line), f))
- break;
-
- truncate_nl(line);
-
- p = strchr(line, ':');
- if (!p)
- continue;
-
- if (strlen(p) < 37)
- continue;
-
- p += 37;
- p += strspn(p, WHITESPACE);
- p += strcspn(p, WHITESPACE); /* skip one more word */
- p += strspn(p, WHITESPACE);
-
- if (*p != '/')
- continue;
-
- s = strdup(p);
- if (!s)
- goto fail;
-
- path_kill_slashes(s);
-
- k = set_consume(unix_sockets, s);
- if (k < 0 && k != -EEXIST)
- goto fail;
- }
-
- return;
-
-fail:
- set_free_free(unix_sockets);
- unix_sockets = NULL;
-}
-
-static bool unix_socket_alive(const char *fn) {
- assert(fn);
-
- load_unix_sockets();
-
- if (unix_sockets)
- return !!set_get(unix_sockets, (char*) fn);
-
- /* We don't know, so assume yes */
- return true;
-}
-
-static int dir_is_mount_point(DIR *d, const char *subdir) {
-
- union file_handle_union h = FILE_HANDLE_INIT;
- int mount_id_parent, mount_id;
- int r_p, r;
-
- r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0);
- if (r_p < 0)
- r_p = -errno;
-
- h.handle.handle_bytes = MAX_HANDLE_SZ;
- r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0);
- if (r < 0)
- r = -errno;
-
- /* got no handle; make no assumptions, return error */
- if (r_p < 0 && r < 0)
- return r_p;
-
- /* got both handles; if they differ, it is a mount point */
- if (r_p >= 0 && r >= 0)
- return mount_id_parent != mount_id;
-
- /* got only one handle; assume different mount points if one
- * of both queries was not supported by the filesystem */
- if (r_p == -ENOSYS || r_p == -EOPNOTSUPP || r == -ENOSYS || r == -EOPNOTSUPP)
- return true;
-
- /* return error */
- if (r_p < 0)
- return r_p;
- return r;
-}
-
-static DIR* xopendirat_nomod(int dirfd, const char *path) {
- DIR *dir;
-
- dir = xopendirat(dirfd, path, O_NOFOLLOW|O_NOATIME);
- if (dir)
- return dir;
-
- log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
- if (errno != EPERM)
- return NULL;
-
- dir = xopendirat(dirfd, path, O_NOFOLLOW);
- if (!dir)
- log_debug_errno(errno, "Cannot open %sdirectory \"%s\": %m", dirfd == AT_FDCWD ? "" : "sub", path);
-
- return dir;
-}
-
-static DIR* opendir_nomod(const char *path) {
- return xopendirat_nomod(AT_FDCWD, path);
-}
-
-static int dir_cleanup(
- Item *i,
- const char *p,
- DIR *d,
- const struct stat *ds,
- usec_t cutoff,
- dev_t rootdev,
- bool mountpoint,
- int maxdepth,
- bool keep_this_level) {
-
- struct dirent *dent;
- struct timespec times[2];
- bool deleted = false;
- int r = 0;
-
- while ((dent = readdir(d))) {
- struct stat s;
- usec_t age;
- _cleanup_free_ char *sub_path = NULL;
-
- if (STR_IN_SET(dent->d_name, ".", ".."))
- continue;
-
- if (fstatat(dirfd(d), dent->d_name, &s, AT_SYMLINK_NOFOLLOW) < 0) {
- if (errno == ENOENT)
- continue;
-
- /* FUSE, NFS mounts, SELinux might return EACCES */
- if (errno == EACCES)
- log_debug_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
- else
- log_error_errno(errno, "stat(%s/%s) failed: %m", p, dent->d_name);
- r = -errno;
- continue;
- }
-
- /* Stay on the same filesystem */
- if (s.st_dev != rootdev) {
- log_debug("Ignoring \"%s/%s\": different filesystem.", p, dent->d_name);
- continue;
- }
-
- /* Try to detect bind mounts of the same filesystem instance; they
- * do not differ in device major/minors. This type of query is not
- * supported on all kernels or filesystem types though. */
- if (S_ISDIR(s.st_mode) && dir_is_mount_point(d, dent->d_name) > 0) {
- log_debug("Ignoring \"%s/%s\": different mount of the same filesystem.",
- p, dent->d_name);
- continue;
- }
-
- /* Do not delete read-only files owned by root */
- if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) {
- log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name);
- continue;
- }
-
- sub_path = strjoin(p, "/", dent->d_name, NULL);
- if (!sub_path) {
- r = log_oom();
- goto finish;
- }
-
- /* Is there an item configured for this path? */
- if (ordered_hashmap_get(items, sub_path)) {
- log_debug("Ignoring \"%s\": a separate entry exists.", sub_path);
- continue;
- }
-
- if (find_glob(globs, sub_path)) {
- log_debug("Ignoring \"%s\": a separate glob exists.", sub_path);
- continue;
- }
-
- if (S_ISDIR(s.st_mode)) {
-
- if (mountpoint &&
- streq(dent->d_name, "lost+found") &&
- s.st_uid == 0) {
- log_debug("Ignoring \"%s\".", sub_path);
- continue;
- }
-
- if (maxdepth <= 0)
- log_warning("Reached max depth on \"%s\".", sub_path);
- else {
- _cleanup_closedir_ DIR *sub_dir;
- int q;
-
- sub_dir = xopendirat_nomod(dirfd(d), dent->d_name);
- if (!sub_dir) {
- if (errno != ENOENT)
- r = log_error_errno(errno, "opendir(%s) failed: %m", sub_path);
-
- continue;
- }
-
- q = dir_cleanup(i, sub_path, sub_dir, &s, cutoff, rootdev, false, maxdepth-1, false);
- if (q < 0)
- r = q;
- }
-
- /* Note: if you are wondering why we don't
- * support the sticky bit for excluding
- * directories from cleaning like we do it for
- * other file system objects: well, the sticky
- * bit already has a meaning for directories,
- * so we don't want to overload that. */
-
- if (keep_this_level) {
- log_debug("Keeping \"%s\".", sub_path);
- continue;
- }
-
- /* Ignore ctime, we change it when deleting */
- age = timespec_load(&s.st_mtim);
- if (age >= cutoff) {
- char a[FORMAT_TIMESTAMP_MAX];
- /* Follows spelling in stat(1). */
- log_debug("Directory \"%s\": modify time %s is too new.",
- sub_path,
- format_timestamp_us(a, sizeof(a), age));
- continue;
- }
-
- age = timespec_load(&s.st_atim);
- if (age >= cutoff) {
- char a[FORMAT_TIMESTAMP_MAX];
- log_debug("Directory \"%s\": access time %s is too new.",
- sub_path,
- format_timestamp_us(a, sizeof(a), age));
- continue;
- }
-
- log_debug("Removing directory \"%s\".", sub_path);
- if (unlinkat(dirfd(d), dent->d_name, AT_REMOVEDIR) < 0)
- if (errno != ENOENT && errno != ENOTEMPTY) {
- log_error_errno(errno, "rmdir(%s): %m", sub_path);
- r = -errno;
- }
-
- } else {
- /* Skip files for which the sticky bit is
- * set. These are semantics we define, and are
- * unknown elsewhere. See XDG_RUNTIME_DIR
- * specification for details. */
- if (s.st_mode & S_ISVTX) {
- log_debug("Skipping \"%s\": sticky bit set.", sub_path);
- continue;
- }
-
- if (mountpoint && S_ISREG(s.st_mode))
- if (s.st_uid == 0 && STR_IN_SET(dent->d_name,
- ".journal",
- "aquota.user",
- "aquota.group")) {
- log_debug("Skipping \"%s\".", sub_path);
- continue;
- }
-
- /* Ignore sockets that are listed in /proc/net/unix */
- if (S_ISSOCK(s.st_mode) && unix_socket_alive(sub_path)) {
- log_debug("Skipping \"%s\": live socket.", sub_path);
- continue;
- }
-
- /* Ignore device nodes */
- if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode)) {
- log_debug("Skipping \"%s\": a device.", sub_path);
- continue;
- }
-
- /* Keep files on this level around if this is
- * requested */
- if (keep_this_level) {
- log_debug("Keeping \"%s\".", sub_path);
- continue;
- }
-
- age = timespec_load(&s.st_mtim);
- if (age >= cutoff) {
- char a[FORMAT_TIMESTAMP_MAX];
- /* Follows spelling in stat(1). */
- log_debug("File \"%s\": modify time %s is too new.",
- sub_path,
- format_timestamp_us(a, sizeof(a), age));
- continue;
- }
-
- age = timespec_load(&s.st_atim);
- if (age >= cutoff) {
- char a[FORMAT_TIMESTAMP_MAX];
- log_debug("File \"%s\": access time %s is too new.",
- sub_path,
- format_timestamp_us(a, sizeof(a), age));
- continue;
- }
-
- age = timespec_load(&s.st_ctim);
- if (age >= cutoff) {
- char a[FORMAT_TIMESTAMP_MAX];
- log_debug("File \"%s\": change time %s is too new.",
- sub_path,
- format_timestamp_us(a, sizeof(a), age));
- continue;
- }
-
- log_debug("unlink \"%s\"", sub_path);
-
- if (unlinkat(dirfd(d), dent->d_name, 0) < 0)
- if (errno != ENOENT)
- r = log_error_errno(errno, "unlink(%s): %m", sub_path);
-
- deleted = true;
- }
- }
-
-finish:
- if (deleted) {
- usec_t age1, age2;
- char a[FORMAT_TIMESTAMP_MAX], b[FORMAT_TIMESTAMP_MAX];
-
- /* Restore original directory timestamps */
- times[0] = ds->st_atim;
- times[1] = ds->st_mtim;
-
- age1 = timespec_load(&ds->st_atim);
- age2 = timespec_load(&ds->st_mtim);
- log_debug("Restoring access and modification time on \"%s\": %s, %s",
- p,
- format_timestamp_us(a, sizeof(a), age1),
- format_timestamp_us(b, sizeof(b), age2));
- if (futimens(dirfd(d), times) < 0)
- log_error_errno(errno, "utimensat(%s): %m", p);
- }
-
- return r;
-}
-
-static int path_set_perms(Item *i, const char *path) {
- _cleanup_close_ int fd = -1;
- struct stat st;
-
- assert(i);
- assert(path);
-
- /* We open the file with O_PATH here, to make the operation
- * somewhat atomic. Also there's unfortunately no fchmodat()
- * with AT_SYMLINK_NOFOLLOW, hence we emulate it here via
- * O_PATH. */
-
- fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
- if (fd < 0)
- return log_error_errno(errno, "Adjusting owner and mode for %s failed: %m", path);
-
- if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
- return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
-
- if (S_ISLNK(st.st_mode))
- log_debug("Skipping mode an owner fix for symlink %s.", path);
- else {
- char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
- xsprintf(fn, "/proc/self/fd/%i", fd);
-
- /* not using i->path directly because it may be a glob */
- if (i->mode_set) {
- mode_t m = i->mode;
-
- if (i->mask_perms) {
- if (!(st.st_mode & 0111))
- m &= ~0111;
- if (!(st.st_mode & 0222))
- m &= ~0222;
- if (!(st.st_mode & 0444))
- m &= ~0444;
- if (!S_ISDIR(st.st_mode))
- m &= ~07000; /* remove sticky/sgid/suid bit, unless directory */
- }
-
- if (m == (st.st_mode & 07777))
- log_debug("\"%s\" has right mode %o", path, st.st_mode);
- else {
- log_debug("chmod \"%s\" to mode %o", path, m);
- if (chmod(fn, m) < 0)
- return log_error_errno(errno, "chmod(%s) failed: %m", path);
- }
- }
-
- if ((i->uid != st.st_uid || i->gid != st.st_gid) &&
- (i->uid_set || i->gid_set)) {
- log_debug("chown \"%s\" to "UID_FMT"."GID_FMT,
- path,
- i->uid_set ? i->uid : UID_INVALID,
- i->gid_set ? i->gid : GID_INVALID);
- if (chown(fn,
- i->uid_set ? i->uid : UID_INVALID,
- i->gid_set ? i->gid : GID_INVALID) < 0)
- return log_error_errno(errno, "chown(%s) failed: %m", path);
- }
- }
-
- fd = safe_close(fd);
-
- return label_fix(path, false, false);
-}
-
-static int parse_xattrs_from_arg(Item *i) {
- const char *p;
- int r;
-
- assert(i);
- assert(i->argument);
-
- p = i->argument;
-
- for (;;) {
- _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL, *xattr_replaced = NULL;
-
- r = extract_first_word(&p, &xattr, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
- if (r < 0)
- log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
- if (r <= 0)
- break;
-
- r = specifier_printf(xattr, specifier_table, NULL, &xattr_replaced);
- if (r < 0)
- return log_error_errno(r, "Failed to replace specifiers in extended attribute '%s': %m", xattr);
-
- r = split_pair(xattr_replaced, "=", &name, &value);
- if (r < 0) {
- log_warning_errno(r, "Failed to parse extended attribute, ignoring: %s", xattr);
- continue;
- }
-
- if (isempty(name) || isempty(value)) {
- log_warning("Malformed extended attribute found, ignoring: %s", xattr);
- continue;
- }
-
- if (strv_push_pair(&i->xattrs, name, value) < 0)
- return log_oom();
-
- name = value = NULL;
- }
-
- return 0;
-}
-
-static int path_set_xattrs(Item *i, const char *path) {
- char **name, **value;
-
- assert(i);
- assert(path);
-
- STRV_FOREACH_PAIR(name, value, i->xattrs) {
- int n;
-
- n = strlen(*value);
- log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
- if (lsetxattr(path, *name, *value, n, 0) < 0) {
- log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
- return -errno;
- }
- }
- return 0;
-}
-
-static int parse_acls_from_arg(Item *item) {
-#ifdef HAVE_ACL
- int r;
-
- assert(item);
-
- /* If force (= modify) is set, we will not modify the acl
- * afterwards, so the mask can be added now if necessary. */
-
- r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
- if (r < 0)
- log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring", item->argument);
-#else
- log_warning_errno(ENOSYS, "ACLs are not supported. Ignoring");
-#endif
-
- return 0;
-}
-
-#ifdef HAVE_ACL
-static int path_set_acl(const char *path, const char *pretty, acl_type_t type, acl_t acl, bool modify) {
- _cleanup_(acl_free_charpp) char *t = NULL;
- _cleanup_(acl_freep) acl_t dup = NULL;
- int r;
-
- /* Returns 0 for success, positive error if already warned,
- * negative error otherwise. */
-
- if (modify) {
- r = acls_for_file(path, type, acl, &dup);
- if (r < 0)
- return r;
-
- r = calc_acl_mask_if_needed(&dup);
- if (r < 0)
- return r;
- } else {
- dup = acl_dup(acl);
- if (!dup)
- return -errno;
-
- /* the mask was already added earlier if needed */
- }
-
- r = add_base_acls_if_needed(&dup, path);
- if (r < 0)
- return r;
-
- t = acl_to_any_text(dup, NULL, ',', TEXT_ABBREVIATE);
- log_debug("Setting %s ACL %s on %s.",
- type == ACL_TYPE_ACCESS ? "access" : "default",
- strna(t), pretty);
-
- r = acl_set_file(path, type, dup);
- if (r < 0)
- /* Return positive to indicate we already warned */
- return -log_error_errno(errno,
- "Setting %s ACL \"%s\" on %s failed: %m",
- type == ACL_TYPE_ACCESS ? "access" : "default",
- strna(t), pretty);
-
- return 0;
-}
-#endif
-
-static int path_set_acls(Item *item, const char *path) {
- int r = 0;
-#ifdef HAVE_ACL
- char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
- _cleanup_close_ int fd = -1;
- struct stat st;
-
- assert(item);
- assert(path);
-
- fd = open(path, O_NOFOLLOW|O_CLOEXEC|O_PATH);
- if (fd < 0)
- return log_error_errno(errno, "Adjusting ACL of %s failed: %m", path);
-
- if (fstatat(fd, "", &st, AT_EMPTY_PATH) < 0)
- return log_error_errno(errno, "Failed to fstat() file %s: %m", path);
-
- if (S_ISLNK(st.st_mode)) {
- log_debug("Skipping ACL fix for symlink %s.", path);
- return 0;
- }
-
- xsprintf(fn, "/proc/self/fd/%i", fd);
-
- if (item->acl_access)
- r = path_set_acl(fn, path, ACL_TYPE_ACCESS, item->acl_access, item->force);
-
- if (r == 0 && item->acl_default)
- r = path_set_acl(fn, path, ACL_TYPE_DEFAULT, item->acl_default, item->force);
-
- if (r > 0)
- return -r; /* already warned */
- else if (r == -EOPNOTSUPP) {
- log_debug_errno(r, "ACLs not supported by file system at %s", path);
- return 0;
- } else if (r < 0)
- log_error_errno(r, "ACL operation on \"%s\" failed: %m", path);
-#endif
- return r;
-}
-
-#define ATTRIBUTES_ALL \
- (FS_NOATIME_FL | \
- FS_SYNC_FL | \
- FS_DIRSYNC_FL | \
- FS_APPEND_FL | \
- FS_COMPR_FL | \
- FS_NODUMP_FL | \
- FS_EXTENT_FL | \
- FS_IMMUTABLE_FL | \
- FS_JOURNAL_DATA_FL | \
- FS_SECRM_FL | \
- FS_UNRM_FL | \
- FS_NOTAIL_FL | \
- FS_TOPDIR_FL | \
- FS_NOCOW_FL)
-
-static int parse_attribute_from_arg(Item *item) {
-
- static const struct {
- char character;
- unsigned value;
- } attributes[] = {
- { 'A', FS_NOATIME_FL }, /* do not update atime */
- { 'S', FS_SYNC_FL }, /* Synchronous updates */
- { 'D', FS_DIRSYNC_FL }, /* dirsync behaviour (directories only) */
- { 'a', FS_APPEND_FL }, /* writes to file may only append */
- { 'c', FS_COMPR_FL }, /* Compress file */
- { 'd', FS_NODUMP_FL }, /* do not dump file */
- { 'e', FS_EXTENT_FL }, /* Top of directory hierarchies*/
- { 'i', FS_IMMUTABLE_FL }, /* Immutable file */
- { 'j', FS_JOURNAL_DATA_FL }, /* Reserved for ext3 */
- { 's', FS_SECRM_FL }, /* Secure deletion */
- { 'u', FS_UNRM_FL }, /* Undelete */
- { 't', FS_NOTAIL_FL }, /* file tail should not be merged */
- { 'T', FS_TOPDIR_FL }, /* Top of directory hierarchies*/
- { 'C', FS_NOCOW_FL }, /* Do not cow file */
- };
-
- enum {
- MODE_ADD,
- MODE_DEL,
- MODE_SET
- } mode = MODE_ADD;
-
- unsigned value = 0, mask = 0;
- const char *p;
-
- assert(item);
-
- p = item->argument;
- if (p) {
- if (*p == '+') {
- mode = MODE_ADD;
- p++;
- } else if (*p == '-') {
- mode = MODE_DEL;
- p++;
- } else if (*p == '=') {
- mode = MODE_SET;
- p++;
- }
- }
-
- if (isempty(p) && mode != MODE_SET) {
- log_error("Setting file attribute on '%s' needs an attribute specification.", item->path);
- return -EINVAL;
- }
-
- for (; p && *p ; p++) {
- unsigned i, v;
-
- for (i = 0; i < ELEMENTSOF(attributes); i++)
- if (*p == attributes[i].character)
- break;
-
- if (i >= ELEMENTSOF(attributes)) {
- log_error("Unknown file attribute '%c' on '%s'.", *p, item->path);
- return -EINVAL;
- }
-
- v = attributes[i].value;
-
- SET_FLAG(value, v, (mode == MODE_ADD || mode == MODE_SET));
-
- mask |= v;
- }
-
- if (mode == MODE_SET)
- mask |= ATTRIBUTES_ALL;
-
- assert(mask != 0);
-
- item->attribute_mask = mask;
- item->attribute_value = value;
- item->attribute_set = true;
-
- return 0;
-}
-
-static int path_set_attribute(Item *item, const char *path) {
- _cleanup_close_ int fd = -1;
- struct stat st;
- unsigned f;
- int r;
-
- if (!item->attribute_set || item->attribute_mask == 0)
- return 0;
-
- fd = open(path, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOATIME|O_NOFOLLOW);
- if (fd < 0) {
- if (errno == ELOOP)
- return log_error_errno(errno, "Skipping file attributes adjustment on symlink %s.", path);
-
- return log_error_errno(errno, "Cannot open '%s': %m", path);
- }
-
- if (fstat(fd, &st) < 0)
- return log_error_errno(errno, "Cannot stat '%s': %m", path);
-
- /* Issuing the file attribute ioctls on device nodes is not
- * safe, as that will be delivered to the drivers, not the
- * file system containing the device node. */
- if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
- log_error("Setting file flags is only supported on regular files and directories, cannot set on '%s'.", path);
- return -EINVAL;
- }
-
- f = item->attribute_value & item->attribute_mask;
-
- /* Mask away directory-specific flags */
- if (!S_ISDIR(st.st_mode))
- f &= ~FS_DIRSYNC_FL;
-
- r = chattr_fd(fd, f, item->attribute_mask);
- if (r < 0)
- log_full_errno(r == -ENOTTY ? LOG_DEBUG : LOG_WARNING,
- r,
- "Cannot set file attribute for '%s', value=0x%08x, mask=0x%08x: %m",
- path, item->attribute_value, item->attribute_mask);
-
- return 0;
-}
-
-static int write_one_file(Item *i, const char *path) {
- _cleanup_close_ int fd = -1;
- int flags, r = 0;
- struct stat st;
-
- assert(i);
- assert(path);
-
- flags = i->type == CREATE_FILE ? O_CREAT|O_APPEND|O_NOFOLLOW :
- i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC|O_NOFOLLOW : 0;
-
- RUN_WITH_UMASK(0000) {
- mac_selinux_create_file_prepare(path, S_IFREG);
- fd = open(path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode);
- mac_selinux_create_file_clear();
- }
-
- if (fd < 0) {
- if (i->type == WRITE_FILE && errno == ENOENT) {
- log_debug_errno(errno, "Not writing \"%s\": %m", path);
- return 0;
- }
-
- r = -errno;
- if (!i->argument && errno == EROFS && stat(path, &st) == 0 &&
- (i->type == CREATE_FILE || st.st_size == 0))
- goto check_mode;
-
- return log_error_errno(r, "Failed to create file %s: %m", path);
- }
-
- if (i->argument) {
- _cleanup_free_ char *unescaped = NULL, *replaced = NULL;
-
- log_debug("%s to \"%s\".", i->type == CREATE_FILE ? "Appending" : "Writing", path);
-
- r = cunescape(i->argument, 0, &unescaped);
- if (r < 0)
- return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument);
-
- r = specifier_printf(unescaped, specifier_table, NULL, &replaced);
- if (r < 0)
- return log_error_errno(r, "Failed to replace specifiers in parameter to write '%s': %m", unescaped);
-
- r = loop_write(fd, replaced, strlen(replaced), false);
- if (r < 0)
- return log_error_errno(r, "Failed to write file \"%s\": %m", path);
- } else
- log_debug("\"%s\" has been created.", path);
-
- fd = safe_close(fd);
-
- if (stat(path, &st) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", path);
-
- check_mode:
- if (!S_ISREG(st.st_mode)) {
- log_error("%s is not a file.", path);
- return -EEXIST;
- }
-
- r = path_set_perms(i, path);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-typedef int (*action_t)(Item *, const char *);
-
-static int item_do_children(Item *i, const char *path, action_t action) {
- _cleanup_closedir_ DIR *d;
- int r = 0;
-
- assert(i);
- assert(path);
-
- /* This returns the first error we run into, but nevertheless
- * tries to go on */
-
- d = opendir_nomod(path);
- if (!d)
- return errno == ENOENT || errno == ENOTDIR ? 0 : -errno;
-
- for (;;) {
- _cleanup_free_ char *p = NULL;
- struct dirent *de;
- int q;
-
- errno = 0;
- de = readdir(d);
- if (!de) {
- if (errno > 0 && r == 0)
- r = -errno;
-
- break;
- }
-
- if (STR_IN_SET(de->d_name, ".", ".."))
- continue;
-
- p = strjoin(path, "/", de->d_name, NULL);
- if (!p)
- return -ENOMEM;
-
- q = action(i, p);
- if (q < 0 && q != -ENOENT && r == 0)
- r = q;
-
- if (IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)) {
- q = item_do_children(i, p, action);
- if (q < 0 && r == 0)
- r = q;
- }
- }
-
- return r;
-}
-
-static int glob_item(Item *i, action_t action, bool recursive) {
- _cleanup_globfree_ glob_t g = {
- .gl_closedir = (void (*)(void *)) closedir,
- .gl_readdir = (struct dirent *(*)(void *)) readdir,
- .gl_opendir = (void *(*)(const char *)) opendir_nomod,
- .gl_lstat = lstat,
- .gl_stat = stat,
- };
- int r = 0, k;
- char **fn;
-
- errno = 0;
- k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g);
- if (k != 0 && k != GLOB_NOMATCH)
- return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path);
-
- STRV_FOREACH(fn, g.gl_pathv) {
- k = action(i, *fn);
- if (k < 0 && r == 0)
- r = k;
-
- if (recursive) {
- k = item_do_children(i, *fn, action);
- if (k < 0 && r == 0)
- r = k;
- }
- }
-
- return r;
-}
-
-typedef enum {
- CREATION_NORMAL,
- CREATION_EXISTING,
- CREATION_FORCE,
- _CREATION_MODE_MAX,
- _CREATION_MODE_INVALID = -1
-} CreationMode;
-
-static const char *creation_mode_verb_table[_CREATION_MODE_MAX] = {
- [CREATION_NORMAL] = "Created",
- [CREATION_EXISTING] = "Found existing",
- [CREATION_FORCE] = "Created replacement",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(creation_mode_verb, CreationMode);
-
-static int create_item(Item *i) {
- _cleanup_free_ char *resolved = NULL;
- struct stat st;
- int r = 0;
- int q = 0;
- CreationMode creation;
-
- assert(i);
-
- log_debug("Running create action for entry %c %s", (char) i->type, i->path);
-
- switch (i->type) {
-
- case IGNORE_PATH:
- case IGNORE_DIRECTORY_PATH:
- case REMOVE_PATH:
- case RECURSIVE_REMOVE_PATH:
- return 0;
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- r = write_one_file(i, i->path);
- if (r < 0)
- return r;
- break;
-
- case COPY_FILES: {
- r = specifier_printf(i->argument, specifier_table, NULL, &resolved);
- if (r < 0)
- return log_error_errno(r, "Failed to substitute specifiers in copy source %s: %m", i->argument);
-
- log_debug("Copying tree \"%s\" to \"%s\".", resolved, i->path);
- r = copy_tree(resolved, i->path, false);
-
- if (r == -EROFS && stat(i->path, &st) == 0)
- r = -EEXIST;
-
- if (r < 0) {
- struct stat a, b;
-
- if (r != -EEXIST)
- return log_error_errno(r, "Failed to copy files to %s: %m", i->path);
-
- if (stat(resolved, &a) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", resolved);
-
- if (stat(i->path, &b) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", i->path);
-
- if ((a.st_mode ^ b.st_mode) & S_IFMT) {
- log_debug("Can't copy to %s, file exists already and is of different type", i->path);
- return 0;
- }
- }
-
- r = path_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
-
- case WRITE_FILE:
- r = glob_item(i, write_one_file, false);
- if (r < 0)
- return r;
-
- break;
-
- case CREATE_DIRECTORY:
- case TRUNCATE_DIRECTORY:
- case CREATE_SUBVOLUME:
- case CREATE_SUBVOLUME_INHERIT_QUOTA:
- case CREATE_SUBVOLUME_NEW_QUOTA:
- RUN_WITH_UMASK(0000)
- mkdir_parents_label(i->path, 0755);
-
- if (IN_SET(i->type, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA)) {
-
- if (btrfs_is_subvol(isempty(arg_root) ? "/" : arg_root) <= 0)
-
- /* Don't create a subvolume unless the
- * root directory is one, too. We do
- * this under the assumption that if
- * the root directory is just a plain
- * directory (i.e. very light-weight),
- * we shouldn't try to split it up
- * into subvolumes (i.e. more
- * heavy-weight). Thus, chroot()
- * environments and suchlike will get
- * a full brtfs subvolume set up below
- * their tree only if they
- * specifically set up a btrfs
- * subvolume for the root dir too. */
-
- r = -ENOTTY;
- else {
- RUN_WITH_UMASK((~i->mode) & 0777)
- r = btrfs_subvol_make(i->path);
- }
- } else
- r = 0;
-
- if (IN_SET(i->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY) || r == -ENOTTY)
- RUN_WITH_UMASK(0000)
- r = mkdir_label(i->path, i->mode);
-
- if (r < 0) {
- int k;
-
- if (r != -EEXIST && r != -EROFS)
- return log_error_errno(r, "Failed to create directory or subvolume \"%s\": %m", i->path);
-
- k = is_dir(i->path, false);
- if (k == -ENOENT && r == -EROFS)
- return log_error_errno(r, "%s does not exist and cannot be created as the file system is read-only.", i->path);
- if (k < 0)
- return log_error_errno(k, "Failed to check if %s exists: %m", i->path);
- if (!k) {
- log_warning("\"%s\" already exists and is not a directory.", i->path);
- return 0;
- }
-
- creation = CREATION_EXISTING;
- } else
- creation = CREATION_NORMAL;
-
- log_debug("%s directory \"%s\".", creation_mode_verb_to_string(creation), i->path);
-
- if (IN_SET(i->type, CREATE_SUBVOLUME_NEW_QUOTA, CREATE_SUBVOLUME_INHERIT_QUOTA)) {
- r = btrfs_subvol_auto_qgroup(i->path, 0, i->type == CREATE_SUBVOLUME_NEW_QUOTA);
- if (r == -ENOTTY)
- log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (unsupported fs or dir not a subvolume): %m", i->path);
- else if (r == -EROFS)
- log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (fs is read-only).", i->path);
- else if (r == -ENOPROTOOPT)
- log_debug_errno(r, "Couldn't adjust quota for subvolume \"%s\" (quota support is disabled).", i->path);
- else if (r < 0)
- q = log_error_errno(r, "Failed to adjust quota for subvolume \"%s\": %m", i->path);
- else if (r > 0)
- log_debug("Adjusted quota for subvolume \"%s\".", i->path);
- else if (r == 0)
- log_debug("Quota for subvolume \"%s\" already in place, no change made.", i->path);
- }
-
- /* fall through */
-
- case EMPTY_DIRECTORY:
- r = path_set_perms(i, i->path);
- if (q < 0)
- return q;
- if (r < 0)
- return r;
-
- break;
-
- case CREATE_FIFO:
- RUN_WITH_UMASK(0000) {
- mac_selinux_create_file_prepare(i->path, S_IFIFO);
- r = mkfifo(i->path, i->mode);
- mac_selinux_create_file_clear();
- }
-
- if (r < 0) {
- if (errno != EEXIST)
- return log_error_errno(errno, "Failed to create fifo %s: %m", i->path);
-
- if (lstat(i->path, &st) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", i->path);
-
- if (!S_ISFIFO(st.st_mode)) {
-
- if (i->force) {
- RUN_WITH_UMASK(0000) {
- mac_selinux_create_file_prepare(i->path, S_IFIFO);
- r = mkfifo_atomic(i->path, i->mode);
- mac_selinux_create_file_clear();
- }
-
- if (r < 0)
- return log_error_errno(r, "Failed to create fifo %s: %m", i->path);
- creation = CREATION_FORCE;
- } else {
- log_warning("\"%s\" already exists and is not a fifo.", i->path);
- return 0;
- }
- } else
- creation = CREATION_EXISTING;
- } else
- creation = CREATION_NORMAL;
- log_debug("%s fifo \"%s\".", creation_mode_verb_to_string(creation), i->path);
-
- r = path_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
- }
-
- case CREATE_SYMLINK: {
- r = specifier_printf(i->argument, specifier_table, NULL, &resolved);
- if (r < 0)
- return log_error_errno(r, "Failed to substitute specifiers in symlink target %s: %m", i->argument);
-
- mac_selinux_create_file_prepare(i->path, S_IFLNK);
- r = symlink(resolved, i->path);
- mac_selinux_create_file_clear();
-
- if (r < 0) {
- _cleanup_free_ char *x = NULL;
-
- if (errno != EEXIST)
- return log_error_errno(errno, "symlink(%s, %s) failed: %m", resolved, i->path);
-
- r = readlink_malloc(i->path, &x);
- if (r < 0 || !streq(resolved, x)) {
-
- if (i->force) {
- mac_selinux_create_file_prepare(i->path, S_IFLNK);
- r = symlink_atomic(resolved, i->path);
- mac_selinux_create_file_clear();
-
- if (r < 0)
- return log_error_errno(r, "symlink(%s, %s) failed: %m", resolved, i->path);
-
- creation = CREATION_FORCE;
- } else {
- log_debug("\"%s\" is not a symlink or does not point to the correct path.", i->path);
- return 0;
- }
- } else
- creation = CREATION_EXISTING;
- } else
-
- creation = CREATION_NORMAL;
- log_debug("%s symlink \"%s\".", creation_mode_verb_to_string(creation), i->path);
- break;
- }
-
- case CREATE_BLOCK_DEVICE:
- case CREATE_CHAR_DEVICE: {
- mode_t file_type;
-
- if (have_effective_cap(CAP_MKNOD) == 0) {
- /* In a container we lack CAP_MKNOD. We
- shouldn't attempt to create the device node in
- that case to avoid noise, and we don't support
- virtualized devices in containers anyway. */
-
- log_debug("We lack CAP_MKNOD, skipping creation of device node %s.", i->path);
- return 0;
- }
-
- file_type = i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR;
-
- RUN_WITH_UMASK(0000) {
- mac_selinux_create_file_prepare(i->path, file_type);
- r = mknod(i->path, i->mode | file_type, i->major_minor);
- mac_selinux_create_file_clear();
- }
-
- if (r < 0) {
- if (errno == EPERM) {
- log_debug("We lack permissions, possibly because of cgroup configuration; "
- "skipping creation of device node %s.", i->path);
- return 0;
- }
-
- if (errno != EEXIST)
- return log_error_errno(errno, "Failed to create device node %s: %m", i->path);
-
- if (lstat(i->path, &st) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", i->path);
-
- if ((st.st_mode & S_IFMT) != file_type) {
-
- if (i->force) {
-
- RUN_WITH_UMASK(0000) {
- mac_selinux_create_file_prepare(i->path, file_type);
- r = mknod_atomic(i->path, i->mode | file_type, i->major_minor);
- mac_selinux_create_file_clear();
- }
-
- if (r < 0)
- return log_error_errno(r, "Failed to create device node \"%s\": %m", i->path);
- creation = CREATION_FORCE;
- } else {
- log_debug("%s is not a device node.", i->path);
- return 0;
- }
- } else
- creation = CREATION_EXISTING;
- } else
- creation = CREATION_NORMAL;
-
- log_debug("%s %s device node \"%s\" %u:%u.",
- creation_mode_verb_to_string(creation),
- i->type == CREATE_BLOCK_DEVICE ? "block" : "char",
- i->path, major(i->mode), minor(i->mode));
-
- r = path_set_perms(i, i->path);
- if (r < 0)
- return r;
-
- break;
- }
-
- case ADJUST_MODE:
- case RELABEL_PATH:
- r = glob_item(i, path_set_perms, false);
- if (r < 0)
- return r;
- break;
-
- case RECURSIVE_RELABEL_PATH:
- r = glob_item(i, path_set_perms, true);
- if (r < 0)
- return r;
- break;
-
- case SET_XATTR:
- r = glob_item(i, path_set_xattrs, false);
- if (r < 0)
- return r;
- break;
-
- case RECURSIVE_SET_XATTR:
- r = glob_item(i, path_set_xattrs, true);
- if (r < 0)
- return r;
- break;
-
- case SET_ACL:
- r = glob_item(i, path_set_acls, false);
- if (r < 0)
- return r;
- break;
-
- case RECURSIVE_SET_ACL:
- r = glob_item(i, path_set_acls, true);
- if (r < 0)
- return r;
- break;
-
- case SET_ATTRIBUTE:
- r = glob_item(i, path_set_attribute, false);
- if (r < 0)
- return r;
- break;
-
- case RECURSIVE_SET_ATTRIBUTE:
- r = glob_item(i, path_set_attribute, true);
- if (r < 0)
- return r;
- break;
- }
-
- return 0;
-}
-
-static int remove_item_instance(Item *i, const char *instance) {
- int r;
-
- assert(i);
-
- switch (i->type) {
-
- case REMOVE_PATH:
- if (remove(instance) < 0 && errno != ENOENT)
- return log_error_errno(errno, "rm(%s): %m", instance);
-
- break;
-
- case TRUNCATE_DIRECTORY:
- case RECURSIVE_REMOVE_PATH:
- /* FIXME: we probably should use dir_cleanup() here
- * instead of rm_rf() so that 'x' is honoured. */
- log_debug("rm -rf \"%s\"", instance);
- r = rm_rf(instance, (i->type == RECURSIVE_REMOVE_PATH ? REMOVE_ROOT|REMOVE_SUBVOLUME : 0) | REMOVE_PHYSICAL);
- if (r < 0 && r != -ENOENT)
- return log_error_errno(r, "rm_rf(%s): %m", instance);
-
- break;
-
- default:
- assert_not_reached("wut?");
- }
-
- return 0;
-}
-
-static int remove_item(Item *i) {
- assert(i);
-
- log_debug("Running remove action for entry %c %s", (char) i->type, i->path);
-
- switch (i->type) {
-
- case REMOVE_PATH:
- case TRUNCATE_DIRECTORY:
- case RECURSIVE_REMOVE_PATH:
- return glob_item(i, remove_item_instance, false);
-
- default:
- return 0;
- }
-}
-
-static int clean_item_instance(Item *i, const char* instance) {
- _cleanup_closedir_ DIR *d = NULL;
- struct stat s, ps;
- bool mountpoint;
- usec_t cutoff, n;
- char timestamp[FORMAT_TIMESTAMP_MAX];
-
- assert(i);
-
- if (!i->age_set)
- return 0;
-
- n = now(CLOCK_REALTIME);
- if (n < i->age)
- return 0;
-
- cutoff = n - i->age;
-
- d = opendir_nomod(instance);
- if (!d) {
- if (errno == ENOENT || errno == ENOTDIR) {
- log_debug_errno(errno, "Directory \"%s\": %m", instance);
- return 0;
- }
-
- log_error_errno(errno, "Failed to open directory %s: %m", instance);
- return -errno;
- }
-
- if (fstat(dirfd(d), &s) < 0)
- return log_error_errno(errno, "stat(%s) failed: %m", i->path);
-
- if (!S_ISDIR(s.st_mode)) {
- log_error("%s is not a directory.", i->path);
- return -ENOTDIR;
- }
-
- if (fstatat(dirfd(d), "..", &ps, AT_SYMLINK_NOFOLLOW) != 0)
- return log_error_errno(errno, "stat(%s/..) failed: %m", i->path);
-
- mountpoint = s.st_dev != ps.st_dev || s.st_ino == ps.st_ino;
-
- log_debug("Cleanup threshold for %s \"%s\" is %s",
- mountpoint ? "mount point" : "directory",
- instance,
- format_timestamp_us(timestamp, sizeof(timestamp), cutoff));
-
- return dir_cleanup(i, instance, d, &s, cutoff, s.st_dev, mountpoint,
- MAX_DEPTH, i->keep_first_level);
-}
-
-static int clean_item(Item *i) {
- assert(i);
-
- log_debug("Running clean action for entry %c %s", (char) i->type, i->path);
-
- switch (i->type) {
- case CREATE_DIRECTORY:
- case CREATE_SUBVOLUME:
- case CREATE_SUBVOLUME_INHERIT_QUOTA:
- case CREATE_SUBVOLUME_NEW_QUOTA:
- case EMPTY_DIRECTORY:
- case TRUNCATE_DIRECTORY:
- case IGNORE_PATH:
- case COPY_FILES:
- clean_item_instance(i, i->path);
- return 0;
- case IGNORE_DIRECTORY_PATH:
- return glob_item(i, clean_item_instance, false);
- default:
- return 0;
- }
-}
-
-static int process_item_array(ItemArray *array);
-
-static int process_item(Item *i) {
- int r, q, p, t = 0;
- _cleanup_free_ char *prefix = NULL;
-
- assert(i);
-
- if (i->done)
- return 0;
-
- i->done = true;
-
- prefix = malloc(strlen(i->path) + 1);
- if (!prefix)
- return log_oom();
-
- PATH_FOREACH_PREFIX(prefix, i->path) {
- ItemArray *j;
-
- j = ordered_hashmap_get(items, prefix);
- if (j) {
- int s;
-
- s = process_item_array(j);
- if (s < 0 && t == 0)
- t = s;
- }
- }
-
- r = arg_create ? create_item(i) : 0;
- q = arg_remove ? remove_item(i) : 0;
- p = arg_clean ? clean_item(i) : 0;
-
- return t < 0 ? t :
- r < 0 ? r :
- q < 0 ? q :
- p;
-}
-
-static int process_item_array(ItemArray *array) {
- unsigned n;
- int r = 0, k;
-
- assert(array);
-
- for (n = 0; n < array->count; n++) {
- k = process_item(array->items + n);
- if (k < 0 && r == 0)
- r = k;
- }
-
- return r;
-}
-
-static void item_free_contents(Item *i) {
- assert(i);
- free(i->path);
- free(i->argument);
- strv_free(i->xattrs);
-
-#ifdef HAVE_ACL
- acl_free(i->acl_access);
- acl_free(i->acl_default);
-#endif
-}
-
-static void item_array_free(ItemArray *a) {
- unsigned n;
-
- if (!a)
- return;
-
- for (n = 0; n < a->count; n++)
- item_free_contents(a->items + n);
- free(a->items);
- free(a);
-}
-
-static int item_compare(const void *a, const void *b) {
- const Item *x = a, *y = b;
-
- /* Make sure that the ownership taking item is put first, so
- * that we first create the node, and then can adjust it */
-
- if (takes_ownership(x->type) && !takes_ownership(y->type))
- return -1;
- if (!takes_ownership(x->type) && takes_ownership(y->type))
- return 1;
-
- return (int) x->type - (int) y->type;
-}
-
-static bool item_compatible(Item *a, Item *b) {
- assert(a);
- assert(b);
- assert(streq(a->path, b->path));
-
- if (takes_ownership(a->type) && takes_ownership(b->type))
- /* check if the items are the same */
- return streq_ptr(a->argument, b->argument) &&
-
- a->uid_set == b->uid_set &&
- a->uid == b->uid &&
-
- a->gid_set == b->gid_set &&
- a->gid == b->gid &&
-
- a->mode_set == b->mode_set &&
- a->mode == b->mode &&
-
- a->age_set == b->age_set &&
- a->age == b->age &&
-
- a->mask_perms == b->mask_perms &&
-
- a->keep_first_level == b->keep_first_level &&
-
- a->major_minor == b->major_minor;
-
- return true;
-}
-
-static bool should_include_path(const char *path) {
- char **prefix;
-
- STRV_FOREACH(prefix, arg_exclude_prefixes)
- if (path_startswith(path, *prefix)) {
- log_debug("Entry \"%s\" matches exclude prefix \"%s\", skipping.",
- path, *prefix);
- return false;
- }
-
- STRV_FOREACH(prefix, arg_include_prefixes)
- if (path_startswith(path, *prefix)) {
- log_debug("Entry \"%s\" matches include prefix \"%s\".", path, *prefix);
- return true;
- }
-
- /* no matches, so we should include this path only if we
- * have no whitelist at all */
- if (strv_length(arg_include_prefixes) == 0)
- return true;
-
- log_debug("Entry \"%s\" does not match any include prefix, skipping.", path);
- return false;
-}
-
-static int parse_line(const char *fname, unsigned line, const char *buffer) {
-
- _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
- _cleanup_(item_free_contents) Item i = {};
- ItemArray *existing;
- OrderedHashmap *h;
- int r, pos;
- bool force = false, boot = false;
-
- assert(fname);
- assert(line >= 1);
- assert(buffer);
-
- r = extract_many_words(
- &buffer,
- NULL,
- EXTRACT_QUOTES,
- &action,
- &path,
- &mode,
- &user,
- &group,
- &age,
- NULL);
- if (r < 0)
- return log_error_errno(r, "[%s:%u] Failed to parse line: %m", fname, line);
- else if (r < 2) {
- log_error("[%s:%u] Syntax error.", fname, line);
- return -EIO;
- }
-
- if (!isempty(buffer) && !streq(buffer, "-")) {
- i.argument = strdup(buffer);
- if (!i.argument)
- return log_oom();
- }
-
- if (isempty(action)) {
- log_error("[%s:%u] Command too short '%s'.", fname, line, action);
- return -EINVAL;
- }
-
- for (pos = 1; action[pos]; pos++) {
- if (action[pos] == '!' && !boot)
- boot = true;
- else if (action[pos] == '+' && !force)
- force = true;
- else {
- log_error("[%s:%u] Unknown modifiers in command '%s'",
- fname, line, action);
- return -EINVAL;
- }
- }
-
- if (boot && !arg_boot) {
- log_debug("Ignoring entry %s \"%s\" because --boot is not specified.",
- action, path);
- return 0;
- }
-
- i.type = action[0];
- i.force = force;
-
- r = specifier_printf(path, specifier_table, NULL, &i.path);
- if (r < 0) {
- log_error("[%s:%u] Failed to replace specifiers: %s", fname, line, path);
- return r;
- }
-
- switch (i.type) {
-
- case CREATE_DIRECTORY:
- case CREATE_SUBVOLUME:
- case CREATE_SUBVOLUME_INHERIT_QUOTA:
- case CREATE_SUBVOLUME_NEW_QUOTA:
- case EMPTY_DIRECTORY:
- case TRUNCATE_DIRECTORY:
- case CREATE_FIFO:
- case IGNORE_PATH:
- case IGNORE_DIRECTORY_PATH:
- case REMOVE_PATH:
- case RECURSIVE_REMOVE_PATH:
- case ADJUST_MODE:
- case RELABEL_PATH:
- case RECURSIVE_RELABEL_PATH:
- if (i.argument)
- log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type);
-
- break;
-
- case CREATE_FILE:
- case TRUNCATE_FILE:
- break;
-
- case CREATE_SYMLINK:
- if (!i.argument) {
- i.argument = strappend("/usr/share/factory/", i.path);
- if (!i.argument)
- return log_oom();
- }
- break;
-
- case WRITE_FILE:
- if (!i.argument) {
- log_error("[%s:%u] Write file requires argument.", fname, line);
- return -EBADMSG;
- }
- break;
-
- case COPY_FILES:
- if (!i.argument) {
- i.argument = strappend("/usr/share/factory/", i.path);
- if (!i.argument)
- return log_oom();
- } else if (!path_is_absolute(i.argument)) {
- log_error("[%s:%u] Source path is not absolute.", fname, line);
- return -EBADMSG;
- }
-
- path_kill_slashes(i.argument);
- break;
-
- case CREATE_CHAR_DEVICE:
- case CREATE_BLOCK_DEVICE: {
- unsigned major, minor;
-
- if (!i.argument) {
- log_error("[%s:%u] Device file requires argument.", fname, line);
- return -EBADMSG;
- }
-
- if (sscanf(i.argument, "%u:%u", &major, &minor) != 2) {
- log_error("[%s:%u] Can't parse device file major/minor '%s'.", fname, line, i.argument);
- return -EBADMSG;
- }
-
- i.major_minor = makedev(major, minor);
- break;
- }
-
- case SET_XATTR:
- case RECURSIVE_SET_XATTR:
- if (!i.argument) {
- log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
- return -EBADMSG;
- }
- r = parse_xattrs_from_arg(&i);
- if (r < 0)
- return r;
- break;
-
- case SET_ACL:
- case RECURSIVE_SET_ACL:
- if (!i.argument) {
- log_error("[%s:%u] Set ACLs requires argument.", fname, line);
- return -EBADMSG;
- }
- r = parse_acls_from_arg(&i);
- if (r < 0)
- return r;
- break;
-
- case SET_ATTRIBUTE:
- case RECURSIVE_SET_ATTRIBUTE:
- if (!i.argument) {
- log_error("[%s:%u] Set file attribute requires argument.", fname, line);
- return -EBADMSG;
- }
- r = parse_attribute_from_arg(&i);
- if (r < 0)
- return r;
- break;
-
- default:
- log_error("[%s:%u] Unknown command type '%c'.", fname, line, (char) i.type);
- return -EBADMSG;
- }
-
- if (!path_is_absolute(i.path)) {
- log_error("[%s:%u] Path '%s' not absolute.", fname, line, i.path);
- return -EBADMSG;
- }
-
- path_kill_slashes(i.path);
-
- if (!should_include_path(i.path))
- return 0;
-
- if (arg_root) {
- char *p;
-
- p = prefix_root(arg_root, i.path);
- if (!p)
- return log_oom();
-
- free(i.path);
- i.path = p;
- }
-
- if (!isempty(user) && !streq(user, "-")) {
- const char *u = user;
-
- r = get_user_creds(&u, &i.uid, NULL, NULL, NULL);
- if (r < 0) {
- log_error("[%s:%u] Unknown user '%s'.", fname, line, user);
- return r;
- }
-
- i.uid_set = true;
- }
-
- if (!isempty(group) && !streq(group, "-")) {
- const char *g = group;
-
- r = get_group_creds(&g, &i.gid);
- if (r < 0) {
- log_error("[%s:%u] Unknown group '%s'.", fname, line, group);
- return r;
- }
-
- i.gid_set = true;
- }
-
- if (!isempty(mode) && !streq(mode, "-")) {
- const char *mm = mode;
- unsigned m;
-
- if (*mm == '~') {
- i.mask_perms = true;
- mm++;
- }
-
- if (parse_mode(mm, &m) < 0) {
- log_error("[%s:%u] Invalid mode '%s'.", fname, line, mode);
- return -EBADMSG;
- }
-
- i.mode = m;
- i.mode_set = true;
- } else
- i.mode = IN_SET(i.type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA) ? 0755 : 0644;
-
- if (!isempty(age) && !streq(age, "-")) {
- const char *a = age;
-
- if (*a == '~') {
- i.keep_first_level = true;
- a++;
- }
-
- if (parse_sec(a, &i.age) < 0) {
- log_error("[%s:%u] Invalid age '%s'.", fname, line, age);
- return -EBADMSG;
- }
-
- i.age_set = true;
- }
-
- h = needs_glob(i.type) ? globs : items;
-
- existing = ordered_hashmap_get(h, i.path);
- if (existing) {
- unsigned n;
-
- for (n = 0; n < existing->count; n++) {
- if (!item_compatible(existing->items + n, &i)) {
- log_warning("[%s:%u] Duplicate line for path \"%s\", ignoring.",
- fname, line, i.path);
- return 0;
- }
- }
- } else {
- existing = new0(ItemArray, 1);
- r = ordered_hashmap_put(h, i.path, existing);
- if (r < 0)
- return log_oom();
- }
-
- if (!GREEDY_REALLOC(existing->items, existing->size, existing->count + 1))
- return log_oom();
-
- memcpy(existing->items + existing->count++, &i, sizeof(i));
-
- /* Sort item array, to enforce stable ordering of application */
- qsort_safe(existing->items, existing->count, sizeof(Item), item_compare);
-
- zero(i);
- return 0;
-}
-
-static void help(void) {
- printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
- "Creates, deletes and cleans up volatile and temporary files and directories.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --create Create marked files/directories\n"
- " --clean Clean up marked directories\n"
- " --remove Remove marked files/directories\n"
- " --boot Execute actions only safe at boot\n"
- " --prefix=PATH Only apply rules with the specified prefix\n"
- " --exclude-prefix=PATH Ignore rules with the specified prefix\n"
- " --root=PATH Operate on an alternate filesystem root\n",
- program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
-
- enum {
- ARG_VERSION = 0x100,
- ARG_CREATE,
- ARG_CLEAN,
- ARG_REMOVE,
- ARG_BOOT,
- ARG_PREFIX,
- ARG_EXCLUDE_PREFIX,
- ARG_ROOT,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "create", no_argument, NULL, ARG_CREATE },
- { "clean", no_argument, NULL, ARG_CLEAN },
- { "remove", no_argument, NULL, ARG_REMOVE },
- { "boot", no_argument, NULL, ARG_BOOT },
- { "prefix", required_argument, NULL, ARG_PREFIX },
- { "exclude-prefix", required_argument, NULL, ARG_EXCLUDE_PREFIX },
- { "root", required_argument, NULL, ARG_ROOT },
- {}
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
-
- switch (c) {
-
- case 'h':
- help();
- return 0;
-
- case ARG_VERSION:
- return version();
-
- case ARG_CREATE:
- arg_create = true;
- break;
-
- case ARG_CLEAN:
- arg_clean = true;
- break;
-
- case ARG_REMOVE:
- arg_remove = true;
- break;
-
- case ARG_BOOT:
- arg_boot = true;
- break;
-
- case ARG_PREFIX:
- if (strv_push(&arg_include_prefixes, optarg) < 0)
- return log_oom();
- break;
-
- case ARG_EXCLUDE_PREFIX:
- if (strv_push(&arg_exclude_prefixes, optarg) < 0)
- return log_oom();
- break;
-
- case ARG_ROOT:
- r = parse_path_argument_and_warn(optarg, true, &arg_root);
- if (r < 0)
- return r;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (!arg_clean && !arg_create && !arg_remove) {
- log_error("You need to specify at least one of --clean, --create or --remove.");
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int read_config_file(const char *fn, bool ignore_enoent) {
- _cleanup_fclose_ FILE *_f = NULL;
- FILE *f;
- char line[LINE_MAX];
- Iterator iterator;
- unsigned v = 0;
- Item *i;
- int r = 0;
-
- assert(fn);
-
- if (streq(fn, "-")) {
- log_debug("Reading config from stdin.");
- fn = "<stdin>";
- f = stdin;
- } else {
- r = search_and_fopen_nulstr(fn, "re", arg_root, conf_file_dirs, &_f);
- if (r < 0) {
- if (ignore_enoent && r == -ENOENT) {
- log_debug_errno(r, "Failed to open \"%s\", ignoring: %m", fn);
- return 0;
- }
-
- return log_error_errno(r, "Failed to open '%s': %m", fn);
- }
- log_debug("Reading config file \"%s\".", fn);
- f = _f;
- }
-
- FOREACH_LINE(line, f, break) {
- char *l;
- int k;
-
- v++;
-
- l = strstrip(line);
- if (*l == '#' || *l == 0)
- continue;
-
- k = parse_line(fn, v, l);
- if (k < 0 && r == 0)
- r = k;
- }
-
- /* we have to determine age parameter for each entry of type X */
- ORDERED_HASHMAP_FOREACH(i, globs, iterator) {
- Iterator iter;
- Item *j, *candidate_item = NULL;
-
- if (i->type != IGNORE_DIRECTORY_PATH)
- continue;
-
- ORDERED_HASHMAP_FOREACH(j, items, iter) {
- if (!IN_SET(j->type, CREATE_DIRECTORY, TRUNCATE_DIRECTORY, CREATE_SUBVOLUME, CREATE_SUBVOLUME_INHERIT_QUOTA, CREATE_SUBVOLUME_NEW_QUOTA))
- continue;
-
- if (path_equal(j->path, i->path)) {
- candidate_item = j;
- break;
- }
-
- if ((!candidate_item && path_startswith(i->path, j->path)) ||
- (candidate_item && path_startswith(j->path, candidate_item->path) && (fnmatch(i->path, j->path, FNM_PATHNAME | FNM_PERIOD) == 0)))
- candidate_item = j;
- }
-
- if (candidate_item && candidate_item->age_set) {
- i->age = candidate_item->age;
- i->age_set = true;
- }
- }
-
- if (ferror(f)) {
- log_error_errno(errno, "Failed to read from file %s: %m", fn);
- if (r == 0)
- r = -EIO;
- }
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- int r, k;
- ItemArray *a;
- Iterator iterator;
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- mac_selinux_init();
-
- items = ordered_hashmap_new(&string_hash_ops);
- globs = ordered_hashmap_new(&string_hash_ops);
-
- if (!items || !globs) {
- r = log_oom();
- goto finish;
- }
-
- r = 0;
-
- if (optind < argc) {
- int j;
-
- for (j = optind; j < argc; j++) {
- k = read_config_file(argv[j], false);
- if (k < 0 && r == 0)
- r = k;
- }
-
- } else {
- _cleanup_strv_free_ char **files = NULL;
- char **f;
-
- r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
- if (r < 0) {
- log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
- goto finish;
- }
-
- STRV_FOREACH(f, files) {
- k = read_config_file(*f, true);
- if (k < 0 && r == 0)
- r = k;
- }
- }
-
- /* The non-globbing ones usually create things, hence we apply
- * them first */
- ORDERED_HASHMAP_FOREACH(a, items, iterator) {
- k = process_item_array(a);
- if (k < 0 && r == 0)
- r = k;
- }
-
- /* The globbing ones usually alter things, hence we apply them
- * second. */
- ORDERED_HASHMAP_FOREACH(a, globs, iterator) {
- k = process_item_array(a);
- if (k < 0 && r == 0)
- r = k;
- }
-
-finish:
- while ((a = ordered_hashmap_steal_first(items)))
- item_array_free(a);
-
- while ((a = ordered_hashmap_steal_first(globs)))
- item_array_free(a);
-
- ordered_hashmap_free(items);
- ordered_hashmap_free(globs);
-
- free(arg_include_prefixes);
- free(arg_exclude_prefixes);
- free(arg_root);
-
- set_free_free(unix_sockets);
-
- mac_selinux_finish();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-update-done/Makefile b/src/grp-initutils/systemd-update-done/Makefile
deleted file mode 100644
index 90cb440874..0000000000
--- a/src/grp-initutils/systemd-update-done/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-rootlibexec_PROGRAMS += systemd-update-done
-
-systemd_update_done_SOURCES = \
- src/update-done/update-done.c
-
-systemd_update_done_LDADD = \
- libshared.la
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-update-done/update-done.c b/src/grp-initutils/systemd-update-done/update-done.c
deleted file mode 100644
index 39d19ec048..0000000000
--- a/src/grp-initutils/systemd-update-done/update-done.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/fd-util.h"
-#include "basic/io-util.h"
-#include "basic/selinux-util.h"
-#include "basic/util.h"
-
-#define MESSAGE \
- "This file was created by systemd-update-done. Its only \n" \
- "purpose is to hold a timestamp of the time this directory\n" \
- "was updated. See systemd-update-done.service(8).\n"
-
-static int apply_timestamp(const char *path, struct timespec *ts) {
- struct timespec twice[2] = {
- *ts,
- *ts
- };
- struct stat st;
-
- assert(path);
- assert(ts);
-
- if (stat(path, &st) >= 0) {
- /* Is the timestamp file already newer than the OS? If
- * so, there's nothing to do. We ignore the nanosecond
- * component of the timestamp, since some file systems
- * do not support any better accuracy than 1s and we
- * have no way to identify the accuracy
- * available. Most notably ext4 on small disks (where
- * 128 byte inodes are used) does not support better
- * accuracy than 1s. */
- if (st.st_mtim.tv_sec > ts->tv_sec)
- return 0;
-
- /* It is older? Then let's update it */
- if (utimensat(AT_FDCWD, path, twice, AT_SYMLINK_NOFOLLOW) < 0) {
-
- if (errno == EROFS)
- return log_debug("Can't update timestamp file %s, file system is read-only.", path);
-
- return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
- }
-
- } else if (errno == ENOENT) {
- _cleanup_close_ int fd = -1;
- int r;
-
- /* The timestamp file doesn't exist yet? Then let's create it. */
-
- r = mac_selinux_create_file_prepare(path, S_IFREG);
- if (r < 0)
- return log_error_errno(r, "Failed to set SELinux context for %s: %m", path);
-
- fd = open(path, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, 0644);
- mac_selinux_create_file_clear();
-
- if (fd < 0) {
- if (errno == EROFS)
- return log_debug("Can't create timestamp file %s, file system is read-only.", path);
-
- return log_error_errno(errno, "Failed to create timestamp file %s: %m", path);
- }
-
- (void) loop_write(fd, MESSAGE, strlen(MESSAGE), false);
-
- if (futimens(fd, twice) < 0)
- return log_error_errno(errno, "Failed to update timestamp on %s: %m", path);
- } else
- log_error_errno(errno, "Failed to stat() timestamp file %s: %m", path);
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- struct stat st;
- int r, q = 0;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- if (stat("/usr", &st) < 0) {
- log_error_errno(errno, "Failed to stat /usr: %m");
- return EXIT_FAILURE;
- }
-
- r = mac_selinux_init();
- if (r < 0) {
- log_error_errno(r, "SELinux setup failed: %m");
- goto finish;
- }
-
- r = apply_timestamp("/etc/.updated", &st.st_mtim);
- q = apply_timestamp("/var/.updated", &st.st_mtim);
-
-finish:
- return r < 0 || q < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-update-utmp/Makefile b/src/grp-initutils/systemd-update-utmp/Makefile
deleted file mode 100644
index 0107808281..0000000000
--- a/src/grp-initutils/systemd-update-utmp/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(HAVE_UTMP),)
-rootlibexec_PROGRAMS += \
- systemd-update-utmp
-endif # HAVE_UTMP
-
-systemd_update_utmp_SOURCES = \
- src/update-utmp/update-utmp.c
-
-systemd_update_utmp_CFLAGS = \
- $(AM_CFLAGS) \
- $(AUDIT_CFLAGS)
-
-systemd_update_utmp_LDADD = \
- libshared.la \
- $(AUDIT_LIBS)
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-update-utmp/update-utmp.c b/src/grp-initutils/systemd-update-utmp/update-utmp.c
deleted file mode 100644
index 69264c3a26..0000000000
--- a/src/grp-initutils/systemd-update-utmp/update-utmp.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-#include <systemd/sd-bus.h>
-
-#include "basic/alloc-util.h"
-#include "sd-bus/bus-error.h"
-#include "shared/bus-util.h"
-#include "basic/formats-util.h"
-#include "basic/log.h"
-#include "basic/macro.h"
-#include "basic/special.h"
-#include "basic/unit-name.h"
-#include "basic/util.h"
-#include "shared/utmp-wtmp.h"
-
-typedef struct Context {
- sd_bus *bus;
-#ifdef HAVE_AUDIT
- int audit_fd;
-#endif
-} Context;
-
-static usec_t get_startup_time(Context *c) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- usec_t t = 0;
- int r;
-
- assert(c);
-
- r = sd_bus_get_property_trivial(
- c->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "UserspaceTimestamp",
- &error,
- 't', &t);
- if (r < 0) {
- log_error_errno(r, "Failed to get timestamp: %s", bus_error_message(&error, r));
- return 0;
- }
-
- return t;
-}
-
-static int get_current_runlevel(Context *c) {
- static const struct {
- const int runlevel;
- const char *special;
- } table[] = {
- /* The first target of this list that is active or has
- * a job scheduled wins. We prefer runlevels 5 and 3
- * here over the others, since these are the main
- * runlevels used on Fedora. It might make sense to
- * change the order on some distributions. */
- { '5', SPECIAL_GRAPHICAL_TARGET },
- { '3', SPECIAL_MULTI_USER_TARGET },
- { '1', SPECIAL_RESCUE_TARGET },
- };
-
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
- unsigned i;
-
- assert(c);
-
- for (i = 0; i < ELEMENTSOF(table); i++) {
- _cleanup_free_ char *state = NULL, *path = NULL;
-
- path = unit_dbus_path_from_name(table[i].special);
- if (!path)
- return log_oom();
-
- r = sd_bus_get_property_string(
- c->bus,
- "org.freedesktop.systemd1",
- path,
- "org.freedesktop.systemd1.Unit",
- "ActiveState",
- &error,
- &state);
- if (r < 0)
- return log_warning_errno(r, "Failed to get state: %s", bus_error_message(&error, r));
-
- if (streq(state, "active") || streq(state, "reloading"))
- return table[i].runlevel;
- }
-
- return 0;
-}
-
-static int on_reboot(Context *c) {
- int r = 0, q;
- usec_t t;
-
- assert(c);
-
- /* We finished start-up, so let's write the utmp
- * record and send the audit msg */
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0)
- if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_BOOT, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
- errno != EPERM) {
- r = log_error_errno(errno, "Failed to send audit message: %m");
- }
-#endif
-
- /* If this call fails it will return 0, which
- * utmp_put_reboot() will then fix to the current time */
- t = get_startup_time(c);
-
- q = utmp_put_reboot(t);
- if (q < 0) {
- log_error_errno(q, "Failed to write utmp record: %m");
- r = q;
- }
-
- return r;
-}
-
-static int on_shutdown(Context *c) {
- int r = 0, q;
-
- assert(c);
-
- /* We started shut-down, so let's write the utmp
- * record and send the audit msg */
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0)
- if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_SHUTDOWN, "", "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 &&
- errno != EPERM) {
- r = log_error_errno(errno, "Failed to send audit message: %m");
- }
-#endif
-
- q = utmp_put_shutdown();
- if (q < 0) {
- log_error_errno(q, "Failed to write utmp record: %m");
- r = q;
- }
-
- return r;
-}
-
-static int on_runlevel(Context *c) {
- int r = 0, q, previous, runlevel;
-
- assert(c);
-
- /* We finished changing runlevel, so let's write the
- * utmp record and send the audit msg */
-
- /* First, get last runlevel */
- q = utmp_get_runlevel(&previous, NULL);
-
- if (q < 0) {
- if (q != -ESRCH && q != -ENOENT)
- return log_error_errno(q, "Failed to get current runlevel: %m");
-
- previous = 0;
- }
-
- /* Secondly, get new runlevel */
- runlevel = get_current_runlevel(c);
-
- if (runlevel < 0)
- return runlevel;
-
- if (previous == runlevel)
- return 0;
-
-#ifdef HAVE_AUDIT
- if (c->audit_fd >= 0) {
- _cleanup_free_ char *s = NULL;
-
- if (asprintf(&s, "old-level=%c new-level=%c",
- previous > 0 ? previous : 'N',
- runlevel > 0 ? runlevel : 'N') < 0)
- return log_oom();
-
- if (audit_log_user_comm_message(c->audit_fd, AUDIT_SYSTEM_RUNLEVEL, s, "systemd-update-utmp", NULL, NULL, NULL, 1) < 0 && errno != EPERM)
- r = log_error_errno(errno, "Failed to send audit message: %m");
- }
-#endif
-
- q = utmp_put_runlevel(runlevel, previous);
- if (q < 0 && q != -ESRCH && q != -ENOENT) {
- log_error_errno(q, "Failed to write utmp record: %m");
- r = q;
- }
-
- return r;
-}
-
-int main(int argc, char *argv[]) {
- Context c = {
-#ifdef HAVE_AUDIT
- .audit_fd = -1
-#endif
- };
- int r;
-
- if (getppid() != 1) {
- log_error("This program should be invoked by init only.");
- return EXIT_FAILURE;
- }
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
-#ifdef HAVE_AUDIT
- /* If the kernel lacks netlink or audit support,
- * don't worry about it. */
- c.audit_fd = audit_open();
- if (c.audit_fd < 0 && errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
- log_error_errno(errno, "Failed to connect to audit log: %m");
-#endif
- r = bus_connect_system_systemd(&c.bus);
- if (r < 0) {
- log_error_errno(r, "Failed to get D-Bus connection: %m");
- r = -EIO;
- goto finish;
- }
-
- log_debug("systemd-update-utmp running as pid "PID_FMT, getpid());
-
- if (streq(argv[1], "reboot"))
- r = on_reboot(&c);
- else if (streq(argv[1], "shutdown"))
- r = on_shutdown(&c);
- else if (streq(argv[1], "runlevel"))
- r = on_runlevel(&c);
- else {
- log_error("Unknown command %s", argv[1]);
- r = -EINVAL;
- }
-
- log_debug("systemd-update-utmp stopped as pid "PID_FMT, getpid());
-
-finish:
-#ifdef HAVE_AUDIT
- if (c.audit_fd >= 0)
- audit_close(c.audit_fd);
-#endif
-
- sd_bus_flush_close_unref(c.bus);
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-user-sessions/Makefile b/src/grp-initutils/systemd-user-sessions/Makefile
deleted file mode 100644
index 66fa3b7059..0000000000
--- a/src/grp-initutils/systemd-user-sessions/Makefile
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(HAVE_PAM),)
-
-systemd_user_sessions_SOURCES = \
- src/user-sessions/user-sessions.c
-
-systemd_user_sessions_LDADD = \
- libshared.la
-
-rootlibexec_PROGRAMS += \
- systemd-user-sessions
-
-nodist_systemunit_DATA += \
- units/systemd-user-sessions.service
-
-MULTI_USER_TARGET_WANTS += \
- systemd-user-sessions.service
-
-endif # HAVE_PAM
-
-EXTRA_DIST += \
- units/systemd-user-sessions.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-user-sessions/user-sessions.c b/src/grp-initutils/systemd-user-sessions/user-sessions.c
deleted file mode 100644
index 639c0200e6..0000000000
--- a/src/grp-initutils/systemd-user-sessions/user-sessions.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <unistd.h>
-
-#include "basic/fileio-label.h"
-#include "basic/fileio.h"
-#include "basic/log.h"
-#include "basic/selinux-util.h"
-#include "basic/string-util.h"
-#include "basic/util.h"
-
-int main(int argc, char*argv[]) {
-
- if (argc != 2) {
- log_error("This program requires one argument.");
- return EXIT_FAILURE;
- }
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- mac_selinux_init();
-
- if (streq(argv[1], "start")) {
- int r = 0;
-
- if (unlink("/run/nologin") < 0 && errno != ENOENT)
- r = log_error_errno(errno,
- "Failed to remove /run/nologin file: %m");
-
- if (unlink("/etc/nologin") < 0 && errno != ENOENT) {
- /* If the file doesn't exist and /etc simply
- * was read-only (in which case unlink()
- * returns EROFS even if the file doesn't
- * exist), don't complain */
-
- if (errno != EROFS || access("/etc/nologin", F_OK) >= 0) {
- log_error_errno(errno, "Failed to remove /etc/nologin file: %m");
- return EXIT_FAILURE;
- }
- }
-
- if (r < 0)
- return EXIT_FAILURE;
-
- } else if (streq(argv[1], "stop")) {
- int r;
-
- r = write_string_file_atomic_label("/run/nologin", "System is going down.");
- if (r < 0) {
- log_error_errno(r, "Failed to create /run/nologin: %m");
- return EXIT_FAILURE;
- }
-
- } else {
- log_error("Unknown verb %s.", argv[1]);
- return EXIT_FAILURE;
- }
-
- mac_selinux_finish();
-
- return EXIT_SUCCESS;
-}
diff --git a/src/grp-initutils/systemd-vconsole-setup/.gitignore b/src/grp-initutils/systemd-vconsole-setup/.gitignore
deleted file mode 100644
index 82741b2fb3..0000000000
--- a/src/grp-initutils/systemd-vconsole-setup/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/90-vconsole.rules
diff --git a/src/grp-initutils/systemd-vconsole-setup/90-vconsole.rules.in b/src/grp-initutils/systemd-vconsole-setup/90-vconsole.rules.in
deleted file mode 100644
index 35b9ad5151..0000000000
--- a/src/grp-initutils/systemd-vconsole-setup/90-vconsole.rules.in
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-# Each vtcon keeps its own state of fonts.
-#
-ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon*", RUN+="@rootlibexecdir@/systemd-vconsole-setup"
diff --git a/src/grp-initutils/systemd-vconsole-setup/Makefile b/src/grp-initutils/systemd-vconsole-setup/Makefile
deleted file mode 100644
index 99b369967e..0000000000
--- a/src/grp-initutils/systemd-vconsole-setup/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- Mode: makefile; indent-tabs-mode: t -*-
-#
-# This file is part of systemd.
-#
-# Copyright 2010-2012 Lennart Poettering
-# Copyright 2010-2012 Kay Sievers
-# Copyright 2013 Zbigniew Jędrzejewski-Szmek
-# Copyright 2013 David Strauss
-# Copyright 2016 Luke Shumaker
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# systemd is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with systemd; If not, see <http://www.gnu.org/licenses/>.
-include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
-include $(topsrcdir)/build-aux/Makefile.head.mk
-
-ifneq ($(ENABLE_VCONSOLE),)
-systemd_vconsole_setup_SOURCES = \
- src/vconsole/vconsole-setup.c
-
-systemd_vconsole_setup_LDADD = \
- libshared.la
-
-rootlibexec_PROGRAMS += \
- systemd-vconsole-setup
-
-nodist_udevrules_DATA += \
- src/vconsole/90-vconsole.rules
-
-nodist_systemunit_DATA += \
- units/systemd-vconsole-setup.service
-
-SYSINIT_TARGET_WANTS += \
- systemd-vconsole-setup.service
-endif # ENABLE_VCONSOLE
-
-EXTRA_DIST += \
- src/vconsole/90-vconsole.rules.in \
- units/systemd-vconsole-setup.service.in
-
-include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-initutils/systemd-vconsole-setup/vconsole-setup.c b/src/grp-initutils/systemd-vconsole-setup/vconsole-setup.c
deleted file mode 100644
index 87c0c2f066..0000000000
--- a/src/grp-initutils/systemd-vconsole-setup/vconsole-setup.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Kay Sievers
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <linux/kd.h>
-#include <linux/tiocl.h>
-#include <linux/vt.h>
-
-#include "basic/alloc-util.h"
-#include "basic/fd-util.h"
-#include "basic/fileio.h"
-#include "basic/io-util.h"
-#include "basic/locale-util.h"
-#include "basic/log.h"
-#include "basic/process-util.h"
-#include "basic/signal-util.h"
-#include "basic/stdio-util.h"
-#include "basic/string-util.h"
-#include "basic/terminal-util.h"
-#include "basic/util.h"
-#include "basic/virt.h"
-
-static bool is_vconsole(int fd) {
- unsigned char data[1];
-
- data[0] = TIOCL_GETFGCONSOLE;
- return ioctl(fd, TIOCLINUX, data) >= 0;
-}
-
-static int disable_utf8(int fd) {
- int r = 0, k;
-
- if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
- r = -errno;
-
- k = loop_write(fd, "\033%@", 3, false);
- if (k < 0)
- r = k;
-
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0);
- if (k < 0)
- r = k;
-
- if (r < 0)
- log_warning_errno(r, "Failed to disable UTF-8: %m");
-
- return r;
-}
-
-static int enable_utf8(int fd) {
- int r = 0, k;
- long current = 0;
-
- if (ioctl(fd, KDGKBMODE, &current) < 0 || current == K_XLATE) {
- /*
- * Change the current keyboard to unicode, unless it
- * is currently in raw or off mode anyway. We
- * shouldn't interfere with X11's processing of the
- * key events.
- *
- * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
- *
- */
-
- if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0)
- r = -errno;
- }
-
- k = loop_write(fd, "\033%G", 3, false);
- if (k < 0)
- r = k;
-
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0);
- if (k < 0)
- r = k;
-
- if (r < 0)
- log_warning_errno(r, "Failed to enable UTF-8: %m");
-
- return r;
-}
-
-static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) {
- const char *args[8];
- int i = 0, r;
- pid_t pid;
-
- /* An empty map means kernel map */
- if (isempty(map))
- return 1;
-
- args[i++] = KBD_LOADKEYS;
- args[i++] = "-q";
- args[i++] = "-C";
- args[i++] = vc;
- if (utf8)
- args[i++] = "-u";
- args[i++] = map;
- if (map_toggle)
- args[i++] = map_toggle;
- args[i++] = NULL;
-
- pid = fork();
- if (pid < 0)
- return log_error_errno(errno, "Failed to fork: %m");
- else if (pid == 0) {
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- execv(args[0], (char **) args);
- _exit(EXIT_FAILURE);
- }
-
- r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true);
- if (r < 0)
- return r;
-
- return r == 0;
-}
-
-static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) {
- const char *args[9];
- int i = 0, r;
- pid_t pid;
-
- /* An empty font means kernel font */
- if (isempty(font))
- return 1;
-
- args[i++] = KBD_SETFONT;
- args[i++] = "-C";
- args[i++] = vc;
- args[i++] = font;
- if (map) {
- args[i++] = "-m";
- args[i++] = map;
- }
- if (unimap) {
- args[i++] = "-u";
- args[i++] = unimap;
- }
- args[i++] = NULL;
-
- pid = fork();
- if (pid < 0)
- return log_error_errno(errno, "Failed to fork: %m");
- else if (pid == 0) {
-
- (void) reset_all_signal_handlers();
- (void) reset_signal_mask();
-
- execv(args[0], (char **) args);
- _exit(EXIT_FAILURE);
- }
-
- r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true);
- if (r < 0)
- return r;
-
- return r == 0;
-}
-
-/*
- * A newly allocated VT uses the font from the active VT. Here
- * we update all possibly already allocated VTs with the configured
- * font. It also allows to restart systemd-vconsole-setup.service,
- * to apply a new font to all VTs.
- */
-static void font_copy_to_all_vcs(int fd) {
- struct vt_stat vcs = {};
- unsigned char map8[E_TABSZ];
- unsigned short map16[E_TABSZ];
- struct unimapdesc unimapd;
- _cleanup_free_ struct unipair* unipairs = NULL;
- int i, r;
-
- unipairs = new(struct unipair, USHRT_MAX);
- if (!unipairs) {
- log_oom();
- return;
- }
-
- /* get active, and 16 bit mask of used VT numbers */
- r = ioctl(fd, VT_GETSTATE, &vcs);
- if (r < 0) {
- log_debug_errno(errno, "VT_GETSTATE failed, ignoring: %m");
- return;
- }
-
- for (i = 1; i <= 15; i++) {
- char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)];
- _cleanup_close_ int vcfd = -1;
- struct console_font_op cfo = {};
-
- if (i == vcs.v_active)
- continue;
-
- /* skip non-allocated ttys */
- xsprintf(vcname, "/dev/vcs%i", i);
- if (access(vcname, F_OK) < 0)
- continue;
-
- xsprintf(vcname, "/dev/tty%i", i);
- vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC);
- if (vcfd < 0)
- continue;
-
- /* copy font from active VT, where the font was uploaded to */
- cfo.op = KD_FONT_OP_COPY;
- cfo.height = vcs.v_active-1; /* tty1 == index 0 */
- (void) ioctl(vcfd, KDFONTOP, &cfo);
-
- /* copy map of 8bit chars */
- if (ioctl(fd, GIO_SCRNMAP, map8) >= 0)
- (void) ioctl(vcfd, PIO_SCRNMAP, map8);
-
- /* copy map of 8bit chars -> 16bit Unicode values */
- if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0)
- (void) ioctl(vcfd, PIO_UNISCRNMAP, map16);
-
- /* copy unicode translation table */
- /* unimapd is a ushort count and a pointer to an
- array of struct unipair { ushort, ushort } */
- unimapd.entries = unipairs;
- unimapd.entry_ct = USHRT_MAX;
- if (ioctl(fd, GIO_UNIMAP, &unimapd) >= 0) {
- struct unimapinit adv = { 0, 0, 0 };
-
- (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv);
- (void) ioctl(vcfd, PIO_UNIMAP, &unimapd);
- }
- }
-}
-
-int main(int argc, char **argv) {
- const char *vc;
- _cleanup_free_ char
- *vc_keymap = NULL, *vc_keymap_toggle = NULL,
- *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL;
- _cleanup_close_ int fd = -1;
- bool utf8, font_copy = false, font_ok, keyboard_ok;
- int r = EXIT_FAILURE;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- umask(0022);
-
- if (argv[1])
- vc = argv[1];
- else {
- vc = "/dev/tty0";
- font_copy = true;
- }
-
- fd = open_terminal(vc, O_RDWR|O_CLOEXEC);
- if (fd < 0) {
- log_error_errno(fd, "Failed to open %s: %m", vc);
- return EXIT_FAILURE;
- }
-
- if (!is_vconsole(fd)) {
- log_error("Device %s is not a virtual console.", vc);
- return EXIT_FAILURE;
- }
-
- utf8 = is_locale_utf8();
-
- r = parse_env_file("/etc/vconsole.conf", NEWLINE,
- "KEYMAP", &vc_keymap,
- "KEYMAP_TOGGLE", &vc_keymap_toggle,
- "FONT", &vc_font,
- "FONT_MAP", &vc_font_map,
- "FONT_UNIMAP", &vc_font_unimap,
- NULL);
-
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read /etc/vconsole.conf: %m");
-
- /* Let the kernel command line override /etc/vconsole.conf */
- if (detect_container() <= 0) {
- r = parse_env_file("/proc/cmdline", WHITESPACE,
- "vconsole.keymap", &vc_keymap,
- "vconsole.keymap.toggle", &vc_keymap_toggle,
- "vconsole.font", &vc_font,
- "vconsole.font.map", &vc_font_map,
- "vconsole.font.unimap", &vc_font_unimap,
- NULL);
-
- if (r < 0 && r != -ENOENT)
- log_warning_errno(r, "Failed to read /proc/cmdline: %m");
- }
-
- if (utf8)
- (void) enable_utf8(fd);
- else
- (void) disable_utf8(fd);
-
- font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0;
- keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0;
-
- /* Only copy the font when we executed setfont successfully */
- if (font_copy && font_ok)
- (void) font_copy_to_all_vcs(fd);
-
- return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}