diff options
author | Michael Biebl <biebl@debian.org> | 2018-06-22 13:38:31 +0200 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2018-06-22 13:38:31 +0200 |
commit | b012e92123bdc9fa10c2f079ec5bd9313b23e21a (patch) | |
tree | 94b74f04796e0da187092db7c2487aaf30f0faf1 /src/shared | |
parent | 98393f852f2f66a74f7370aa63c07b26d610343c (diff) | |
download | systemd-b012e92123bdc9fa10c2f079ec5bd9313b23e21a.tar.gz |
New upstream version 239
Diffstat (limited to 'src/shared')
111 files changed, 2186 insertions, 3304 deletions
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c index 889a971d88..1eaf653103 100644 --- a/src/shared/acl-util.c +++ b/src/shared/acl-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2011,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 <errno.h> #include <stdbool.h> @@ -217,10 +199,8 @@ int acl_search_groups(const char *path, char ***ret_groups) { r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } - if (ret_groups) { - *ret_groups = g; - g = NULL; - } + if (ret_groups) + *ret_groups = TAKE_PTR(g); return ret; } @@ -287,9 +267,8 @@ int parse_acl(const char *text, acl_t *acl_access, acl_t *acl_default, bool want } } - *acl_access = a_acl; - *acl_default = d_acl; - a_acl = d_acl = NULL; + *acl_access = TAKE_PTR(a_acl); + *acl_default = TAKE_PTR(d_acl); return 0; } @@ -393,8 +372,8 @@ int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl) { if (r < 0) return -errno; - *acl = old; - old = NULL; + *acl = TAKE_PTR(old); + return 0; } diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h index 6b581cbc42..10b2a3d9f0 100644 --- a/src/shared/acl-util.h +++ b/src/shared/acl-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2011 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/>. -***/ - #if HAVE_ACL #include <acl/libacl.h> diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c index 1a640f4f1b..d565ebd43e 100644 --- a/src/shared/acpi-fpdt.c +++ b/src/shared/acpi-fpdt.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2013 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> diff --git a/src/shared/acpi-fpdt.h b/src/shared/acpi-fpdt.h index 4521a1e686..47bfefc5a0 100644 --- a/src/shared/acpi-fpdt.h +++ b/src/shared/acpi-fpdt.h @@ -1,24 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2013 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 <time-util.h> diff --git a/src/shared/apparmor-util.c b/src/shared/apparmor-util.c index e9c4081892..c4a4b04d22 100644 --- a/src/shared/apparmor-util.c +++ b/src/shared/apparmor-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <stddef.h> diff --git a/src/shared/apparmor-util.h b/src/shared/apparmor-util.h index 33ebd4d612..7fbaf90dcc 100644 --- a/src/shared/apparmor-util.h +++ b/src/shared/apparmor-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> bool mac_apparmor_use(void); diff --git a/src/shared/ask-password-api.c b/src/shared/ask-password-api.c index 4fa9188957..682dc754fc 100644 --- a/src/shared/ask-password-api.c +++ b/src/shared/ask-password-api.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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> @@ -730,8 +712,7 @@ int ask_password_agent( if (keyname) (void) add_to_keyring_and_log(keyname, flags, l); - *ret = l; - l = NULL; + *ret = TAKE_PTR(l); r = 0; finish: diff --git a/src/shared/ask-password-api.h b/src/shared/ask-password-api.h index 4b2eb3fe92..93ca8bff52 100644 --- a/src/shared/ask-password-api.h +++ b/src/shared/ask-password-api.h @@ -1,37 +1,18 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include "time-util.h" typedef enum AskPasswordFlags { - ASK_PASSWORD_ACCEPT_CACHED = 1U << 0, - ASK_PASSWORD_PUSH_CACHE = 1U << 1, - ASK_PASSWORD_ECHO = 1U << 2, /* show the password literally while reading, instead of "*" */ - ASK_PASSWORD_SILENT = 1U << 3, /* do no show any password at all while reading */ - ASK_PASSWORD_NO_TTY = 1U << 4, - ASK_PASSWORD_NO_AGENT = 1U << 5, - ASK_PASSWORD_CONSOLE_COLOR = 1U << 6, /* Use color if /dev/console points to a console that supports color */ + ASK_PASSWORD_ACCEPT_CACHED = 1 << 0, + ASK_PASSWORD_PUSH_CACHE = 1 << 1, + ASK_PASSWORD_ECHO = 1 << 2, /* show the password literally while reading, instead of "*" */ + ASK_PASSWORD_SILENT = 1 << 3, /* do no show any password at all while reading */ + ASK_PASSWORD_NO_TTY = 1 << 4, + ASK_PASSWORD_NO_AGENT = 1 << 5, + ASK_PASSWORD_CONSOLE_COLOR = 1 << 6, /* Use color if /dev/console points to a console that supports color */ } AskPasswordFlags; int ask_password_tty(int tty_fd, const char *message, const char *keyname, usec_t until, AskPasswordFlags flags, const char *flag_file, char **ret); diff --git a/src/shared/base-filesystem.c b/src/shared/base-filesystem.c index 3c25aa534c..89d7a7d59b 100644 --- a/src/shared/base-filesystem.c +++ b/src/shared/base-filesystem.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2014 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> @@ -63,8 +45,8 @@ static const BaseFilesystem table[] = { int base_filesystem_create(const char *root, uid_t uid, gid_t gid) { _cleanup_close_ int fd = -1; - unsigned i; int r = 0; + size_t i; fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW); if (fd < 0) diff --git a/src/shared/base-filesystem.h b/src/shared/base-filesystem.h index 5d134b4eb9..d1d4eaa662 100644 --- a/src/shared/base-filesystem.h +++ b/src/shared/base-filesystem.h @@ -1,24 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2014 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 <sys/types.h> diff --git a/src/shared/boot-timestamps.c b/src/shared/boot-timestamps.c index 543e01a364..bcbb86d1b1 100644 --- a/src/shared/boot-timestamps.c +++ b/src/shared/boot-timestamps.c @@ -1,23 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2012 Lennart Poettering - Copyright 2013 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 "acpi-fpdt.h" #include "boot-timestamps.h" diff --git a/src/shared/boot-timestamps.h b/src/shared/boot-timestamps.h index 8c67d302b4..c719dd3602 100644 --- a/src/shared/boot-timestamps.h +++ b/src/shared/boot-timestamps.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2012 Lennart Poettering - Copyright 2013 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 <time-util.h> diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 0e3e17a776..47a7dbafbd 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -1,21 +1,4 @@ -/*** - This file is part of systemd. - - Copyright 2017 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/>. -***/ +/* SPDX-License-Identifier: LGPL-2.1+ */ #include <stdio.h> #include <linux/magic.h> @@ -138,13 +121,15 @@ int boot_entry_load(const char *path, BootEntry *entry) { } void boot_config_free(BootConfig *config) { - unsigned i; + size_t i; assert(config); free(config->default_pattern); free(config->timeout); free(config->editor); + free(config->auto_entries); + free(config->auto_firmware); free(config->entry_oneshot); free(config->entry_default); @@ -200,6 +185,12 @@ int boot_loader_read_conf(const char *path, BootConfig *config) { r = free_and_strdup(&config->timeout, p); else if (streq(field, "editor")) r = free_and_strdup(&config->editor, p); + else if (streq(field, "auto-entries")) + r = free_and_strdup(&config->auto_entries, p); + else if (streq(field, "auto-firmware")) + r = free_and_strdup(&config->auto_firmware, p); + else if (streq(field, "console-mode")) + r = free_and_strdup(&config->console_mode, p); else { log_notice("%s:%u: Unknown line \"%s\"", path, line, field); continue; @@ -252,7 +243,7 @@ int boot_entries_find(const char *dir, BootEntry **ret_entries, size_t *ret_n_en } static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) { - unsigned i, j; + size_t i, j; bool non_unique = false; assert(entries || n_entries == 0); @@ -272,7 +263,7 @@ static bool find_nonunique(BootEntry *entries, size_t n_entries, bool *arr) { static int boot_entries_uniquify(BootEntry *entries, size_t n_entries) { char *s; - unsigned i; + size_t i; int r; bool arr[n_entries]; @@ -402,7 +393,7 @@ static int verify_esp( uint64_t *ret_psize, sd_id128_t *ret_uuid) { #if HAVE_BLKID - _cleanup_blkid_free_probe_ blkid_probe b = NULL; + _cleanup_(blkid_free_probep) blkid_probe b = NULL; char t[DEV_NUM_PATH_MAX]; const char *v; #endif diff --git a/src/shared/bootspec.h b/src/shared/bootspec.h index d9c641bf08..f47c073a46 100644 --- a/src/shared/bootspec.h +++ b/src/shared/bootspec.h @@ -1,21 +1,4 @@ -/*** - This file is part of systemd. - - Copyright 2017 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/>. -***/ +/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once @@ -40,6 +23,9 @@ typedef struct BootConfig { char *default_pattern; char *timeout; char *editor; + char *auto_entries; + char *auto_firmware; + char *console_mode; char *entry_oneshot; char *entry_default; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 54b2137c9c..3238b442c0 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 "alloc-util.h" #include "bus-internal.h" @@ -91,8 +73,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { return bus_log_create_error(r); \ \ return 1; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ + } #define DEFINE_BUS_APPEND_PARSE(bus_type, parse_func) \ static int bus_append_##parse_func( \ @@ -113,8 +94,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { return bus_log_create_error(r); \ \ return 1; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ + } DEFINE_BUS_APPEND_PARSE("b", parse_boolean); DEFINE_BUS_APPEND_PARSE("i", ioprio_class_from_string); @@ -124,7 +104,7 @@ DEFINE_BUS_APPEND_PARSE("i", log_level_from_string); DEFINE_BUS_APPEND_PARSE("i", parse_errno); DEFINE_BUS_APPEND_PARSE("i", sched_policy_from_string); DEFINE_BUS_APPEND_PARSE("i", secure_bits_from_string); -DEFINE_BUS_APPEND_PARSE("i", signal_from_string_try_harder); +DEFINE_BUS_APPEND_PARSE("i", signal_from_string); DEFINE_BUS_APPEND_PARSE("i", socket_protocol_from_name); DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, ioprio_parse_priority); DEFINE_BUS_APPEND_PARSE_PTR("i", int32_t, int, parse_nice); @@ -462,7 +442,6 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons return bus_append_safe_atou64(m, field, eq); return bus_append_parse_size(m, field, eq, 1024); - } if (streq(field, "CPUQuota")) { @@ -700,7 +679,8 @@ static int bus_append_automount_property(sd_bus_message *m, const char *field, c } static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) { - int r, rl; + const char *suffix; + int r; if (STR_IN_SET(field, "User", "Group", @@ -714,7 +694,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con if (STR_IN_SET(field, "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", "PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", - "NoNewPrivileges", "SyslogLevelPrefix", + "PrivateMounts", "NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute", "RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables", "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS", "CPUSchedulingResetOnFork", "LockPersonality")) @@ -879,25 +859,29 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con return bus_append_byte_array(m, field, decoded, sz); } - rl = rlimit_from_string(field); - if (rl >= 0) { - const char *sn; - struct rlimit l; + if ((suffix = startswith(field, "Limit"))) { + int rl; - r = rlimit_parse(rl, eq, &l); - if (r < 0) - return log_error_errno(r, "Failed to parse resource limit: %s", eq); + rl = rlimit_from_string(suffix); + if (rl >= 0) { + const char *sn; + struct rlimit l; - r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max); - if (r < 0) - return bus_log_create_error(r); + r = rlimit_parse(rl, eq, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit: %s", eq); - sn = strjoina(field, "Soft"); - r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur); - if (r < 0) - return bus_log_create_error(r); + r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max); + if (r < 0) + return bus_log_create_error(r); - return 1; + sn = strjoina(field, "Soft"); + r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } } if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) { @@ -982,7 +966,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con if (r < 0) return bus_log_create_error(r); - for (p = eq;;) { + for (;;) { _cleanup_free_ char *word = NULL; r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); @@ -1019,12 +1003,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con if (streq(field, "RestrictNamespaces")) { bool invert = false; - unsigned long flags = 0; - - if (eq[0] == '~') { - invert = true; - eq++; - } + unsigned long flags; r = parse_boolean(eq); if (r > 0) @@ -1032,7 +1011,12 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con else if (r == 0) flags = NAMESPACE_FLAGS_ALL; else { - r = namespace_flag_from_string_many(eq, &flags); + if (eq[0] == '~') { + invert = true; + eq++; + } + + r = namespace_flags_from_string(eq, &flags); if (r < 0) return log_error_errno(r, "Failed to parse %s value %s.", field, eq); } @@ -1114,7 +1098,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con } else d = s; - r = sd_bus_message_append(m, "(ssbt)", s, d, ignore_enoent, flags); if (r < 0) return bus_log_create_error(r); @@ -1168,8 +1151,10 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS); if (r < 0) return log_error_errno(r, "Failed to parse argument: %m"); - if (r == 0) - return log_error("Failed to parse argument: %m"); + if (r == 0) { + log_error("Failed to parse argument: %s", p); + return -EINVAL; + } r = sd_bus_message_append(m, "(ss)", path, w); if (r < 0) @@ -1206,7 +1191,7 @@ static int bus_append_kill_property(sd_bus_message *m, const char *field, const if (streq(field, "KillSignal")) - return bus_append_signal_from_string_try_harder(m, field, eq); + return bus_append_signal_from_string(m, field, eq); return 0; } @@ -1315,7 +1300,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con r = safe_atoi(word, &val); if (r < 0) { - val = signal_from_string_try_harder(word); + val = signal_from_string(word); if (val < 0) return log_error_errno(r, "Invalid status or signal %s in %s: %m", word, field); @@ -1808,8 +1793,7 @@ int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) { if (r < 0) return r; - *ret = d; - d = NULL; + *ret = TAKE_PTR(d); return 0; } @@ -1918,8 +1902,6 @@ finish: } static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { - int r = 0; - assert(d->result); if (!quiet) { @@ -1937,6 +1919,8 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* log_error("Operation on or unit type of %s not supported on this system.", strna(d->name)); else if (streq(d->result, "collected")) log_error("Queued job for %s was garbage collected.", strna(d->name)); + else if (streq(d->result, "once")) + log_error("Unit %s was started already once and can't be started again.", strna(d->name)); else if (!STR_IN_SET(d->result, "done", "skipped")) { if (d->name) { _cleanup_free_ char *result = NULL; @@ -1953,21 +1937,24 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* } if (STR_IN_SET(d->result, "canceled", "collected")) - r = -ECANCELED; + return -ECANCELED; else if (streq(d->result, "timeout")) - r = -ETIME; + return -ETIME; else if (streq(d->result, "dependency")) - r = -EIO; + return -EIO; else if (streq(d->result, "invalid")) - r = -ENOEXEC; + return -ENOEXEC; else if (streq(d->result, "assert")) - r = -EPROTO; + return -EPROTO; else if (streq(d->result, "unsupported")) - r = -EOPNOTSUPP; - else if (!STR_IN_SET(d->result, "done", "skipped")) - r = -EIO; + return -EOPNOTSUPP; + else if (streq(d->result, "once")) + return -ESTALE; + else if (STR_IN_SET(d->result, "done", "skipped")) + return 0; - return r; + log_debug("Unexpected job result, assuming server side newer than us: %s", d->result); + return -EIO; } int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { @@ -2021,7 +2008,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { return bus_wait_for_jobs(d, quiet, NULL); } -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes) { const char *type, *path, *source; int r; @@ -2466,3 +2453,29 @@ finish: return r; } + +int unit_load_state(sd_bus *bus, const char *name, char **load_state) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *path = NULL; + int r; + + path = unit_dbus_path_from_name(name); + if (!path) + return log_oom(); + + /* This function warns on it's own, because otherwise it'd be awkward to pass + * the dbus error message around. */ + + r = sd_bus_get_property_string( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Unit", + "LoadState", + &error, + load_state); + if (r < 0) + return log_error_errno(r, "Failed to get load state of %s: %s", name, bus_error_message(&error, r)); + + return 0; +} diff --git a/src/shared/bus-unit-util.h b/src/shared/bus-unit-util.h index 514e6edb76..4fc94b0f4e 100644 --- a/src/shared/bus-unit-util.h +++ b/src/shared/bus-unit-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 "install.h" #include "output-mode.h" #include "sd-bus.h" @@ -54,6 +35,8 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet); DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free); -int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes); +int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, size_t *n_changes); int unit_show_processes(sd_bus *bus, const char *unit, const char *cgroup_path, const char *prefix, unsigned n_columns, OutputFlags flags, sd_bus_error *error); + +int unit_load_state(sd_bus *bus, const char *name, char **load_state); diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 548e817105..a4f2deba31 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <errno.h> #include <fcntl.h> @@ -604,8 +586,7 @@ int bus_connect_system_systemd(sd_bus **_bus) { if (r < 0) return r; - *_bus = bus; - bus = NULL; + *_bus = TAKE_PTR(bus); return 0; } @@ -642,8 +623,7 @@ int bus_connect_user_systemd(sd_bus **_bus) { if (r < 0) return r; - *_bus = bus; - bus = NULL; + *_bus = TAKE_PTR(bus); return 0; } @@ -656,15 +636,15 @@ int bus_connect_user_systemd(sd_bus **_bus) { printf("%s=" fmt "\n", name, __VA_ARGS__); \ } while (0) -int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) { +int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) { char type; const char *contents; int r; assert(name); - assert(property); + assert(m); - r = sd_bus_message_peek_type(property, &type, &contents); + r = sd_bus_message_peek_type(m, &type, &contents); if (r < 0) return r; @@ -673,7 +653,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_STRING: { const char *s; - r = sd_bus_message_read_basic(property, type, &s); + r = sd_bus_message_read_basic(m, type, &s); if (r < 0) return r; @@ -692,7 +672,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_BOOLEAN: { int b; - r = sd_bus_message_read_basic(property, type, &b); + r = sd_bus_message_read_basic(m, type, &b); if (r < 0) return r; @@ -704,15 +684,17 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_UINT64: { uint64_t u; - r = sd_bus_message_read_basic(property, type, &u); + r = sd_bus_message_read_basic(m, type, &u); if (r < 0) return r; /* Yes, heuristics! But we can change this check * should it turn out to not be sufficient */ - if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) { - char timestamp[FORMAT_TIMESTAMP_MAX], *t; + if (endswith(name, "Timestamp") || + STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec", "TimeUSec", "RTCTimeUSec")) { + char timestamp[FORMAT_TIMESTAMP_MAX]; + const char *t; t = format_timestamp(timestamp, sizeof(timestamp), u); if (t || all) @@ -731,7 +713,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL) result = "no"; else { - r = namespace_flag_to_string_many(u, &s); + r = namespace_flags_to_string(u, &s); if (r < 0) return r; @@ -781,7 +763,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_INT64: { int64_t i; - r = sd_bus_message_read_basic(property, type, &i); + r = sd_bus_message_read_basic(m, type, &i); if (r < 0) return r; @@ -793,7 +775,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_UINT32: { uint32_t u; - r = sd_bus_message_read_basic(property, type, &u); + r = sd_bus_message_read_basic(m, type, &u); if (r < 0) return r; @@ -818,7 +800,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_INT32: { int32_t i; - r = sd_bus_message_read_basic(property, type, &i); + r = sd_bus_message_read_basic(m, type, &i); if (r < 0) return r; @@ -829,7 +811,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b case SD_BUS_TYPE_DOUBLE: { double d; - r = sd_bus_message_read_basic(property, type, &d); + r = sd_bus_message_read_basic(m, type, &d); if (r < 0) return r; @@ -842,18 +824,18 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b bool first = true; const char *str; - r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents); + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents); if (r < 0) return r; - while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { + while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) { bool good; if (first && !value) printf("%s=", name); /* This property has multiple space-separated values, so - * neither spaces not newlines can be allowed in a value. */ + * neither spaces nor newlines can be allowed in a value. */ good = str[strcspn(str, " \n")] == '\0'; printf("%s%s", first ? "" : " ", good ? str : "[unprintable]"); @@ -868,7 +850,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b if (!first || all) puts(""); - r = sd_bus_message_exit_container(property); + r = sd_bus_message_exit_container(m); if (r < 0) return r; @@ -878,7 +860,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b const uint8_t *u; size_t n; - r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n); + r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n); if (r < 0) return r; @@ -900,7 +882,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b uint32_t *u; size_t n; - r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n); + r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n); if (r < 0) return r; @@ -925,81 +907,118 @@ int bus_print_property(const char *name, sd_bus_message *property, bool value, b return 0; } -int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; +int bus_message_print_all_properties( + sd_bus_message *m, + bus_message_print_t func, + char **filter, + bool value, + bool all, + Set **found_properties) { - assert(bus); - assert(path); + int r; - r = sd_bus_call_method(bus, - dest, - path, - "org.freedesktop.DBus.Properties", - "GetAll", - &error, - &reply, - "s", ""); - if (r < 0) - return r; + assert(m); - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}"); + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}"); if (r < 0) return r; - while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { + while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { const char *name; const char *contents; - r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name); + r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name); if (r < 0) return r; + if (found_properties) { + r = set_ensure_allocated(found_properties, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = set_put(*found_properties, name); + if (r < 0 && r != EEXIST) + return log_oom(); + } + if (!filter || strv_find(filter, name)) { - r = sd_bus_message_peek_type(reply, NULL, &contents); + r = sd_bus_message_peek_type(m, NULL, &contents); if (r < 0) return r; - r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents); if (r < 0) return r; - r = bus_print_property(name, reply, value, all); + if (func) + r = func(name, m, value, all); + if (!func || r == 0) + r = bus_print_property(name, m, value, all); if (r < 0) return r; if (r == 0) { if (all) printf("%s=[unprintable]\n", name); /* skip what we didn't read */ - r = sd_bus_message_skip(reply, contents); + r = sd_bus_message_skip(m, contents); if (r < 0) return r; } - r = sd_bus_message_exit_container(reply); + r = sd_bus_message_exit_container(m); if (r < 0) return r; } else { - r = sd_bus_message_skip(reply, "v"); + r = sd_bus_message_skip(m, "v"); if (r < 0) return r; } - r = sd_bus_message_exit_container(reply); + r = sd_bus_message_exit_container(m); if (r < 0) return r; } if (r < 0) return r; - r = sd_bus_message_exit_container(reply); + r = sd_bus_message_exit_container(m); if (r < 0) return r; return 0; } +int bus_print_all_properties( + sd_bus *bus, + const char *dest, + const char *path, + bus_message_print_t func, + char **filter, + bool value, + bool all, + Set **found_properties) { + + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert(bus); + assert(path); + + r = sd_bus_call_method(bus, + dest, + path, + "org.freedesktop.DBus.Properties", + "GetAll", + &error, + &reply, + "s", ""); + if (r < 0) + return r; + + return bus_message_print_all_properties(reply, func, filter, value, all, found_properties); +} + int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { sd_id128_t *p = userdata; const void *v; @@ -1020,7 +1039,7 @@ int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_err return 0; } -static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) { +static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) { char type; int r; @@ -1031,7 +1050,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ switch (type) { case SD_BUS_TYPE_STRING: { - char **p = userdata; + const char **p = userdata; const char *s; r = sd_bus_message_read_basic(m, type, &s); @@ -1041,7 +1060,11 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ if (isempty(s)) s = NULL; - return free_and_strdup(p, s); + if (flags & BUS_MAP_STRDUP) + return free_and_strdup((char **) userdata, s); + + *p = s; + return 0; } case SD_BUS_TYPE_ARRAY: { @@ -1052,21 +1075,21 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ if (r < 0) return r; - strv_free(*p); - *p = l; - l = NULL; - return 0; + return strv_free_and_replace(*p, l); } case SD_BUS_TYPE_BOOLEAN: { - unsigned b; - int *p = userdata; + int b; r = sd_bus_message_read_basic(m, type, &b); if (r < 0) return r; - *p = b; + if (flags & BUS_MAP_BOOLEAN_AS_BOOL) + *(bool*) userdata = b; + else + *(int*) userdata = b; + return 0; } @@ -1111,6 +1134,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ int bus_message_map_all_properties( sd_bus_message *m, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, void *userdata) { @@ -1153,7 +1177,7 @@ int bus_message_map_all_properties( if (map[i].set) r = prop->set(sd_bus_message_get_bus(m), member, m, error, v); else - r = map_basic(sd_bus_message_get_bus(m), member, m, error, v); + r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v); if (r < 0) return r; @@ -1179,6 +1203,7 @@ int bus_message_map_all_properties( int bus_message_map_properties_changed( sd_bus_message *m, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, void *userdata) { @@ -1188,7 +1213,7 @@ int bus_message_map_properties_changed( assert(m); assert(map); - r = bus_message_map_all_properties(m, map, error, userdata); + r = bus_message_map_all_properties(m, map, flags, error, userdata); if (r < 0) return r; @@ -1218,7 +1243,9 @@ int bus_map_all_properties( const char *destination, const char *path, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, + sd_bus_message **reply, void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; @@ -1228,6 +1255,7 @@ int bus_map_all_properties( assert(destination); assert(path); assert(map); + assert(reply || (flags & BUS_MAP_STRDUP)); r = sd_bus_call_method( bus, @@ -1241,7 +1269,14 @@ int bus_map_all_properties( if (r < 0) return r; - return bus_message_map_all_properties(m, map, error, userdata); + r = bus_message_map_all_properties(m, map, flags, error, userdata); + if (r < 0) + return r; + + if (reply) + *reply = sd_bus_message_ref(m); + + return r; } int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) { @@ -1260,9 +1295,15 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s case BUS_TRANSPORT_LOCAL: if (user) r = sd_bus_default_user(&bus); - else - r = sd_bus_default_system(&bus); + else { + if (sd_booted() <= 0) { + /* Print a friendly message when the local system is actually not running systemd as PID 1. */ + log_error("System has not been booted with systemd as init system (PID 1). Can't operate."); + return -EHOSTDOWN; + } + r = sd_bus_default_system(&bus); + } break; case BUS_TRANSPORT_REMOTE: @@ -1283,8 +1324,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s if (r < 0) return r; - *ret = bus; - bus = NULL; + *ret = TAKE_PTR(bus); return 0; } @@ -1304,9 +1344,15 @@ int bus_connect_transport_systemd(BusTransport transport, const char *host, bool case BUS_TRANSPORT_LOCAL: if (user) r = bus_connect_user_systemd(bus); - else - r = bus_connect_system_systemd(bus); + else { + if (sd_booted() <= 0) { + /* Print a friendly message when the local system is actually not running systemd as PID 1. */ + log_error("System has not been booted with systemd as init system (PID 1). Can't operate."); + return -EHOSTDOWN; + } + r = bus_connect_system_systemd(bus); + } break; case BUS_TRANSPORT_REMOTE: @@ -1353,7 +1399,7 @@ int bus_property_set_bool( if (r < 0) return r; - *(bool *) userdata = !!b; + *(bool*) userdata = b; return 0; } @@ -1564,36 +1610,40 @@ int bus_property_get_rlimit( void *userdata, sd_bus_error *error) { + const char *is_soft; struct rlimit *rl; uint64_t u; rlim_t x; - const char *is_soft; assert(bus); assert(reply); assert(userdata); is_soft = endswith(property, "Soft"); + rl = *(struct rlimit**) userdata; if (rl) x = is_soft ? rl->rlim_cur : rl->rlim_max; else { struct rlimit buf = {}; + const char *s, *p; int z; - const char *s; + /* Chop off "Soft" suffix */ s = is_soft ? strndupa(property, is_soft - property) : property; - z = rlimit_from_string(strstr(s, "Limit")); + /* Skip over any prefix, such as "Default" */ + assert_se(p = strstr(s, "Limit")); + + z = rlimit_from_string(p + 5); assert(z >= 0); - getrlimit(z, &buf); + (void) getrlimit(z, &buf); x = is_soft ? buf.rlim_cur : buf.rlim_max; } - /* rlim_t might have different sizes, let's map - * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on - * all archs */ + /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all + * archs */ u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x; return sd_bus_message_append(reply, "t", u); @@ -1618,7 +1668,7 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) { return r; } -int bus_open_system_watch_bind(sd_bus **ret) { +int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) { _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; const char *e; int r; @@ -1631,6 +1681,12 @@ int bus_open_system_watch_bind(sd_bus **ret) { if (r < 0) return r; + if (description) { + r = sd_bus_set_description(bus, description); + if (r < 0) + return r; + } + e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS"); if (!e) e = DEFAULT_SYSTEM_BUS_ADDRESS; @@ -1663,8 +1719,201 @@ int bus_open_system_watch_bind(sd_bus **ret) { if (r < 0) return r; - *ret = bus; - bus = NULL; + *ret = TAKE_PTR(bus); return 0; } + +struct request_name_data { + unsigned n_ref; + + const char *name; + uint64_t flags; + void *userdata; +}; + +static void request_name_destroy_callback(void *userdata) { + struct request_name_data *data = userdata; + + assert(data); + assert(data->n_ref > 0); + + log_info("%s n_ref=%u", __func__, data->n_ref); + + data->n_ref--; + if (data->n_ref == 0) + free(data); +} + +static int reload_dbus_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + struct request_name_data *data = userdata; + const sd_bus_error *e; + int r; + + assert(data); + assert(data->name); + assert(data->n_ref > 0); + + e = sd_bus_message_get_error(m); + if (e) { + log_error_errno(sd_bus_error_get_errno(e), "Failed to reload DBus configuration: %s", e->message); + return 1; + } + + /* Here, use the default request name handler to avoid an infinite loop of reloading and requesting. */ + r = sd_bus_request_name_async(sd_bus_message_get_bus(m), NULL, data->name, data->flags, NULL, data->userdata); + if (r < 0) + log_error_errno(r, "Failed to request name: %m"); + + return 1; +} + +static int request_name_handler_may_reload_dbus(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { + struct request_name_data *data = userdata; + uint32_t ret; + int r; + + assert(m); + assert(data); + + if (sd_bus_message_is_method_error(m, NULL)) { + const sd_bus_error *e = sd_bus_message_get_error(m); + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + + if (!sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED)) { + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, failing connection: %s", + e->message); + + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug_errno(sd_bus_error_get_errno(e), + "Unable to request name, will retry after reloading DBus configuration: %s", + e->message); + + /* If systemd-timesyncd.service enables DynamicUser= and dbus.service + * started before the dynamic user is realized, then the DBus policy + * about timesyncd has not been enabled yet. So, let's try to reload + * DBus configuration, and after that request the name again. Note that it + * seems that no privileges are necessary to call the following method. */ + + r = sd_bus_call_method_async( + sd_bus_message_get_bus(m), + &slot, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "ReloadConfig", + reload_dbus_handler, + data, NULL); + if (r < 0) { + log_error_errno(r, "Failed to reload DBus configuration: %m"); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + data->n_ref ++; + assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0); + + r = sd_bus_slot_set_floating(slot, true); + if (r < 0) + return r; + + return 1; + } + + r = sd_bus_message_read(m, "u", &ret); + if (r < 0) + return r; + + switch (ret) { + + case BUS_NAME_ALREADY_OWNER: + log_debug("Already owner of requested service name, ignoring."); + return 1; + + case BUS_NAME_IN_QUEUE: + log_debug("In queue for requested service name."); + return 1; + + case BUS_NAME_PRIMARY_OWNER: + log_debug("Successfully acquired requested service name."); + return 1; + + case BUS_NAME_EXISTS: + log_debug("Requested service name already owned, failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; + } + + log_debug("Unexpected response from RequestName(), failing connection."); + bus_enter_closing(sd_bus_message_get_bus(m)); + return 1; +} + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata) { + _cleanup_free_ struct request_name_data *data = NULL; + _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; + int r; + + data = new(struct request_name_data, 1); + if (!data) + return -ENOMEM; + + *data = (struct request_name_data) { + .n_ref = 1, + .name = name, + .flags = flags, + .userdata = userdata, + }; + + r = sd_bus_request_name_async(bus, &slot, name, flags, request_name_handler_may_reload_dbus, data); + if (r < 0) + return r; + + assert_se(sd_bus_slot_set_destroy_callback(slot, request_name_destroy_callback) >= 0); + TAKE_PTR(data); + + if (ret_slot) + *ret_slot = TAKE_PTR(slot); + else { + r = sd_bus_slot_set_floating(slot, true); + if (r < 0) + return r; + } + + return 0; +} + +int bus_reply_pair_array(sd_bus_message *m, char **l) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + char **k, **v; + int r; + + assert(m); + + /* Reply to the specified message with a message containing a dictionary put together from the specified + * strv */ + + r = sd_bus_message_new_method_return(m, &reply); + if (r < 0) + return r; + + r = sd_bus_message_open_container(reply, 'a', "{ss}"); + if (r < 0) + return r; + + STRV_FOREACH_PAIR(k, v, l) { + r = sd_bus_message_append(reply, "{ss}", *k, *v); + if (r < 0) + return r; + } + + r = sd_bus_message_close_container(reply); + if (r < 0) + return r; + + return sd_bus_send(NULL, reply, NULL); +} diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index 969a444d83..b400eb81e2 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <stddef.h> #include <stdint.h> @@ -49,11 +30,17 @@ struct bus_properties_map { size_t offset; }; +enum { + BUS_MAP_STRDUP = 1 << 0, /* If set, each "s" message is duplicated. Thus, each pointer needs to be freed. */ + BUS_MAP_BOOLEAN_AS_BOOL = 1 << 1, /* If set, each "b" message is written to a bool pointer. If not set, "b" is written to a int pointer. */ +}; + int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata); -int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); -int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); -int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, sd_bus_error *error, void *userdata); +int bus_message_map_all_properties(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata); +int bus_message_map_properties_changed(sd_bus_message *m, const struct bus_properties_map *map, unsigned flags, sd_bus_error *error, void *userdata); +int bus_map_all_properties(sd_bus *bus, const char *destination, const char *path, const struct bus_properties_map *map, + unsigned flags, sd_bus_error *error, sd_bus_message **reply, void *userdata); int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name); @@ -76,8 +63,11 @@ int bus_connect_user_systemd(sd_bus **_bus); int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus); int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus); +typedef int (*bus_message_print_t) (const char *name, sd_bus_message *m, bool value, bool all); + int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all); -int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all); +int bus_message_print_all_properties(sd_bus_message *m, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); +int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, bus_message_print_t func, char **filter, bool value, bool all, Set **found_properties); int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error); int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error); @@ -89,7 +79,7 @@ int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, assert_cc(sizeof(int) == sizeof(int32_t)); #define bus_property_get_int ((sd_bus_property_get_t) NULL) -assert_cc(sizeof(unsigned) == sizeof(unsigned)); +assert_cc(sizeof(unsigned) == sizeof(uint32_t)); #define bus_property_get_unsigned ((sd_bus_property_get_t) NULL) /* On 64bit machines we can use the default serializer for size_t and @@ -126,7 +116,7 @@ assert_cc(sizeof(mode_t) == sizeof(uint32_t)); int bus_log_parse_error(int r); int bus_log_create_error(int r); -#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ +#define BUS_DEFINE_PROPERTY_GET_GLOBAL(function, bus_type, val) \ int function(sd_bus *bus, \ const char *path, \ const char *interface, \ @@ -135,23 +125,41 @@ int bus_log_create_error(int r); void *userdata, \ sd_bus_error *error) { \ \ - const char *value; \ - type *field = userdata; \ - int r; \ - \ assert(bus); \ assert(reply); \ - assert(field); \ \ - value = strempty(name##_to_string(*field)); \ + return sd_bus_message_append(reply, bus_type, val); \ + } + +#define BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, get2) \ + int function(sd_bus *bus, \ + const char *path, \ + const char *interface, \ + const char *property, \ + sd_bus_message *reply, \ + void *userdata, \ + sd_bus_error *error) { \ \ - r = sd_bus_message_append_basic(reply, 's', value); \ - if (r < 0) \ - return r; \ + data_type *data = userdata; \ + \ + assert(bus); \ + assert(reply); \ + assert(data); \ \ - return 1; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ + return sd_bus_message_append(reply, bus_type, \ + get2(get1(data))); \ + } + +#define ident(x) (x) +#define BUS_DEFINE_PROPERTY_GET(function, bus_type, data_type, get1) \ + BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, get1, ident) + +#define ref(x) (*(x)) +#define BUS_DEFINE_PROPERTY_GET_REF(function, bus_type, data_type, get) \ + BUS_DEFINE_PROPERTY_GET2(function, bus_type, data_type, ref, get) + +#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type) \ + BUS_DEFINE_PROPERTY_GET_REF(function, "s", type, name##_to_string) #define BUS_PROPERTY_DUAL_TIMESTAMP(name, offset, flags) \ SD_BUS_PROPERTY(name, "t", bus_property_get_usec, (offset) + offsetof(struct dual_timestamp, realtime), (flags)), \ @@ -164,4 +172,11 @@ int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface int bus_track_add_name_many(sd_bus_track *t, char **l); -int bus_open_system_watch_bind(sd_bus **ret); +int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description); +static inline int bus_open_system_watch_bind(sd_bus **ret) { + return bus_open_system_watch_bind_with_description(ret, NULL); +} + +int bus_request_name_async_may_reload_dbus(sd_bus *bus, sd_bus_slot **ret_slot, const char *name, uint64_t flags, void *userdata); + +int bus_reply_pair_array(sd_bus_message *m, char **l); diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 0ddae95434..4d1a90bd55 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <dirent.h> #include <errno.h> @@ -189,8 +171,7 @@ int show_cgroup_by_path( free(last); } - last = k; - k = NULL; + last = TAKE_PTR(k); } if (r < 0) @@ -358,7 +339,7 @@ int show_cgroup_get_path_and_warn( const char *m; m = strjoina("/run/systemd/machines/", machine); - r = parse_env_file(m, NEWLINE, "SCOPE", &unit, NULL); + r = parse_env_file(NULL, m, NEWLINE, "SCOPE", &unit, NULL); if (r < 0) return log_error_errno(r, "Failed to load machine data: %m"); @@ -386,10 +367,8 @@ int show_cgroup_get_path_and_warn( return log_oom(); *ret = t; - } else { - *ret = root; - root = NULL; - } + } else + *ret = TAKE_PTR(root); return 0; } diff --git a/src/shared/cgroup-show.h b/src/shared/cgroup-show.h index efa597aad0..4e510fb73c 100644 --- a/src/shared/cgroup-show.h +++ b/src/shared/cgroup-show.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <sys/types.h> diff --git a/src/shared/clean-ipc.c b/src/shared/clean-ipc.c index 7e2ef4a8eb..08dc7b9e43 100644 --- a/src/shared/clean-ipc.c +++ b/src/shared/clean-ipc.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <dirent.h> #include <errno.h> diff --git a/src/shared/clean-ipc.h b/src/shared/clean-ipc.h index 0ade561b3f..eaff47d4b7 100644 --- a/src/shared/clean-ipc.h +++ b/src/shared/clean-ipc.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <sys/types.h> #include "user-util.h" diff --git a/src/shared/condition.c b/src/shared/condition.c index a2fd05c425..2969a89b4e 100644 --- a/src/shared/condition.c +++ b/src/shared/condition.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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> @@ -39,6 +21,7 @@ #include "cap-list.h" #include "cgroup-util.h" #include "condition.h" +#include "efivars.h" #include "extract-word.h" #include "fd-util.h" #include "fileio.h" @@ -116,7 +99,7 @@ static int condition_test_kernel_command_line(Condition *c) { if (r < 0) return r; - equal = !!strchr(c->parameter, '='); + equal = strchr(c->parameter, '='); for (p = line;;) { _cleanup_free_ char *word = NULL; @@ -264,7 +247,7 @@ static int condition_test_control_group_controller(Condition *c) { return 1; } - return (system_mask & wanted_mask) == wanted_mask; + return FLAGS_SET(system_mask, wanted_mask); } static int condition_test_group(Condition *c) { @@ -394,6 +377,8 @@ static int condition_test_security(Condition *c) { return use_ima(); if (streq(c->parameter, "tomoyo")) return mac_tomoyo_use(); + if (streq(c->parameter, "uefi-secureboot")) + return is_efi_secure_boot(); return false; } @@ -477,7 +462,7 @@ static int condition_test_needs_update(Condition *c) { uint64_t timestamp; int r; - r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", ×tamp_str, NULL); + r = parse_env_file(NULL, p, NULL, "TIMESTAMP_NSEC", ×tamp_str, NULL); if (r < 0) { log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p); return true; diff --git a/src/shared/condition.h b/src/shared/condition.h index a84d993370..e69fc366f7 100644 --- a/src/shared/condition.h +++ b/src/shared/condition.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <stdio.h> diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 15cfe4e4f7..2d62fdf05d 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <limits.h> @@ -46,6 +28,7 @@ #include "syslog-util.h" #include "time-util.h" #include "utf8.h" +#include "rlimit-util.h" int config_item_table_lookup( const void *table, @@ -165,7 +148,7 @@ static int next_assignment( return 0; } -/* Parse a variable assignment line */ +/* Parse a single logical line */ static int parse_line( const char* unit, const char *filename, @@ -180,7 +163,7 @@ static int parse_line( char *l, void *userdata) { - char *e; + char *e, *include; assert(filename); assert(line > 0); @@ -194,7 +177,8 @@ static int parse_line( if (strchr(COMMENTS "\n", *l)) return 0; - if (startswith(l, ".include ")) { + include = first_word(l, ".include"); + if (include) { _cleanup_free_ char *fn = NULL; /* .includes are a bad idea, we only support them here @@ -211,13 +195,20 @@ static int parse_line( return 0; } - fn = file_in_same_dir(filename, strstrip(l+9)); + log_syntax(unit, LOG_WARNING, filename, line, 0, + ".include directives are deprecated, and support for them will be removed in a future version of systemd. " + "Please use drop-in files instead."); + + fn = file_in_same_dir(filename, strstrip(include)); if (!fn) return -ENOMEM; return config_parse(unit, fn, NULL, sections, lookup, table, flags, userdata); } + if (!utf8_is_valid(l)) + return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l); + if (*l == '[') { size_t k; char *n; @@ -244,8 +235,7 @@ static int parse_line( *section_line = 0; *section_ignored = true; } else { - free(*section); - *section = n; + free_and_replace(*section, n); *section_line = line; *section_ignored = false; } @@ -308,8 +298,8 @@ int config_parse(const char *unit, /* Only log on request, except for ENOENT, * since we return 0 to the caller. */ if ((flags & CONFIG_PARSE_WARN) || errno == ENOENT) - log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, - "Failed to open configuration file '%s': %m", filename); + log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno, + "Failed to open configuration file '%s': %m", filename); return errno == ENOENT ? 0 : -errno; } } @@ -403,12 +393,31 @@ int config_parse(const char *unit, if (flags & CONFIG_PARSE_WARN) log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); return r; - } continuation = mfree(continuation); } + if (continuation) { + r = parse_line(unit, + filename, + ++line, + sections, + lookup, + table, + flags, + §ion, + §ion_line, + §ion_ignored, + continuation, + userdata); + if (r < 0) { + if (flags & CONFIG_PARSE_WARN) + log_warning_errno(r, "%s:%u: Failed to parse file: %m", filename, line); + return r; + } + } + return 0; } @@ -488,35 +497,7 @@ int config_parse_many( } #define DEFINE_PARSER(type, vartype, conv_func) \ - int config_parse_##type( \ - const char *unit, \ - const char *filename, \ - unsigned line, \ - const char *section, \ - unsigned section_line, \ - const char *lvalue, \ - int ltype, \ - const char *rvalue, \ - void *data, \ - void *userdata) { \ - \ - vartype *i = data; \ - int r; \ - \ - assert(filename); \ - assert(lvalue); \ - assert(rvalue); \ - assert(data); \ - \ - r = conv_func(rvalue, i); \ - if (r < 0) \ - log_syntax(unit, LOG_ERR, filename, line, r, \ - "Failed to parse %s value, ignoring: %s", \ - #type, rvalue); \ - \ - return 0; \ - } \ - struct __useless_struct_to_allow_trailing_semicolon__ + DEFINE_CONFIG_PARSE_PTR(config_parse_##type, conv_func, vartype, "Failed to parse " #type " value") DEFINE_PARSER(int, int, safe_atoi); DEFINE_PARSER(long, long, safe_atoli); @@ -646,7 +627,7 @@ int config_parse_bool(const char* unit, return fatal ? -ENOEXEC : 0; } - *b = !!k; + *b = k; return 0; } @@ -695,28 +676,15 @@ int config_parse_string( void *data, void *userdata) { - char **s = data, *n; + char **s = data; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (!utf8_is_valid(rvalue)) { - log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); - return 0; - } - - if (isempty(rvalue)) - n = NULL; - else { - n = strdup(rvalue); - if (!n) - return log_oom(); - } - - free(*s); - *s = n; + if (free_and_strdup(s, empty_to_null(rvalue)) < 0) + return log_oom(); return 0; } @@ -733,42 +701,29 @@ int config_parse_path( void *data, void *userdata) { - char **s = data, *n; + _cleanup_free_ char *n = NULL; bool fatal = ltype; + char **s = data; + int r; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if (isempty(rvalue)) { - n = NULL; + if (isempty(rvalue)) goto finalize; - } - - if (!utf8_is_valid(rvalue)) { - log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue); - return fatal ? -ENOEXEC : 0; - } - - if (!path_is_absolute(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Not an absolute path%s: %s", - fatal ? "" : ", ignoring", rvalue); - return fatal ? -ENOEXEC : 0; - } n = strdup(rvalue); if (!n) return log_oom(); - path_kill_slashes(n); + r = path_simplify_and_warn(n, PATH_CHECK_ABSOLUTE | (fatal ? PATH_CHECK_FATAL : 0), unit, filename, line, lvalue); + if (r < 0) + return fatal ? -ENOEXEC : 0; finalize: - free(*s); - *s = n; - - return 0; + return free_and_replace(*s, n); } int config_parse_strv( @@ -809,12 +764,6 @@ int config_parse_strv( break; } - if (!utf8_is_valid(word)) { - log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, word); - free(word); - continue; - } - r = strv_consume(sv, word); if (r < 0) return log_oom(); @@ -823,6 +772,41 @@ int config_parse_strv( return 0; } +int config_parse_warn_compat( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Disabled reason = ltype; + + switch(reason) { + + case DISABLED_CONFIGURATION: + log_syntax(unit, LOG_DEBUG, filename, line, 0, + "Support for option %s= has been disabled at compile time and it is ignored", lvalue); + break; + + case DISABLED_LEGACY: + log_syntax(unit, LOG_INFO, filename, line, 0, + "Support for option %s= has been removed and it is ignored", lvalue); + break; + + case DISABLED_EXPERIMENTAL: + log_syntax(unit, LOG_INFO, filename, line, 0, + "Support for option %s= has not yet been enabled and it is ignored", lvalue); + break; + } + + return 0; +} + int config_parse_log_facility( const char *unit, const char *filename, @@ -905,7 +889,7 @@ int config_parse_signal( assert(rvalue); assert(sig); - r = signal_from_string_try_harder(rvalue); + r = signal_from_string(rvalue); if (r <= 0) { log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse signal name, ignoring: %s", rvalue); return 0; @@ -1132,8 +1116,112 @@ int config_parse_join_controllers( } strv_free_free(*ret); - *ret = controllers; - controllers = NULL; + *ret = TAKE_PTR(controllers); + + return 0; +} + +int config_parse_mtu( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint32_t *mtu = data; + int r; + + assert(rvalue); + assert(mtu); + + r = parse_mtu(ltype, rvalue, mtu); + if (r == -ERANGE) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s", + (uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX, + rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse MTU value '%s', ignoring: %m", rvalue); + return 0; + } + + return 0; +} + +int config_parse_rlimit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + struct rlimit **rl = data, d = {}; + int r; + + assert(rvalue); + assert(rl); + + r = rlimit_parse(ltype, rvalue, &d); + if (r == -EILSEQ) { + log_syntax(unit, LOG_WARNING, filename, line, r, "Soft resource limit chosen higher than hard limit, ignoring: %s", rvalue); + return 0; + } + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); + return 0; + } + + if (rl[ltype]) + *rl[ltype] = d; + else { + rl[ltype] = newdup(struct rlimit, &d, 1); + if (!rl[ltype]) + return log_oom(); + } + + return 0; +} + +int config_parse_permille(const char* unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + unsigned *permille = data; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(permille); + + r = parse_permille(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse permille value, ignoring: %s", rvalue); + return 0; + } + + *permille = (unsigned) r; return 0; } diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 908f530713..16f042d894 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stddef.h> @@ -33,23 +14,32 @@ /* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */ typedef enum ConfigParseFlags { - CONFIG_PARSE_RELAXED = 1U << 0, - CONFIG_PARSE_ALLOW_INCLUDE = 1U << 1, - CONFIG_PARSE_WARN = 1U << 2, - CONFIG_PARSE_REFUSE_BOM = 1U << 3, + CONFIG_PARSE_RELAXED = 1 << 0, + CONFIG_PARSE_ALLOW_INCLUDE = 1 << 1, + CONFIG_PARSE_WARN = 1 << 2, + CONFIG_PARSE_REFUSE_BOM = 1 << 3, } ConfigParseFlags; +/* Argument list for parsers of specific configuration settings. */ +#define CONFIG_PARSER_ARGUMENTS \ + const char *unit, \ + const char *filename, \ + unsigned line, \ + const char *section, \ + unsigned section_line, \ + const char *lvalue, \ + int ltype, \ + const char *rvalue, \ + void *data, \ + void *userdata + /* Prototype for a parser for a specific configuration setting */ -typedef int (*ConfigParserCallback)(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata); +typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS); + +/* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long + * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function + * prototypes on the same screen…) */ +#define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS) /* Wraps information for parsing a specific configuration variable, to * be stored in a simple array */ @@ -120,47 +110,103 @@ int config_parse_many( ConfigParseFlags flags, void *userdata); -/* Generic parsers */ -#define GENERIC_PARSER_ARGS \ - const char *unit, \ - const char *filename, \ - unsigned line, \ - const char *section, \ - unsigned section_line, \ - const char *lvalue, \ - int ltype, \ - const char *rvalue, \ - void *data, \ - void *userdata -int config_parse_int(GENERIC_PARSER_ARGS); -int config_parse_unsigned(GENERIC_PARSER_ARGS); -int config_parse_long(GENERIC_PARSER_ARGS); -int config_parse_uint8(GENERIC_PARSER_ARGS); -int config_parse_uint16(GENERIC_PARSER_ARGS); -int config_parse_uint32(GENERIC_PARSER_ARGS); -int config_parse_uint64(GENERIC_PARSER_ARGS); -int config_parse_double(GENERIC_PARSER_ARGS); -int config_parse_iec_size(GENERIC_PARSER_ARGS); -int config_parse_si_size(GENERIC_PARSER_ARGS); -int config_parse_iec_uint64(GENERIC_PARSER_ARGS); -int config_parse_bool(GENERIC_PARSER_ARGS); -int config_parse_tristate(GENERIC_PARSER_ARGS); -int config_parse_string(GENERIC_PARSER_ARGS); -int config_parse_path(GENERIC_PARSER_ARGS); -int config_parse_strv(GENERIC_PARSER_ARGS); -int config_parse_sec(GENERIC_PARSER_ARGS); -int config_parse_nsec(GENERIC_PARSER_ARGS); -int config_parse_mode(GENERIC_PARSER_ARGS); -int config_parse_log_facility(GENERIC_PARSER_ARGS); -int config_parse_log_level(GENERIC_PARSER_ARGS); -int config_parse_signal(GENERIC_PARSER_ARGS); -int config_parse_personality(GENERIC_PARSER_ARGS); -int config_parse_ifname(GENERIC_PARSER_ARGS); -int config_parse_ip_port(GENERIC_PARSER_ARGS); -int config_parse_join_controllers(GENERIC_PARSER_ARGS); - -#define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \ - int function(GENERIC_PARSER_ARGS) { \ +CONFIG_PARSER_PROTOTYPE(config_parse_int); +CONFIG_PARSER_PROTOTYPE(config_parse_unsigned); +CONFIG_PARSER_PROTOTYPE(config_parse_long); +CONFIG_PARSER_PROTOTYPE(config_parse_uint8); +CONFIG_PARSER_PROTOTYPE(config_parse_uint16); +CONFIG_PARSER_PROTOTYPE(config_parse_uint32); +CONFIG_PARSER_PROTOTYPE(config_parse_uint64); +CONFIG_PARSER_PROTOTYPE(config_parse_double); +CONFIG_PARSER_PROTOTYPE(config_parse_iec_size); +CONFIG_PARSER_PROTOTYPE(config_parse_si_size); +CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64); +CONFIG_PARSER_PROTOTYPE(config_parse_bool); +CONFIG_PARSER_PROTOTYPE(config_parse_tristate); +CONFIG_PARSER_PROTOTYPE(config_parse_string); +CONFIG_PARSER_PROTOTYPE(config_parse_path); +CONFIG_PARSER_PROTOTYPE(config_parse_strv); +CONFIG_PARSER_PROTOTYPE(config_parse_sec); +CONFIG_PARSER_PROTOTYPE(config_parse_nsec); +CONFIG_PARSER_PROTOTYPE(config_parse_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat); +CONFIG_PARSER_PROTOTYPE(config_parse_log_facility); +CONFIG_PARSER_PROTOTYPE(config_parse_log_level); +CONFIG_PARSER_PROTOTYPE(config_parse_signal); +CONFIG_PARSER_PROTOTYPE(config_parse_personality); +CONFIG_PARSER_PROTOTYPE(config_parse_permille); +CONFIG_PARSER_PROTOTYPE(config_parse_ifname); +CONFIG_PARSER_PROTOTYPE(config_parse_ip_port); +CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers); +CONFIG_PARSER_PROTOTYPE(config_parse_mtu); +CONFIG_PARSER_PROTOTYPE(config_parse_rlimit); + +typedef enum Disabled { + DISABLED_CONFIGURATION, + DISABLED_LEGACY, + DISABLED_EXPERIMENTAL, +} Disabled; + +#define DEFINE_CONFIG_PARSE(function, parser, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + int *i = data, r; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + r = parser(rvalue); \ + if (r < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + msg ", ignoring: %s", rvalue); \ + return 0; \ + } \ + \ + *i = r; \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type *i = data; \ + int r; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + r = parser(rvalue, i); \ + if (r < 0) \ + log_syntax(unit, LOG_ERR, filename, line, r, \ + msg ", ignoring: %s", rvalue); \ + \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ + type *i = data, x; \ + \ + assert(filename); \ + assert(lvalue); \ + assert(rvalue); \ + assert(data); \ + \ + x = name##_from_string(rvalue); \ + if (x < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ + msg ", ignoring: %s", rvalue); \ + return 0; \ + } \ + \ + *i = x; \ + return 0; \ + } + +#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ type *i = data, x; \ \ assert(filename); \ @@ -168,8 +214,14 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS); assert(rvalue); \ assert(data); \ \ - if ((x = name##_from_string(rvalue)) < 0) { \ - log_syntax(unit, LOG_ERR, filename, line, -x, \ + if (isempty(rvalue)) { \ + *i = default_value; \ + return 0; \ + } \ + \ + x = name##_from_string(rvalue); \ + if (x < 0) { \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ msg ", ignoring: %s", rvalue); \ return 0; \ } \ @@ -178,8 +230,8 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS); return 0; \ } -#define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \ - int function(GENERIC_PARSER_ARGS) { \ +#define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \ + CONFIG_PARSER_PROTOTYPE(function) { \ type **enums = data, x, *ys; \ _cleanup_free_ type *xs = NULL; \ const char *word, *state; \ @@ -205,17 +257,17 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS); return -ENOMEM; \ \ if ((x = name##_from_string(en)) < 0) { \ - log_syntax(unit, LOG_ERR, filename, line, \ - -x, msg ", ignoring: %s", en); \ + log_syntax(unit, LOG_ERR, filename, line, 0, \ + msg ", ignoring: %s", en); \ continue; \ } \ \ for (ys = xs; x != invalid && *ys != invalid; ys++) { \ if (*ys == x) { \ - log_syntax(unit, LOG_ERR, filename, \ - line, -x, \ - "Duplicate entry, ignoring: %s", \ - en); \ + log_syntax(unit, LOG_NOTICE, filename, \ + line, 0, \ + "Duplicate entry, ignoring: %s", \ + en); \ x = invalid; \ } \ } \ @@ -233,9 +285,6 @@ int config_parse_join_controllers(GENERIC_PARSER_ARGS); *(xs + i) = invalid; \ } \ \ - free(*enums); \ - *enums = xs; \ - xs = NULL; \ - \ + free_and_replace(*enums, xs); \ return 0; \ } diff --git a/src/shared/dev-setup.c b/src/shared/dev-setup.c index 6d2cc685fa..d117fbfda0 100644 --- a/src/shared/dev-setup.c +++ b/src/shared/dev-setup.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2010-2012 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 <stdlib.h> diff --git a/src/shared/dev-setup.h b/src/shared/dev-setup.h index 4dd591de0a..f105f2f20f 100644 --- a/src/shared/dev-setup.h +++ b/src/shared/dev-setup.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2010-2012 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 <sys/types.h> int dev_setup(const char *prefix, uid_t uid, gid_t gid); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 86114e3dd1..fa1cf26ee1 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 <sys/mount.h> #include <sys/prctl.h> @@ -43,6 +25,7 @@ #include "linux-3.13/dm-ioctl.h" #include "missing.h" #include "mount-util.h" +#include "os-util.h" #include "path-util.h" #include "process-util.h" #include "raw-clone.h" @@ -62,7 +45,7 @@ int probe_filesystem(const char *node, char **ret_fstype) { * different error otherwise. */ #if HAVE_BLKID - _cleanup_blkid_free_probe_ blkid_probe b = NULL; + _cleanup_(blkid_free_probep) blkid_probe b = NULL; const char *fstype; int r; @@ -108,16 +91,43 @@ not_found: #endif } -int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret) { +#if HAVE_BLKID +/* Detect RPMB and Boot partitions, which are not listed by blkid. + * See https://github.com/systemd/systemd/issues/5806. */ +static bool device_is_mmc_special_partition(struct udev_device *d) { + const char *sysname; + + sysname = udev_device_get_sysname(d); + return sysname && startswith(sysname, "mmcblk") && + (endswith(sysname, "rpmb") || endswith(sysname, "boot0") || endswith(sysname, "boot1")); +} + +static bool device_is_block(struct udev_device *d) { + const char *ss; + + ss = udev_device_get_subsystem(d); + if (!ss) + return false; + + return streq(ss, "block"); +} +#endif + +int dissect_image( + int fd, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DissectedImage **ret) { #if HAVE_BLKID sd_id128_t root_uuid = SD_ID128_NULL, verity_uuid = SD_ID128_NULL; - _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; + _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; bool is_gpt, is_mbr, generic_rw, multiple_generic = false; - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_(udev_device_unrefp) struct udev_device *d = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; - _cleanup_blkid_free_probe_ blkid_probe b = NULL; - _cleanup_udev_unref_ struct udev *udev = NULL; + _cleanup_(blkid_free_probep) blkid_probe b = NULL; + _cleanup_(udev_unrefp) struct udev *udev = NULL; _cleanup_free_ char *generic_node = NULL; sd_id128_t generic_uuid = SD_ID128_NULL; const char *pttype = NULL; @@ -216,16 +226,13 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI .rw = true, .partno = -1, .architecture = _ARCHITECTURE_INVALID, - .fstype = t, - .node = n, + .fstype = TAKE_PTR(t), + .node = TAKE_PTR(n), }; - t = n = NULL; - m->encrypted = streq(fstype, "crypto_LUKS"); - *ret = m; - m = NULL; + *ret = TAKE_PTR(m); return 0; } @@ -277,8 +284,25 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI /* Count the partitions enumerated by the kernel */ n = 0; first = udev_enumerate_get_list_entry(e); - udev_list_entry_foreach(item, first) + udev_list_entry_foreach(item, first) { + _cleanup_(udev_device_unrefp) struct udev_device *q; + dev_t qn; + + q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); + if (!q) + return -errno; + + qn = udev_device_get_devnum(q); + if (major(qn) == 0) + continue; + + if (!device_is_block(q)) + continue; + + if (device_is_mmc_special_partition(q)) + continue; n++; + } /* Count the partitions enumerated by blkid */ z = blkid_partlist_numof_partitions(pl); @@ -334,10 +358,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { - _cleanup_udev_device_unref_ struct udev_device *q; + _cleanup_(udev_device_unrefp) struct udev_device *q; unsigned long long pflags; blkid_partition pp; - const char *node, *sysname; + const char *node; dev_t qn; int nr; @@ -352,11 +376,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI if (st.st_rdev == qn) continue; - /* Filter out weird MMC RPMB partitions, which cannot reasonably be read, see - * https://github.com/systemd/systemd/issues/5806 */ - sysname = udev_device_get_sysname(q); - if (sysname && startswith(sysname, "mmcblk") && - (endswith(sysname, "rpmb") || endswith(sysname, "boot0" ) || endswith(sysname, "boot1"))) + if (!device_is_block(q)) + continue; + + if (device_is_mmc_special_partition(q)) continue; node = udev_device_get_devnode(q); @@ -523,12 +546,10 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI .partno = nr, .rw = rw, .architecture = architecture, - .node = n, - .fstype = t, + .node = TAKE_PTR(n), + .fstype = TAKE_PTR(t), .uuid = id, }; - - n = t = NULL; } } else if (is_mbr) { @@ -586,11 +607,9 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI .rw = generic_rw, .partno = generic_nr, .architecture = _ARCHITECTURE_INVALID, - .node = generic_node, + .node = TAKE_PTR(generic_node), .uuid = generic_uuid, }; - - generic_node = NULL; } } @@ -633,8 +652,7 @@ int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectI p->rw = false; } - *ret = m; - m = NULL; + *ret = TAKE_PTR(m); return 0; #else @@ -759,6 +777,14 @@ int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags); if (r < 0) return r; + + if (flags & DISSECT_IMAGE_VALIDATE_OS) { + r = path_is_os_tree(where); + if (r < 0) + return r; + if (r == 0) + return -EMEDIUMTYPE; + } } if ((flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY)) @@ -865,10 +891,9 @@ static int make_dm_name_and_node(const void *original_node, const char *suffix, if (!node) return -ENOMEM; - *ret_name = name; - *ret_node = node; + *ret_name = TAKE_PTR(name); + *ret_node = TAKE_PTR(node); - name = node = NULL; return 0; } @@ -917,15 +942,11 @@ static int decrypt_partition( return r == -EPERM ? -EKEYREJECTED : r; } - d->decrypted[d->n_decrypted].name = name; - name = NULL; - - d->decrypted[d->n_decrypted].device = cd; - cd = NULL; + d->decrypted[d->n_decrypted].name = TAKE_PTR(name); + d->decrypted[d->n_decrypted].device = TAKE_PTR(cd); d->n_decrypted++; - m->decrypted_node = node; - node = NULL; + m->decrypted_node = TAKE_PTR(node); return 0; } @@ -979,15 +1000,11 @@ static int verity_partition( if (r < 0) return r; - d->decrypted[d->n_decrypted].name = name; - name = NULL; - - d->decrypted[d->n_decrypted].device = cd; - cd = NULL; + d->decrypted[d->n_decrypted].name = TAKE_PTR(name); + d->decrypted[d->n_decrypted].device = TAKE_PTR(cd); d->n_decrypted++; - m->decrypted_node = node; - node = NULL; + m->decrypted_node = TAKE_PTR(node); return 0; } @@ -1056,8 +1073,7 @@ int dissected_image_decrypt( } } - *ret = d; - d = NULL; + *ret = TAKE_PTR(d); return 1; #else @@ -1215,11 +1231,9 @@ int root_hash_load(const char *image, void **ret, size_t *ret_size) { if (l < sizeof(sd_id128_t)) return -EINVAL; - *ret = k; + *ret = TAKE_PTR(k); *ret_size = l; - k = NULL; - return 1; } @@ -1262,17 +1276,15 @@ int dissected_image_acquire_metadata(DissectedImage *m) { if (r < 0) goto finish; - r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS, &child); + r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child); if (r < 0) goto finish; if (r == 0) { - /* Make sure we never propagate to the host */ - if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) - _exit(EXIT_FAILURE); - - r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY); - if (r < 0) + r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_VALIDATE_OS); + if (r < 0) { + log_debug_errno(r, "Failed to mount dissected image: %m"); _exit(EXIT_FAILURE); + } for (k = 0; k < _META_MAX; k++) { _cleanup_close_ int fd = -1; @@ -1281,18 +1293,14 @@ int dissected_image_acquire_metadata(DissectedImage *m) { fds[2*k] = safe_close(fds[2*k]); NULSTR_FOREACH(p, paths[k]) { - _cleanup_free_ char *q = NULL; - - r = chase_symlinks(p, t, CHASE_PREFIX_ROOT, &q); - if (r < 0) - continue; - - fd = open(q, O_RDONLY|O_CLOEXEC|O_NOCTTY); + fd = chase_symlinks_and_open(p, t, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); if (fd >= 0) break; } - if (fd < 0) + if (fd < 0) { + log_debug_errno(fd, "Failed to read %s file of image, ignoring: %m", paths[k]); continue; + } r = copy_bytes(fd, fds[2*k+1], (uint64_t) -1, 0); if (r < 0) @@ -1379,6 +1387,55 @@ finish: return r; } +int dissect_image_and_warn( + int fd, + const char *name, + const void *root_hash, + size_t root_hash_size, + DissectImageFlags flags, + DissectedImage **ret) { + + _cleanup_free_ char *buffer = NULL; + int r; + + if (!name) { + r = fd_get_path(fd, &buffer); + if (r < 0) + return r; + + name = buffer; + } + + r = dissect_image(fd, root_hash, root_hash_size, flags, ret); + + switch (r) { + + case -EOPNOTSUPP: + return log_error_errno(r, "Dissecting images is not supported, compiled without blkid support."); + + case -ENOPKG: + return log_error_errno(r, "Couldn't identify a suitable partition table or file system in '%s'.", name); + + case -EADDRNOTAVAIL: + return log_error_errno(r, "No root partition for specified root hash found in '%s'.", name); + + case -ENOTUNIQ: + return log_error_errno(r, "Multiple suitable root partitions found in image '%s'.", name); + + case -ENXIO: + return log_error_errno(r, "No suitable root partition found in image '%s'.", name); + + case -EPROTONOSUPPORT: + return log_error_errno(r, "Device '%s' is loopback block device with partition scanning turned off, please turn it on.", name); + + default: + if (r < 0) + return log_error_errno(r, "Failed to dissect image '%s': %m", name); + + return r; + } +} + static const char *const partition_designator_table[] = { [PARTITION_ROOT] = "root", [PARTITION_ROOT_SECONDARY] = "root-secondary", diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 10e251ff09..0033921fa0 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 <stdbool.h> #include "sd-id128.h" @@ -75,6 +56,7 @@ typedef enum DissectImageFlags { DISSECT_IMAGE_REQUIRE_ROOT = 1 << 5, /* Don't accept disks without root partition */ DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root partition */ DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only non-root partitions */ + DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifyable as OS images */ } DissectImageFlags; struct DissectedImage { @@ -92,6 +74,7 @@ struct DissectedImage { int probe_filesystem(const char *node, char **ret_fstype); int dissect_image(int fd, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret); +int dissect_image_and_warn(int fd, const char *name, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DissectedImage **ret); DissectedImage* dissected_image_unref(DissectedImage *m); DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref); diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c index 8c807e0e23..de2fcca8b2 100644 --- a/src/shared/dns-domain.c +++ b/src/shared/dns-domain.c @@ -1,21 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** - 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/>. ***/ #if HAVE_LIBIDN2 @@ -295,8 +279,7 @@ int dns_label_escape_new(const char *p, size_t l, char **ret) { if (r < 0) return r; - *ret = s; - s = NULL; + *ret = TAKE_PTR(s); return r; } @@ -367,10 +350,7 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, if (encoded_size <= 0 || encoded_size > DNS_LABEL_MAX) return -EINVAL; - if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1) - return 0; - - if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0) + if (!memory_startswith(encoded, encoded_size, IDNA_ACE_PREFIX)) return 0; input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size); @@ -409,10 +389,9 @@ int dns_name_concat(const char *a, const char *b, char **_ret) { if (a) p = a; - else if (b) { - p = b; - b = NULL; - } else + else if (b) + p = TAKE_PTR(b); + else goto finish; for (;;) { @@ -427,8 +406,7 @@ int dns_name_concat(const char *a, const char *b, char **_ret) { if (b) { /* Now continue with the second string, if there is one */ - p = b; - b = NULL; + p = TAKE_PTR(b); continue; } @@ -478,8 +456,7 @@ finish: } ret[n] = 0; - *_ret = ret; - ret = NULL; + *_ret = TAKE_PTR(ret); } return 0; @@ -601,8 +578,7 @@ int dns_name_endswith(const char *name, const char *suffix) { /* Not the same, let's jump back, and try with the next label again */ s = suffix; - n = saved_n; - saved_n = NULL; + n = TAKE_PTR(saved_n); } } } @@ -677,8 +653,8 @@ int dns_name_change_suffix(const char *name, const char *old_suffix, const char /* Not the same, let's jump back, and try with the next label again */ s = old_suffix; - n = saved_after; - saved_after = saved_before = NULL; + n = TAKE_PTR(saved_after); + saved_before = NULL; } } @@ -1113,20 +1089,14 @@ finish: if (r < 0) return r; - if (_domain) { - *_domain = domain; - domain = NULL; - } + if (_domain) + *_domain = TAKE_PTR(domain); - if (_type) { - *_type = type; - type = NULL; - } + if (_type) + *_type = TAKE_PTR(type); - if (_name) { - *_name = name; - name = NULL; - } + if (_name) + *_name = TAKE_PTR(name); return 0; } @@ -1309,8 +1279,8 @@ int dns_name_apply_idna(const char *name, char **ret) { } } - *ret = t; - t = NULL; + *ret = TAKE_PTR(t); + return 1; /* *ret has been written */ } @@ -1367,8 +1337,7 @@ int dns_name_apply_idna(const char *name, char **ret) { return -ENOMEM; buf[n] = 0; - *ret = buf; - buf = NULL; + *ret = TAKE_PTR(buf); return 1; #else diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h index cd3dbb7a89..0fd72cb029 100644 --- a/src/shared/dns-domain.h +++ b/src/shared/dns-domain.h @@ -2,22 +2,6 @@ #pragma once /*** - 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 <errno.h> @@ -38,7 +22,7 @@ #define DNS_HOSTNAME_MAX 253 /* Maximum length of a full hostname, on the wire, including the final NUL byte */ -#define DNS_WIRE_FOMAT_HOSTNAME_MAX 255 +#define DNS_WIRE_FORMAT_HOSTNAME_MAX 255 /* Maximum number of labels per valid hostname */ #define DNS_N_LABELS_MAX 127 diff --git a/src/shared/dropin.c b/src/shared/dropin.c index f0966874ee..357c66d800 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2014 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 <stdarg.h> @@ -128,14 +110,16 @@ static int unit_file_find_dir( assert(path); r = chase_symlinks(path, original_root, 0, &chased); - /* Ignore -ENOENT, after all most units won't have a drop-in dir. - * Also ignore -ENAMETOOLONG, users are not even able to create - * the drop-in dir in such case. This mostly happens for device units with long /sys path. - * */ - if (IN_SET(r, -ENOENT, -ENAMETOOLONG)) + if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */ return 0; + if (r == -ENAMETOOLONG) { + /* Also, ignore -ENAMETOOLONG but log about it. After all, users are not even able to create the + * drop-in dir in such case. This mostly happens for device units with an overly long /sys path. */ + log_debug_errno(r, "Path '%s' too long, couldn't canonicalize, ignoring.", path); + return 0; + } if (r < 0) - return log_full_errno(LOG_WARNING, r, "Failed to canonicalize path %s: %m", path); + return log_warning_errno(r, "Failed to canonicalize path '%s': %m", path); r = strv_push(dirs, chased); if (r < 0) @@ -153,7 +137,12 @@ static int unit_file_find_dirs( const char *suffix, char ***dirs) { + _cleanup_free_ char *prefix = NULL, *instance = NULL, *built = NULL; + bool is_instance, chopped; + const char *dash; + UnitType type; char *path; + size_t n; int r; assert(unit_path); @@ -161,26 +150,76 @@ static int unit_file_find_dirs( assert(suffix); path = strjoina(unit_path, "/", name, suffix); - if (!unit_path_cache || set_get(unit_path_cache, path)) { r = unit_file_find_dir(original_root, path, dirs); if (r < 0) return r; } - if (unit_name_is_valid(name, UNIT_NAME_INSTANCE)) { - /* Also try the template dir */ - + is_instance = unit_name_is_valid(name, UNIT_NAME_INSTANCE); + if (is_instance) { /* Also try the template dir */ _cleanup_free_ char *template = NULL; r = unit_name_template(name, &template); if (r < 0) return log_error_errno(r, "Failed to generate template from unit name: %m"); - return unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs); + r = unit_file_find_dirs(original_root, unit_path_cache, unit_path, template, suffix, dirs); + if (r < 0) + return r; } - return 0; + /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then + * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also + * search "foo-bar-.service" and "foo-.service". + * + * Note the order in which we do it: we traverse up adding drop-ins on each step. This means the more specific + * drop-ins may override the more generic drop-ins, which is the intended behaviour. */ + + r = unit_name_to_prefix(name, &prefix); + if (r < 0) + return log_error_errno(r, "Failed to derive unit name prefix from unit name: %m"); + + chopped = false; + for (;;) { + dash = strrchr(prefix, '-'); + if (!dash) /* No dash? if so we are done */ + return 0; + + n = (size_t) (dash - prefix); + if (n == 0) /* Leading dash? If so, we are done */ + return 0; + + if (prefix[n+1] != 0 || chopped) { + prefix[n+1] = 0; + break; + } + + /* Trailing dash? If so, chop it off and try again, but not more than once. */ + prefix[n] = 0; + chopped = true; + } + + if (!unit_prefix_is_valid(prefix)) + return 0; + + type = unit_name_to_type(name); + if (type < 0) { + log_error("Failed to to derive unit type from unit name: %s", name); + return -EINVAL; + } + + if (is_instance) { + r = unit_name_to_instance(name, &instance); + if (r < 0) + return log_error_errno(r, "Failed to derive unit name instance from unit name: %m"); + } + + r = unit_name_build_from_type(prefix, instance, type, &built); + if (r < 0) + return log_error_errno(r, "Failed to build prefix unit name: %m"); + + return unit_file_find_dirs(original_root, unit_path_cache, unit_path, built, suffix, dirs); } int unit_file_find_dropin_paths( @@ -193,15 +232,15 @@ int unit_file_find_dropin_paths( char ***ret) { _cleanup_strv_free_ char **dirs = NULL; - Iterator i; char *t, **p; + Iterator i; int r; assert(ret); SET_FOREACH(t, names, i) STRV_FOREACH(p, lookup_path) - unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs); + (void) unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs); if (strv_isempty(dirs)) { *ret = NULL; diff --git a/src/shared/dropin.h b/src/shared/dropin.h index 102fc9403c..ae7379beee 100644 --- a/src/shared/dropin.h +++ b/src/shared/dropin.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2014 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 "hashmap.h" #include "macro.h" #include "set.h" @@ -49,6 +30,7 @@ static inline int unit_file_find_dropin_conf_paths( Set *unit_path_cache, Set *names, char ***paths) { + return unit_file_find_dropin_paths(original_root, lookup_path, unit_path_cache, diff --git a/src/shared/efivars.c b/src/shared/efivars.c index 9ca51cf750..fcc0db8b0b 100644 --- a/src/shared/efivars.c +++ b/src/shared/efivars.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <dirent.h> #include <errno.h> @@ -249,8 +231,7 @@ int efi_get_variable( ((char*) buf)[st.st_size - 4] = 0; ((char*) buf)[st.st_size - 4 + 1] = 0; - *value = buf; - buf = NULL; + *value = TAKE_PTR(buf); *size = (size_t) st.st_size - 4; if (attribute) @@ -428,16 +409,12 @@ int efi_get_boot_option( } } - if (title) { - *title = s; - s = NULL; - } + if (title) + *title = TAKE_PTR(s); if (part_uuid) *part_uuid = p_uuid; - if (path) { - *path = p; - p = NULL; - } + if (path) + *path = TAKE_PTR(p); if (active) *active = !!(header->attr & LOAD_OPTION_ACTIVE); @@ -563,8 +540,7 @@ int efi_get_boot_order(uint16_t **order) { l / sizeof(uint16_t) > INT_MAX) return -EINVAL; - *order = buf; - buf = NULL; + *order = TAKE_PTR(buf); return (int) (l / sizeof(uint16_t)); } @@ -630,8 +606,8 @@ int efi_get_boot_options(uint16_t **options) { qsort_safe(list, count, sizeof(uint16_t), cmp_uint16); - *options = list; - list = NULL; + *options = TAKE_PTR(list); + return count; } diff --git a/src/shared/efivars.h b/src/shared/efivars.h index 5b5951321c..dac66da9f8 100644 --- a/src/shared/efivars.h +++ b/src/shared/efivars.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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/>. -***/ - #if ! ENABLE_EFI #include <errno.h> #endif diff --git a/src/shared/fdset.c b/src/shared/fdset.c index 9ce1295223..8c852f1137 100644 --- a/src/shared/fdset.c +++ b/src/shared/fdset.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <alloca.h> #include <errno.h> @@ -25,6 +7,7 @@ #include "sd-daemon.h" +#include "alloc-util.h" #include "dirent-util.h" #include "fd-util.h" #include "fdset.h" @@ -41,8 +24,8 @@ FDSet *fdset_new(void) { return MAKE_FDSET(set_new(NULL)); } -int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds) { - unsigned i; +int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds) { + size_t i; FDSet *s; int r; @@ -168,8 +151,7 @@ int fdset_new_fill(FDSet **_s) { } r = 0; - *_s = s; - s = NULL; + *_s = TAKE_PTR(s); finish: /* We won't close the fds here! */ @@ -219,7 +201,6 @@ int fdset_new_listen_fds(FDSet **_s, bool unset) { *_s = s; return 0; - fail: if (s) set_free(MAKE_SET(s)); @@ -231,10 +212,10 @@ int fdset_close_others(FDSet *fds) { void *e; Iterator i; int *a; - unsigned j, m; + size_t j = 0, m; - j = 0, m = fdset_size(fds); - a = alloca(sizeof(int) * m); + m = fdset_size(fds); + a = newa(int, m); SET_FOREACH(e, MAKE_SET(fds), i) a[j++] = PTR_TO_FD(e); diff --git a/src/shared/fdset.h b/src/shared/fdset.h index 864ab676f7..d31062b5c6 100644 --- a/src/shared/fdset.h +++ b/src/shared/fdset.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include "hashmap.h" @@ -37,7 +18,7 @@ int fdset_put_dup(FDSet *s, int fd); bool fdset_contains(FDSet *s, int fd); int fdset_remove(FDSet *s, int fd); -int fdset_new_array(FDSet **ret, const int *fds, unsigned n_fds); +int fdset_new_array(FDSet **ret, const int *fds, size_t n_fds); int fdset_new_fill(FDSet **ret); int fdset_new_listen_fds(FDSet **ret, bool unset); diff --git a/src/shared/firewall-util.c b/src/shared/firewall-util.c index a6859462ac..eb4f5ff616 100644 --- a/src/shared/firewall-util.c +++ b/src/shared/firewall-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2015 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/>. -***/ /* Temporary work-around for broken glibc vs. linux kernel header definitions * This is already fixed upstream, remove this when distributions have updated. @@ -181,7 +163,6 @@ int fw_add_local_dnat( uint16_t remote_port, const union in_addr_union *previous_remote) { - _cleanup_(iptc_freep) struct xtc_handle *h = NULL; struct ipt_entry *entry, *mask; struct ipt_entry_target *t; diff --git a/src/shared/firewall-util.h b/src/shared/firewall-util.h index fd7e3b456e..4fc71dade2 100644 --- a/src/shared/firewall-util.h +++ b/src/shared/firewall-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2015 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 <stdbool.h> #include <stdint.h> diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c index bcd7b43084..6fd9866c00 100644 --- a/src/shared/fstab-util.c +++ b/src/shared/fstab-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - 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 <errno.h> #include <mntent.h> @@ -169,10 +151,8 @@ answer: *filtered = f; } - if (value) { - *value = v; - v = NULL; - } + if (value) + *value = TAKE_PTR(v); return !!n; } @@ -201,8 +181,7 @@ int fstab_extract_values(const char *opts, const char *name, char ***values) { return r; } - *values = res; - res = NULL; + *values = TAKE_PTR(res); return !!*values; } diff --git a/src/shared/fstab-util.h b/src/shared/fstab-util.h index 87f82dcfb4..9820f78ca8 100644 --- a/src/shared/fstab-util.h +++ b/src/shared/fstab-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - 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 <stdbool.h> #include <stddef.h> diff --git a/src/shared/generator.c b/src/shared/generator.c index 2b0a4ecdc8..8d4fd3267b 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <errno.h> #include <stdio_ext.h> diff --git a/src/shared/generator.h b/src/shared/generator.h index e1c636a218..f0a493b21e 100644 --- a/src/shared/generator.h +++ b/src/shared/generator.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdio.h> int generator_open_unit_file( diff --git a/src/shared/gpt.h b/src/shared/gpt.h index 7589f6fb7a..fd953fabc7 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <endian.h> #include "sd-id128.h" @@ -46,7 +27,6 @@ #define GPT_ROOT_ARM_64_VERITY SD_ID128_MAKE(df,33,00,ce,d6,9f,4c,92,97,8c,9b,fb,0f,38,d8,20) #define GPT_ROOT_IA64_VERITY SD_ID128_MAKE(86,ed,10,d5,b6,07,45,bb,89,57,d3,50,f2,3d,05,71) - #if defined(__x86_64__) # define GPT_ROOT_NATIVE GPT_ROOT_X86_64 # define GPT_ROOT_SECONDARY GPT_ROOT_X86 diff --git a/src/shared/ima-util.c b/src/shared/ima-util.c index 064f38be6f..0d4ce3cafc 100644 --- a/src/shared/ima-util.c +++ b/src/shared/ima-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <unistd.h> diff --git a/src/shared/ima-util.h b/src/shared/ima-util.h index 5633c78be9..8f20741c33 100644 --- a/src/shared/ima-util.h +++ b/src/shared/ima-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> bool use_ima(void); diff --git a/src/shared/import-util.c b/src/shared/import-util.c index 07ba216e93..d53b90796f 100644 --- a/src/shared/import-util.c +++ b/src/shared/import-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2015 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> @@ -55,7 +37,6 @@ int import_url_last_component(const char *url, char **ret) { return 0; } - int import_url_change_last_component(const char *url, const char *suffix, char **ret) { const char *e; char *s; @@ -153,8 +134,7 @@ int raw_strip_suffixes(const char *p, char **ret) { break; } - *ret = q; - q = NULL; + *ret = TAKE_PTR(q); return 0; } diff --git a/src/shared/import-util.h b/src/shared/import-util.h index 583845b1a4..0f2a5170c8 100644 --- a/src/shared/import-util.h +++ b/src/shared/import-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2015 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 <stdbool.h> #include "macro.h" diff --git a/src/shared/initreq.h b/src/shared/initreq.h index 710037d84b..9b19b5d729 100644 --- a/src/shared/initreq.h +++ b/src/shared/initreq.h @@ -55,7 +55,6 @@ struct init_request_bsd { char reserved[128]; /* For future expansion. */ }; - /* * Because of legacy interfaces, "runlevel" and "sleeptime" * aren't in a separate struct in the union. diff --git a/src/shared/install-printf.c b/src/shared/install-printf.c index aaab2e6665..078d5734be 100644 --- a/src/shared/install-printf.c +++ b/src/shared/install-printf.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - 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 <stdio.h> @@ -50,10 +32,8 @@ static int specifier_prefix_and_instance(char specifier, void *data, void *userd if (!ans) return -ENOMEM; *ret = ans; - } else { - *ret = prefix; - prefix = NULL; - } + } else + *ret = TAKE_PTR(prefix); return 0; } @@ -103,6 +83,27 @@ static int specifier_instance(char specifier, void *data, void *userdata, char * return 0; } +static int specifier_last_component(char specifier, void *data, void *userdata, char **ret) { + _cleanup_free_ char *prefix = NULL; + char *dash; + int r; + + r = specifier_prefix(specifier, data, userdata, &prefix); + if (r < 0) + return r; + + dash = strrchr(prefix, '-'); + if (dash) { + dash = strdup(dash + 1); + if (!dash) + return -ENOMEM; + *ret = dash; + } else + *ret = TAKE_PTR(prefix); + + return 0; +} + int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) { /* This is similar to unit_full_printf() but does not support @@ -126,6 +127,7 @@ int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret) { 'N', specifier_prefix_and_instance, NULL }, { 'p', specifier_prefix, NULL }, { 'i', specifier_instance, NULL }, + { 'j', specifier_last_component, NULL }, { 'U', specifier_user_id, NULL }, { 'u', specifier_user_name, NULL }, diff --git a/src/shared/install-printf.h b/src/shared/install-printf.h index d868f65cfa..378b3bfd92 100644 --- a/src/shared/install-printf.h +++ b/src/shared/install-printf.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - 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 "install.h" int install_full_printf(UnitFileInstallInfo *i, const char *format, char **ret); diff --git a/src/shared/install.c b/src/shared/install.c index ed5f51cc46..77ae812878 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2011 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 <dirent.h> #include <errno.h> @@ -59,8 +41,9 @@ #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64 typedef enum SearchFlags { - SEARCH_LOAD = 1, - SEARCH_FOLLOW_CONFIG_SYMLINKS = 2, + SEARCH_LOAD = 1 << 0, + SEARCH_FOLLOW_CONFIG_SYMLINKS = 1 << 1, + SEARCH_DROPIN = 1 << 2, } SearchFlags; typedef struct { @@ -111,8 +94,6 @@ static inline void presets_freep(Presets *p) { p->n_rules = 0; } -static int unit_file_lookup_state(UnitFileScope scope, const LookupPaths *paths, const char *name, UnitFileState *ret); - bool unit_type_may_alias(UnitType type) { return IN_SET(type, UNIT_SERVICE, @@ -297,7 +278,7 @@ static int path_is_vendor(const LookupPaths *p, const char *path) { int unit_file_changes_add( UnitFileChange **changes, - unsigned *n_changes, + size_t *n_changes, UnitFileChangeType type, const char *path, const char *source) { @@ -323,9 +304,9 @@ int unit_file_changes_add( if (!p || (source && !s)) return -ENOMEM; - path_kill_slashes(p); + path_simplify(p, false); if (s) - path_kill_slashes(s); + path_simplify(s, false); c[*n_changes] = (UnitFileChange) { type, p, s }; p = s = NULL; @@ -333,8 +314,8 @@ int unit_file_changes_add( return 0; } -void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { - unsigned i; +void unit_file_changes_free(UnitFileChange *changes, size_t n_changes) { + size_t i; assert(changes || n_changes == 0); @@ -346,8 +327,8 @@ void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes) { free(changes); } -void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet) { - unsigned i; +void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet) { + size_t i; bool logged = false; assert(changes || n_changes == 0); @@ -446,7 +427,7 @@ static int create_symlink( const char *new_path, bool force, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_free_ char *dest = NULL, *dirname = NULL; const char *rp; @@ -530,7 +511,7 @@ static int mark_symlink_for_removal( if (!n) return -ENOMEM; - path_kill_slashes(n); + path_simplify(n, false); r = set_consume(*remove_symlinks_to, n); if (r == -EEXIST) @@ -550,7 +531,7 @@ static int remove_marked_symlinks_fd( bool dry_run, bool *restart, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -612,7 +593,7 @@ static int remove_marked_symlinks_fd( p = path_make_absolute(de->d_name, path); if (!p) return -ENOMEM; - path_kill_slashes(p); + path_simplify(p, false); q = readlink_malloc(p, &dest); if (q == -ENOENT) @@ -667,7 +648,7 @@ static int remove_marked_symlinks( const LookupPaths *lp, bool dry_run, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_close_ int fd = -1; bool restart; @@ -908,16 +889,13 @@ static int find_symlinks_in_scope( if (r > 0) { /* We found symlinks in this dir? Yay! Let's see where precisely it is enabled. */ - r = path_is_config(paths, *p, false); - if (r < 0) - return r; - if (r > 0) { + if (path_equal_ptr(*p, paths->persistent_config)) { /* This is the best outcome, let's return it immediately. */ *state = UNIT_FILE_ENABLED; return 1; } - /* look for globally enablement of user units */ + /* look for global enablement of user units */ if (scope == UNIT_FILE_USER && path_is_user_config_dir(*p)) { *state = UNIT_FILE_ENABLED; return 1; @@ -932,11 +910,7 @@ static int find_symlinks_in_scope( enabled_at_all = true; } else if (same_name_link) { - - r = path_is_config(paths, *p, false); - if (r < 0) - return r; - if (r > 0) + if (path_equal_ptr(*p, paths->persistent_config)) same_name_link_config = true; else { r = path_is_runtime(paths, *p, false); @@ -1013,7 +987,7 @@ static int install_info_may_process( UnitFileInstallInfo *i, const LookupPaths *paths, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { assert(i); assert(paths); @@ -1228,6 +1202,7 @@ static int unit_file_load( InstallContext *c, UnitFileInstallInfo *info, const char *path, + const char *root_dir, SearchFlags flags) { const ConfigTableItem items[] = { @@ -1248,40 +1223,57 @@ static int unit_file_load( assert(info); assert(path); - type = unit_name_to_type(info->name); - if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && - !unit_type_may_template(type)) - return log_error_errno(EINVAL, "Unit type %s cannot be templated.", unit_type_to_string(type)); + if (!(flags & SEARCH_DROPIN)) { + /* Loading or checking for the main unit file… */ - if (!(flags & SEARCH_LOAD)) { - r = lstat(path, &st); - if (r < 0) + type = unit_name_to_type(info->name); + if (type < 0) + return -EINVAL; + if (unit_name_is_valid(info->name, UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE) && !unit_type_may_template(type)) { + log_error("Unit type %s cannot be templated.", unit_type_to_string(type)); + return -EINVAL; + } + + if (!(flags & SEARCH_LOAD)) { + r = lstat(path, &st); + if (r < 0) + return -errno; + + if (null_or_empty(&st)) + info->type = UNIT_FILE_TYPE_MASKED; + else if (S_ISREG(st.st_mode)) + info->type = UNIT_FILE_TYPE_REGULAR; + else if (S_ISLNK(st.st_mode)) + return -ELOOP; + else if (S_ISDIR(st.st_mode)) + return -EISDIR; + else + return -ENOTTY; + + return 0; + } + + fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) return -errno; + } else { + /* Operating on a drop-in file. If we aren't supposed to load the unit file drop-ins don't matter, let's hence shortcut this. */ - if (null_or_empty(&st)) - info->type = UNIT_FILE_TYPE_MASKED; - else if (S_ISREG(st.st_mode)) - info->type = UNIT_FILE_TYPE_REGULAR; - else if (S_ISLNK(st.st_mode)) - return -ELOOP; - else if (S_ISDIR(st.st_mode)) - return -EISDIR; - else - return -ENOTTY; + if (!(flags & SEARCH_LOAD)) + return 0; - return 0; + fd = chase_symlinks_and_open(path, root_dir, 0, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL); + if (fd < 0) + return fd; } - /* c is only needed if we actually load the file */ - assert(c); - - fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fd < 0) - return -errno; if (fstat(fd, &st) < 0) return -errno; + if (null_or_empty(&st)) { - info->type = UNIT_FILE_TYPE_MASKED; + if ((flags & SEARCH_DROPIN) == 0) + info->type = UNIT_FILE_TYPE_MASKED; + return 0; } @@ -1294,6 +1286,9 @@ static int unit_file_load( return -errno; fd = -1; + /* c is only needed if we actually load the file (it's referenced from items[] btw, in case you wonder.) */ + assert(c); + r = config_parse(info->name, path, f, NULL, config_item_table_lookup, items, @@ -1301,7 +1296,8 @@ static int unit_file_load( if (r < 0) return log_debug_errno(r, "Failed to parse %s: %m", info->name); - info->type = UNIT_FILE_TYPE_REGULAR; + if ((flags & SEARCH_DROPIN) == 0) + info->type = UNIT_FILE_TYPE_REGULAR; return (int) strv_length(info->aliases) + @@ -1319,8 +1315,8 @@ static int unit_file_load_or_readlink( _cleanup_free_ char *target = NULL; int r; - r = unit_file_load(c, info, path, flags); - if (r != -ELOOP) + r = unit_file_load(c, info, path, root_dir, flags); + if (r != -ELOOP || (flags & SEARCH_DROPIN)) return r; /* This is a symlink, let's read it. */ @@ -1383,16 +1379,12 @@ static int unit_file_search( const LookupPaths *paths, SearchFlags flags) { + const char *dropin_dir_name = NULL, *dropin_template_dir_name = NULL; + _cleanup_strv_free_ char **dirs = NULL, **files = NULL; _cleanup_free_ char *template = NULL; - _cleanup_strv_free_ char **dirs = NULL; - _cleanup_strv_free_ char **files = NULL; - const char *dropin_dir_name = NULL; - const char *dropin_template_dir_name = NULL; - - char **p; - int r; - int result; bool found_unit = false; + int r, result; + char **p; assert(info); assert(paths); @@ -1420,10 +1412,8 @@ static int unit_file_search( return -ENOMEM; r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags); - if (r >= 0) { - info->path = path; - path = NULL; + info->path = TAKE_PTR(path); result = r; found_unit = true; break; @@ -1446,8 +1436,7 @@ static int unit_file_search( r = unit_file_load_or_readlink(c, info, path, paths->root_dir, flags); if (r >= 0) { - info->path = path; - path = NULL; + info->path = TAKE_PTR(path); result = r; found_unit = true; break; @@ -1501,7 +1490,7 @@ static int unit_file_search( return log_debug_errno(r, "Failed to get list of conf files: %m"); STRV_FOREACH(p, files) { - r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags); + r = unit_file_load_or_readlink(c, info, *p, paths->root_dir, flags | SEARCH_DROPIN); if (r < 0) return log_debug_errno(r, "Failed to load conf file %s: %m", *p); } @@ -1666,7 +1655,7 @@ static int install_info_discover( SearchFlags flags, UnitFileInstallInfo **ret, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { UnitFileInstallInfo *i; int r; @@ -1690,7 +1679,7 @@ static int install_info_symlink_alias( const char *config_path, bool force, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { char **s; int r = 0, q; @@ -1725,7 +1714,7 @@ static int install_info_symlink_wants( char **list, const char *suffix, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_free_ char *buf = NULL; const char *n; @@ -1754,8 +1743,7 @@ static int install_info_symlink_wants( if (r < 0) return r; - path = instance.path; - instance.path = NULL; + path = TAKE_PTR(instance.path); if (instance.type == UNIT_FILE_TYPE_MASKED) { unit_file_changes_add(changes, n_changes, -ERFKILL, path, NULL); @@ -1796,7 +1784,7 @@ static int install_info_symlink_link( const char *config_path, bool force, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_free_ char *path = NULL; int r; @@ -1825,7 +1813,7 @@ static int install_info_apply( const char *config_path, bool force, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { int r, q; @@ -1862,7 +1850,7 @@ static int install_context_apply( bool force, SearchFlags flags, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { UnitFileInstallInfo *i; int r; @@ -1923,16 +1911,14 @@ static int install_context_mark_for_removal( InstallContext *c, const LookupPaths *paths, Set **remove_symlinks_to, - const char *config_path, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { UnitFileInstallInfo *i; int r; assert(c); assert(paths); - assert(config_path); /* Marks all items for removal */ @@ -1988,9 +1974,9 @@ int unit_file_mask( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; const char *config_path; char **i; int r; @@ -2034,15 +2020,15 @@ int unit_file_unmask( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; _cleanup_strv_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; const char *config_path; char **i; - bool dry_run; + bool dry_run = !!(flags & UNIT_FILE_DRY_RUN); int r, q; assert(scope >= 0); @@ -2052,73 +2038,71 @@ int unit_file_unmask( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; - if (!config_path) - return -ENXIO; - - dry_run = !!(flags & UNIT_FILE_DRY_RUN); - STRV_FOREACH(i, files) { - _cleanup_free_ char *path = NULL; - if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; - path = path_make_absolute(*i, config_path); - if (!path) - return -ENOMEM; + FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) { + _cleanup_free_ char *path = NULL; - r = null_or_empty_path(path); - if (r == -ENOENT) - continue; - if (r < 0) - return r; - if (r == 0) - continue; + path = path_make_absolute(*i, config_path); + if (!path) + return -ENOMEM; - if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) - return -ENOMEM; + r = null_or_empty_path(path); + if (r == -ENOENT) + continue; + if (r < 0) + return r; + if (r == 0) + continue; - todo[n_todo] = strdup(*i); - if (!todo[n_todo]) - return -ENOMEM; + if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) + return -ENOMEM; - n_todo++; + todo[n_todo] = strdup(*i); + if (!todo[n_todo]) + return -ENOMEM; + + n_todo++; + } } strv_uniq(todo); r = 0; - STRV_FOREACH(i, todo) { - _cleanup_free_ char *path = NULL; - const char *rp; + FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) { + STRV_FOREACH(i, todo) { + _cleanup_free_ char *path = NULL; + const char *rp; - path = path_make_absolute(*i, config_path); - if (!path) - return -ENOMEM; + path = path_make_absolute(*i, config_path); + if (!path) + return -ENOMEM; - if (!dry_run && unlink(path) < 0) { - if (errno != ENOENT) { - if (r >= 0) - r = -errno; - unit_file_changes_add(changes, n_changes, -errno, path, NULL); + if (!dry_run && unlink(path) < 0) { + if (errno != ENOENT) { + if (r >= 0) + r = -errno; + unit_file_changes_add(changes, n_changes, -errno, path, NULL); + } + + continue; } - continue; - } + unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); - unit_file_changes_add(changes, n_changes, UNIT_FILE_UNLINK, path, NULL); + rp = skip_root(&paths, path); + q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path); + if (q < 0) + return q; + } - rp = skip_root(&paths, path); - q = mark_symlink_for_removal(&remove_symlinks_to, rp ?: path); - if (q < 0) - return q; + q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); + if (r >= 0) + r = q; } - q = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); - if (r >= 0) - r = q; - return r; } @@ -2128,9 +2112,9 @@ int unit_file_link( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_strv_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; const char *config_path; @@ -2228,10 +2212,10 @@ int unit_file_revert( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_strv_free_ char **todo = NULL; size_t n_todo = 0, n_allocated = 0; char **i; @@ -2297,8 +2281,7 @@ int unit_file_revert( if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) return -ENOMEM; - todo[n_todo++] = dropin; - dropin = NULL; + todo[n_todo++] = TAKE_PTR(dropin); } } } @@ -2327,8 +2310,7 @@ int unit_file_revert( if (!GREEDY_REALLOC0(todo, n_allocated, n_todo + 2)) return -ENOMEM; - todo[n_todo++] = path; - path = NULL; + todo[n_todo++] = TAKE_PTR(path); } } } @@ -2387,9 +2369,9 @@ int unit_file_add_dependency( const char *target, UnitDependency dep, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i, *target_info; const char *config_path; @@ -2461,9 +2443,9 @@ int unit_file_enable( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; const char *config_path; UnitFileInstallInfo *i; @@ -2507,11 +2489,12 @@ int unit_file_disable( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; + bool dry_run = !!(flags & UNIT_FILE_DRY_RUN); const char *config_path; char **i; int r; @@ -2523,10 +2506,6 @@ int unit_file_disable( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; - if (!config_path) - return -ENXIO; - STRV_FOREACH(i, files) { if (!unit_name_is_valid(*i, UNIT_NAME_ANY)) return -EINVAL; @@ -2536,11 +2515,17 @@ int unit_file_disable( return r; } - r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, config_path, changes, n_changes); + r = install_context_mark_for_removal(scope, &c, &paths, &remove_symlinks_to, changes, n_changes); if (r < 0) return r; - return remove_marked_symlinks(remove_symlinks_to, config_path, &paths, !!(flags & UNIT_FILE_DRY_RUN), changes, n_changes); + FOREACH_STRING(config_path, paths.runtime_config, paths.persistent_config) { + r = remove_marked_symlinks(remove_symlinks_to, config_path, &paths, dry_run, changes, n_changes); + if (r < 0) + return r; + } + + return 0; } int unit_file_reenable( @@ -2549,7 +2534,7 @@ int unit_file_reenable( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { char **n; int r; @@ -2576,9 +2561,9 @@ int unit_file_set_default( const char *root_dir, const char *name, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i; const char *new_path; @@ -2613,7 +2598,7 @@ int unit_file_get_default( const char *root_dir, char **name) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(install_context_done) InstallContext c = {}; UnitFileInstallInfo *i; char *n; @@ -2643,7 +2628,7 @@ int unit_file_get_default( return 0; } -static int unit_file_lookup_state( +int unit_file_lookup_state( UnitFileScope scope, const LookupPaths *paths, const char *name, @@ -2737,7 +2722,7 @@ int unit_file_get_state( const char *name, UnitFileState *ret) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; int r; assert(scope >= 0); @@ -2781,7 +2766,8 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres assert(scope < _UNIT_FILE_SCOPE_MAX); assert(presets); - if (scope == UNIT_FILE_SYSTEM) + switch (scope) { + case UNIT_FILE_SYSTEM: r = conf_files_list(&files, ".preset", root_dir, 0, "/etc/systemd/system-preset", "/run/systemd/system-preset", @@ -2791,17 +2777,20 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres "/lib/systemd/system-preset", #endif NULL); - else if (scope == UNIT_FILE_GLOBAL) + break; + + case UNIT_FILE_GLOBAL: + case UNIT_FILE_USER: r = conf_files_list(&files, ".preset", root_dir, 0, "/etc/systemd/user-preset", "/run/systemd/user-preset", "/usr/local/lib/systemd/user-preset", "/usr/lib/systemd/user-preset", NULL); - else { - *presets = (Presets){}; + break; - return 0; + default: + assert_not_reached("Invalid unit file scope"); } if (r < 0) @@ -2920,45 +2909,45 @@ int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char static int execute_preset( UnitFileScope scope, + UnitFileFlags flags, InstallContext *plus, InstallContext *minus, const LookupPaths *paths, - const char *config_path, char **files, UnitFilePresetMode mode, - bool force, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { - int r; + const char *config_path; + bool force = !!(flags & UNIT_FILE_FORCE); + bool runtime = !!(flags & UNIT_FILE_RUNTIME); + int r = 0, q; assert(plus); assert(minus); assert(paths); - assert(config_path); if (mode != UNIT_FILE_PRESET_ENABLE_ONLY) { _cleanup_set_free_free_ Set *remove_symlinks_to = NULL; - r = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, config_path, changes, n_changes); - if (r < 0) - return r; + q = install_context_mark_for_removal(scope, minus, paths, &remove_symlinks_to, changes, n_changes); + if (q < 0) + return q; - r = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes); - } else - r = 0; + FOREACH_STRING(config_path, paths->runtime_config, paths->persistent_config) { + q = remove_marked_symlinks(remove_symlinks_to, config_path, paths, false, changes, n_changes); + if (r == 0) + r = q; + } + } if (mode != UNIT_FILE_PRESET_DISABLE_ONLY) { - int q; - /* Returns number of symlinks that where supposed to be installed. */ - q = install_context_apply(scope, plus, paths, config_path, force, SEARCH_LOAD, changes, n_changes); - if (r >= 0) { - if (q < 0) - r = q; - else - r += q; - } + q = install_context_apply(scope, plus, paths, + runtime ? paths->runtime_config : paths->persistent_config, + force, SEARCH_LOAD, changes, n_changes); + if (r == 0) + r = q; } return r; @@ -2972,7 +2961,7 @@ static int preset_prepare_one( const char *name, Presets presets, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_(install_context_done) InstallContext tmp = {}; UnitFileInstallInfo *i; @@ -3017,12 +3006,11 @@ int unit_file_preset( char **files, UnitFilePresetMode mode, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(presets_freep) Presets presets = {}; - const char *config_path; char **i; int r; @@ -3034,10 +3022,6 @@ int unit_file_preset( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; - if (!config_path) - return -ENXIO; - r = read_presets(scope, root_dir, &presets); if (r < 0) return r; @@ -3048,7 +3032,7 @@ int unit_file_preset( return r; } - return execute_preset(scope, &plus, &minus, &paths, config_path, files, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + return execute_preset(scope, flags, &plus, &minus, &paths, files, mode, changes, n_changes); } int unit_file_preset_all( @@ -3057,12 +3041,11 @@ int unit_file_preset_all( const char *root_dir, UnitFilePresetMode mode, UnitFileChange **changes, - unsigned *n_changes) { + size_t *n_changes) { _cleanup_(install_context_done) InstallContext plus = {}, minus = {}; - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(presets_freep) Presets presets = {}; - const char *config_path = NULL; char **i; int r; @@ -3074,10 +3057,6 @@ int unit_file_preset_all( if (r < 0) return r; - config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config; - if (!config_path) - return -ENXIO; - r = read_presets(scope, root_dir, &presets); if (r < 0) return r; @@ -3095,7 +3074,6 @@ int unit_file_preset_all( } FOREACH_DIRENT(de, d, return -errno) { - if (!unit_name_is_valid(de->d_name, UNIT_NAME_ANY)) continue; @@ -3119,7 +3097,7 @@ int unit_file_preset_all( } } - return execute_preset(scope, &plus, &minus, &paths, config_path, NULL, mode, !!(flags & UNIT_FILE_FORCE), changes, n_changes); + return execute_preset(scope, flags, &plus, &minus, &paths, NULL, mode, changes, n_changes); } static void unit_file_list_free_one(UnitFileList *f) { @@ -3143,7 +3121,7 @@ int unit_file_get_list( char **states, char **patterns) { - _cleanup_lookup_paths_free_ LookupPaths paths = {}; + _cleanup_(lookup_paths_free) LookupPaths paths = {}; char **i; int r; diff --git a/src/shared/install.h b/src/shared/install.h index 6d7518d72a..e452940991 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2011 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/>. -***/ - typedef enum UnitFileScope UnitFileScope; typedef enum UnitFileState UnitFileState; typedef enum UnitFilePresetMode UnitFilePresetMode; @@ -77,12 +58,12 @@ enum UnitFileChangeType { UNIT_FILE_IS_MASKED, UNIT_FILE_IS_DANGLING, _UNIT_FILE_CHANGE_TYPE_MAX, - _UNIT_FILE_CHANGE_INVALID = INT_MIN + _UNIT_FILE_CHANGE_TYPE_INVALID = INT_MIN }; enum UnitFileFlags { - UNIT_FILE_RUNTIME = 1, - UNIT_FILE_FORCE = 1 << 1, + UNIT_FILE_RUNTIME = 1 << 0, + UNIT_FILE_FORCE = 1 << 1, UNIT_FILE_DRY_RUN = 1 << 2, }; @@ -96,8 +77,8 @@ struct UnitFileChange { char *source; }; -static inline bool unit_file_changes_have_modification(const UnitFileChange* changes, unsigned n_changes) { - unsigned i; +static inline bool unit_file_changes_have_modification(const UnitFileChange* changes, size_t n_changes) { + size_t i; for (i = 0; i < n_changes; i++) if (IN_SET(changes[i].type, UNIT_FILE_SYMLINK, UNIT_FILE_UNLINK)) return true; @@ -142,21 +123,21 @@ int unit_file_enable( const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_disable( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_reenable( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_preset( UnitFileScope scope, UnitFileFlags flags, @@ -164,48 +145,48 @@ int unit_file_preset( char **files, UnitFilePresetMode mode, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_preset_all( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, UnitFilePresetMode mode, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_mask( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_unmask( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_link( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_revert( UnitFileScope scope, const char *root_dir, char **files, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_set_default( UnitFileScope scope, UnitFileFlags flags, const char *root_dir, const char *file, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); int unit_file_get_default( UnitFileScope scope, const char *root_dir, @@ -218,7 +199,13 @@ int unit_file_add_dependency( const char *target, UnitDependency dep, UnitFileChange **changes, - unsigned *n_changes); + size_t *n_changes); + +int unit_file_lookup_state( + UnitFileScope scope, + const LookupPaths *paths, + const char *name, + UnitFileState *ret); int unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename, UnitFileState *ret); int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char *name); @@ -226,9 +213,9 @@ int unit_file_exists(UnitFileScope scope, const LookupPaths *paths, const char * int unit_file_get_list(UnitFileScope scope, const char *root_dir, Hashmap *h, char **states, char **patterns); Hashmap* unit_file_list_free(Hashmap *h); -int unit_file_changes_add(UnitFileChange **changes, unsigned *n_changes, UnitFileChangeType type, const char *path, const char *source); -void unit_file_changes_free(UnitFileChange *changes, unsigned n_changes); -void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, unsigned n_changes, bool quiet); +int unit_file_changes_add(UnitFileChange **changes, size_t *n_changes, UnitFileChangeType type, const char *path, const char *source); +void unit_file_changes_free(UnitFileChange *changes, size_t n_changes); +void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *changes, size_t n_changes, bool quiet); int unit_file_query_preset(UnitFileScope scope, const char *root_dir, const char *name); diff --git a/src/shared/journal-util.c b/src/shared/journal-util.c index 7d53f9dd56..89b76af5b3 100644 --- a/src/shared/journal-util.c +++ b/src/shared/journal-util.c @@ -1,23 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2013 Zbigniew Jędrzejewski-Szmek - Copyright 2015 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 "acl-util.h" #include "fs-util.h" diff --git a/src/shared/journal-util.h b/src/shared/journal-util.h index f973729a32..404fa53b30 100644 --- a/src/shared/journal-util.h +++ b/src/shared/journal-util.h @@ -1,23 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2013 Zbigniew Jędrzejewski-Szmek - Copyright 2015 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 <stdbool.h> #include <sys/types.h> diff --git a/src/shared/libshared.sym b/src/shared/libshared.sym index e4ae17eede..6a7495adc3 100644 --- a/src/shared/libshared.sym +++ b/src/shared/libshared.sym @@ -1,3 +1,3 @@ SD_SHARED { - global: *; + global: *; }; diff --git a/src/shared/linux/auto_dev-ioctl.h b/src/shared/linux/auto_dev-ioctl.h index b3555fb2c8..d9838eba49 100644 --- a/src/shared/linux/auto_dev-ioctl.h +++ b/src/shared/linux/auto_dev-ioctl.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2008 Red Hat, Inc. All rights reserved. - * Copyright 2008 Ian Kent <raven@themaw.net> + * Copyright © 2008 Red Hat, Inc. All rights reserved. + * Copyright © 2008 Ian Kent <raven@themaw.net> * * This file is part of the Linux kernel and is made available under * the terms of the GNU General Public License, version 2, or at your diff --git a/src/shared/linux/libbpf.h b/src/shared/linux/libbpf.h index 1989e3a869..ad131fcb12 100644 --- a/src/shared/linux/libbpf.h +++ b/src/shared/linux/libbpf.h @@ -104,7 +104,6 @@ struct bpf_insn; #define BPF_LD_MAP_FD(DST, MAP_FD) \ BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD) - /* Direct packet access, R0 = *(uint *) (skb->data + imm32) */ #define BPF_LD_ABS(SIZE, IMM) \ diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 5609e42feb..33afbe2f7f 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2012 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> @@ -65,7 +47,6 @@ static int print_catalog(FILE *f, sd_journal *j) { int r; _cleanup_free_ char *t = NULL, *z = NULL; - r = sd_journal_get_catalog(j, &t); if (r < 0) return r; @@ -97,7 +78,6 @@ static int parse_field(const void *data, size_t length, const char *field, size_ nl = length - field_len; - buf = newdup_suffix0(char, (const char*) data + field_len, nl); if (!buf) return log_oom(); @@ -308,20 +288,14 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou assert(f); assert(j); - r = -ENXIO; if (realtime) r = safe_atou64(realtime, &x); - if (r < 0) + if (!realtime || r < 0 || !VALID_REALTIME(x)) r = sd_journal_get_realtime_usec(j, &x); if (r < 0) return log_error_errno(r, "Failed to get realtime timestamp: %m"); - if (x > USEC_TIMESTAMP_FORMATTABLE_MAX) { - log_error("Timestamp cannot be printed"); - return -EINVAL; - } - - if (mode == OUTPUT_SHORT_FULL) { + if (IN_SET(mode, OUTPUT_SHORT_FULL, OUTPUT_WITH_UNIT)) { const char *k; if (flags & OUTPUT_UTC) @@ -329,7 +303,7 @@ static int output_timestamp_realtime(FILE *f, sd_journal *j, OutputMode mode, Ou else k = format_timestamp(buf, sizeof(buf), x); if (!k) { - log_error("Failed to format timestamp."); + log_error("Failed to format timestamp: %"PRIu64, x); return -EINVAL; } @@ -406,8 +380,8 @@ static int output_short( const void *data; size_t length; size_t n = 0; - _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL; - size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0; + _cleanup_free_ char *hostname = NULL, *identifier = NULL, *comm = NULL, *pid = NULL, *fake_pid = NULL, *message = NULL, *realtime = NULL, *monotonic = NULL, *priority = NULL, *unit = NULL, *user_unit = NULL; + size_t hostname_len = 0, identifier_len = 0, comm_len = 0, pid_len = 0, fake_pid_len = 0, message_len = 0, realtime_len = 0, monotonic_len = 0, priority_len = 0, unit_len = 0, user_unit_len = 0; int p = LOG_INFO; bool ellipsized = false; const ParseFieldVec fields[] = { @@ -420,6 +394,8 @@ static int output_short( PARSE_FIELD_VEC_ENTRY("SYSLOG_IDENTIFIER=", &identifier, &identifier_len), PARSE_FIELD_VEC_ENTRY("_SOURCE_REALTIME_TIMESTAMP=", &realtime, &realtime_len), PARSE_FIELD_VEC_ENTRY("_SOURCE_MONOTONIC_TIMESTAMP=", &monotonic, &monotonic_len), + PARSE_FIELD_VEC_ENTRY("_SYSTEMD_UNIT=", &unit, &unit_len), + PARSE_FIELD_VEC_ENTRY("_SYSTEMD_USER_UNIT=", &user_unit, &user_unit_len), }; size_t highlight_shifted[] = {highlight ? highlight[0] : 0, highlight ? highlight[1] : 0}; @@ -435,7 +411,6 @@ static int output_short( sd_journal_set_data_threshold(j, flags & (OUTPUT_SHOW_ALL|OUTPUT_FULL_WIDTH) ? 0 : PRINT_CHAR_THRESHOLD + 1); JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { - r = parse_fieldv(data, length, fields, ELEMENTSOF(fields)); if (r < 0) return r; @@ -477,7 +452,19 @@ static int output_short( n += hostname_len + 1; } - if (identifier && shall_print(identifier, identifier_len, flags)) { + if (mode == OUTPUT_WITH_UNIT && ((unit && shall_print(unit, unit_len, flags)) || (user_unit && shall_print(user_unit, user_unit_len, flags)))) { + if (unit) { + fprintf(f, " %.*s", (int) unit_len, unit); + n += unit_len + 1; + } + if (user_unit) { + if (unit) + fprintf(f, "/%.*s", (int) user_unit_len, user_unit); + else + fprintf(f, " %.*s", (int) user_unit_len, user_unit); + n += unit_len + 1; + } + } else if (identifier && shall_print(identifier, identifier_len, flags)) { fprintf(f, " %.*s", (int) identifier_len, identifier); n += identifier_len + 1; } else if (comm && shall_print(comm, comm_len, flags)) { @@ -665,10 +652,8 @@ static int output_export( JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) { const char *c; - /* We already printed the boot id, from the data in - * the header, hence let's suppress it here */ - if (length >= 9 && - startswith(data, "_BOOT_ID=")) + /* We already printed the boot id from the data in the header, hence let's suppress it here */ + if (memory_startswith(data, length, "_BOOT_ID=")) continue; c = memchr(data, '=', length); @@ -833,15 +818,14 @@ static int output_json( char *n; unsigned u; - if (length >= 9 && - memcmp(data, "_BOOT_ID=", 9) == 0) + if (memory_startswith(data, length, "_BOOT_ID=")) continue; eq = memchr(data, '=', length); if (!eq) continue; - n = strndup(data, eq - (const char*) data); + n = memdup_suffix0(data, eq - (const char*) data); if (!n) { r = log_oom(); goto finish; @@ -864,12 +848,10 @@ static int output_json( } } } - if (r == -EBADMSG) { log_debug_errno(r, "Skipping message we can't read: %m"); return 0; } - if (r < 0) return r; @@ -879,14 +861,14 @@ static int output_json( SD_JOURNAL_FOREACH_DATA(j, data, length) { const char *eq; - char *kk, *n; + char *kk; + _cleanup_free_ char *n = NULL; size_t m; unsigned u; - /* We already printed the boot id, from the data in + /* We already printed the boot id from the data in * the header, hence let's suppress it here */ - if (length >= 9 && - memcmp(data, "_BOOT_ID=", 9) == 0) + if (memory_startswith(data, length, "_BOOT_ID=")) continue; eq = memchr(data, '=', length); @@ -894,33 +876,24 @@ static int output_json( continue; m = eq - (const char*) data; - - n = strndup(data, m); + n = memdup_suffix0(data, m); if (!n) { r = log_oom(); goto finish; } - if (output_fields && !set_get(output_fields, n)) { - free(n); + if (output_fields && !set_get(output_fields, n)) continue; - } - if (separator) { - if (mode == OUTPUT_JSON_PRETTY) - fputs(",\n\t", f); - else - fputs(", ", f); - } + if (separator) + fputs(mode == OUTPUT_JSON_PRETTY ? ",\n\t" : ", ", f); u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk)); - if (u == 0) { + if (u == 0) /* We already printed this, let's jump to the next */ - free(n); separator = false; - continue; - } else if (u == 1) { + else if (u == 1) { /* Field only appears once, output it directly */ json_escape(f, data, m, flags); @@ -930,12 +903,9 @@ static int output_json( hashmap_remove(h, n); free(kk); - free(n); separator = true; - continue; - } else { /* Field appears multiple times, output it as array */ json_escape(f, data, m, flags); @@ -962,7 +932,6 @@ static int output_json( hashmap_remove(h, n); free(kk); - free(n); /* Iterate data fields form the beginning */ done = false; @@ -1068,10 +1037,11 @@ static int (*output_funcs[_OUTPUT_MODE_MAX])( [OUTPUT_JSON] = output_json, [OUTPUT_JSON_PRETTY] = output_json, [OUTPUT_JSON_SSE] = output_json, - [OUTPUT_CAT] = output_cat + [OUTPUT_CAT] = output_cat, + [OUTPUT_WITH_UNIT] = output_short, }; -int output_journal( +int show_journal_entry( FILE *f, sd_journal *j, OutputMode mode, @@ -1122,14 +1092,15 @@ static int maybe_print_begin_newline(FILE *f, OutputFlags *flags) { return 0; } -static int show_journal(FILE *f, - sd_journal *j, - OutputMode mode, - unsigned n_columns, - usec_t not_before, - unsigned how_many, - OutputFlags flags, - bool *ellipsized) { +int show_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags, + bool *ellipsized) { int r; unsigned line = 0; @@ -1140,14 +1111,18 @@ static int show_journal(FILE *f, assert(mode >= 0); assert(mode < _OUTPUT_MODE_MAX); - /* Seek to end */ - r = sd_journal_seek_tail(j); - if (r < 0) - return log_error_errno(r, "Failed to seek to tail: %m"); + if (how_many == (unsigned) -1) + need_seek = true; + else { + /* Seek to end */ + r = sd_journal_seek_tail(j); + if (r < 0) + return log_error_errno(r, "Failed to seek to tail: %m"); - r = sd_journal_previous_skip(j, how_many); - if (r < 0) - return log_error_errno(r, "Failed to skip previous: %m"); + r = sd_journal_previous_skip(j, how_many); + if (r < 0) + return log_error_errno(r, "Failed to skip previous: %m"); + } for (;;) { for (;;) { @@ -1181,7 +1156,7 @@ static int show_journal(FILE *f, line++; maybe_print_begin_newline(f, &flags); - r = output_journal(f, j, mode, n_columns, flags, NULL, NULL, ellipsized); + r = show_journal_entry(f, j, mode, n_columns, flags, NULL, NULL, ellipsized); if (r < 0) return r; } diff --git a/src/shared/logs-show.h b/src/shared/logs-show.h index c876dcc46a..002d06af84 100644 --- a/src/shared/logs-show.h +++ b/src/shared/logs-show.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2012 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 <stdbool.h> #include <stddef.h> #include <stdio.h> @@ -32,7 +13,7 @@ #include "time-util.h" #include "util.h" -int output_journal( +int show_journal_entry( FILE *f, sd_journal *j, OutputMode mode, @@ -41,6 +22,15 @@ int output_journal( char **output_fields, size_t highlight[2], bool *ellipsized); +int show_journal( + FILE *f, + sd_journal *j, + OutputMode mode, + unsigned n_columns, + usec_t not_before, + unsigned how_many, + OutputFlags flags, + bool *ellipsized); int add_match_this_boot(sd_journal *j, const char *machine); diff --git a/src/shared/loop-util.c b/src/shared/loop-util.c index 0f3defd581..872c25c3dc 100644 --- a/src/shared/loop-util.c +++ b/src/shared/loop-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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> @@ -100,14 +82,11 @@ int loop_device_make(int fd, int open_flags, LoopDevice **ret) { return -ENOMEM; *d = (LoopDevice) { - .fd = loop, - .node = loopdev, + .fd = TAKE_FD(loop), + .node = TAKE_PTR(loopdev), .nr = nr, }; - loop = -1; - loopdev = NULL; - *ret = d; return (*ret)->fd; diff --git a/src/shared/loop-util.h b/src/shared/loop-util.h index 7e18e5779d..d78466c5ee 100644 --- a/src/shared/loop-util.h +++ b/src/shared/loop-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 "macro.h" typedef struct LoopDevice LoopDevice; diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c index 66eefb3036..00a5eff670 100644 --- a/src/shared/machine-image.c +++ b/src/shared/machine-image.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <dirent.h> #include <errno.h> @@ -48,6 +30,7 @@ #include "machine-image.h" #include "macro.h" #include "mkdir.h" +#include "os-util.h" #include "path-util.h" #include "rm-rf.h" #include "string-table.h" @@ -58,16 +41,31 @@ #include "util.h" #include "xattr-util.h" -static const char image_search_path[] = - "/var/lib/machines\0" - "/var/lib/container\0" /* legacy */ - "/usr/local/lib/machines\0" - "/usr/lib/machines\0"; +static const char* const image_search_path[_IMAGE_CLASS_MAX] = { + [IMAGE_MACHINE] = "/etc/machines\0" /* only place symlinks here */ + "/run/machines\0" /* and here too */ + "/var/lib/machines\0" /* the main place for images */ + "/var/lib/container\0" /* legacy */ + "/usr/local/lib/machines\0" + "/usr/lib/machines\0", + + [IMAGE_PORTABLE] = "/etc/portables\0" /* only place symlinks here */ + "/run/portables\0" /* and here too */ + "/var/lib/portables\0" /* the main place for images */ + "/usr/local/lib/portables\0" + "/usr/lib/portables\0", +}; Image *image_unref(Image *i) { if (!i) return NULL; + assert(i->n_ref > 0); + i->n_ref--; + + if (i->n_ref > 0) + return NULL; + free(i->name); free(i->path); @@ -78,9 +76,18 @@ Image *image_unref(Image *i) { return mfree(i); } +Image *image_ref(Image *i) { + if (!i) + return NULL; + + assert(i->n_ref > 0); + i->n_ref++; + + return i; +} + static char **image_settings_path(Image *image) { _cleanup_strv_free_ char **l = NULL; - char **ret; const char *fn, *s; unsigned i = 0; @@ -104,10 +111,7 @@ static char **image_settings_path(Image *image) { if (!l[i]) return NULL; - ret = l; - l = NULL; - - return ret; + return TAKE_PTR(l); } static char *image_roothash_path(Image *image) { @@ -142,6 +146,7 @@ static int image_new( if (!i) return -ENOMEM; + i->n_ref = 1; i->type = t; i->read_only = read_only; i->crtime = crtime; @@ -157,15 +162,45 @@ static int image_new( i->path = strjoin(path, "/", filename); else i->path = strdup(filename); - if (!i->path) return -ENOMEM; - path_kill_slashes(i->path); + path_simplify(i->path, false); + + *ret = TAKE_PTR(i); + + return 0; +} + +static int extract_pretty(const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *name = NULL; + const char *p; + size_t n; + + assert(path); + assert(ret); + + p = last_path_component(path); + n = strcspn(p, "/"); + + name = strndup(p, n); + if (!name) + return -ENOMEM; + + if (suffix) { + char *e; + + e = endswith(name, suffix); + if (!e) + return -EINVAL; - *ret = i; - i = NULL; + *e = 0; + } + + if (!image_name_is_valid(name)) + return -EINVAL; + *ret = TAKE_PTR(name); return 0; } @@ -174,40 +209,55 @@ static int image_make( int dfd, const char *path, const char *filename, + const struct stat *st, Image **ret) { - struct stat st; + _cleanup_free_ char *pretty_buffer = NULL; + struct stat stbuf; bool read_only; int r; + assert(dfd >= 0 || dfd == AT_FDCWD); assert(filename); /* We explicitly *do* follow symlinks here, since we want to allow symlinking trees, raw files and block - * devices into /var/lib/machines/, and treat them normally. */ + * devices into /var/lib/machines/, and treat them normally. + * + * This function returns -ENOENT if we can't find the image after all, and -EMEDIUMTYPE if it's not a file we + * recognize. */ - if (fstatat(dfd, filename, &st, 0) < 0) - return -errno; + if (!st) { + if (fstatat(dfd, filename, &stbuf, 0) < 0) + return -errno; + + st = &stbuf; + } read_only = (path && path_startswith(path, "/usr")) || (faccessat(dfd, filename, W_OK, AT_EACCESS) < 0 && errno == EROFS); - if (S_ISDIR(st.st_mode)) { + if (S_ISDIR(st->st_mode)) { _cleanup_close_ int fd = -1; unsigned file_attr = 0; if (!ret) - return 1; + return 0; - if (!pretty) - pretty = filename; + if (!pretty) { + r = extract_pretty(filename, NULL, &pretty_buffer); + if (r < 0) + return r; + + pretty = pretty_buffer; + } fd = openat(dfd, filename, O_CLOEXEC|O_NOCTTY|O_DIRECTORY); if (fd < 0) return -errno; /* btrfs subvolumes have inode 256 */ - if (st.st_ino == 256) { + if (st->st_ino == 256) { r = btrfs_is_filesystem(fd); if (r < 0) @@ -245,7 +295,7 @@ static int image_make( } } - return 1; + return 0; } } @@ -266,56 +316,69 @@ static int image_make( if (r < 0) return r; - return 1; + return 0; - } else if (S_ISREG(st.st_mode) && endswith(filename, ".raw")) { + } else if (S_ISREG(st->st_mode) && endswith(filename, ".raw")) { usec_t crtime = 0; /* It's a RAW disk image */ if (!ret) - return 1; + return 0; + + (void) fd_getcrtime_at(dfd, filename, &crtime, 0); - fd_getcrtime_at(dfd, filename, &crtime, 0); + if (!pretty) { + r = extract_pretty(filename, ".raw", &pretty_buffer); + if (r < 0) + return r; - if (!pretty) - pretty = strndupa(filename, strlen(filename) - 4); + pretty = pretty_buffer; + } r = image_new(IMAGE_RAW, pretty, path, filename, - !(st.st_mode & 0222) || read_only, + !(st->st_mode & 0222) || read_only, crtime, - timespec_load(&st.st_mtim), + timespec_load(&st->st_mtim), ret); if (r < 0) return r; - (*ret)->usage = (*ret)->usage_exclusive = st.st_blocks * 512; - (*ret)->limit = (*ret)->limit_exclusive = st.st_size; + (*ret)->usage = (*ret)->usage_exclusive = st->st_blocks * 512; + (*ret)->limit = (*ret)->limit_exclusive = st->st_size; - return 1; + return 0; - } else if (S_ISBLK(st.st_mode)) { + } else if (S_ISBLK(st->st_mode)) { _cleanup_close_ int block_fd = -1; uint64_t size = UINT64_MAX; /* A block device */ if (!ret) - return 1; + return 0; - if (!pretty) - pretty = filename; + if (!pretty) { + r = extract_pretty(filename, NULL, &pretty_buffer); + if (r < 0) + return r; + + pretty = pretty_buffer; + } block_fd = openat(dfd, filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); if (block_fd < 0) log_debug_errno(errno, "Failed to open block device %s/%s, ignoring: %m", path, filename); else { - if (fstat(block_fd, &st) < 0) + /* Refresh stat data after opening the node */ + if (fstat(block_fd, &stbuf) < 0) return -errno; - if (!S_ISBLK(st.st_mode)) /* Verify that what we opened is actually what we think it is */ + st = &stbuf; + + if (!S_ISBLK(st->st_mode)) /* Verify that what we opened is actually what we think it is */ return -ENOTTY; if (!read_only) { @@ -328,7 +391,7 @@ static int image_make( } if (ioctl(block_fd, BLKGETSIZE64, &size) < 0) - log_debug_errno(errno, "Failed to issue BLKFLSBUF on device %s/%s, ignoring: %m", path, filename); + log_debug_errno(errno, "Failed to issue BLKGETSIZE64 on device %s/%s, ignoring: %m", path, filename); block_fd = safe_close(block_fd); } @@ -337,7 +400,7 @@ static int image_make( pretty, path, filename, - !(st.st_mode & 0222) || read_only, + !(st->st_mode & 0222) || read_only, 0, 0, ret); @@ -347,24 +410,27 @@ static int image_make( if (size != 0 && size != UINT64_MAX) (*ret)->usage = (*ret)->usage_exclusive = (*ret)->limit = (*ret)->limit_exclusive = size; - return 1; + return 0; } - return 0; + return -EMEDIUMTYPE; } -int image_find(const char *name, Image **ret) { +int image_find(ImageClass class, const char *name, Image **ret) { const char *path; int r; + assert(class >= 0); + assert(class < _IMAGE_CLASS_MAX); assert(name); /* There are no images with invalid names */ if (!image_name_is_valid(name)) - return 0; + return -ENOENT; - NULSTR_FOREACH(path, image_search_path) { + NULSTR_FOREACH(path, image_search_path[class]) { _cleanup_closedir_ DIR *d = NULL; + struct stat st; d = opendir(path); if (!d) { @@ -374,37 +440,90 @@ int image_find(const char *name, Image **ret) { return -errno; } - r = image_make(NULL, dirfd(d), path, name, ret); - if (IN_SET(r, 0, -ENOENT)) { + /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people to + * symlink block devices into the search path */ + if (fstatat(dirfd(d), name, &st, 0) < 0) { _cleanup_free_ char *raw = NULL; + if (errno != ENOENT) + return -errno; + raw = strappend(name, ".raw"); if (!raw) return -ENOMEM; - r = image_make(NULL, dirfd(d), path, raw, ret); - if (IN_SET(r, 0, -ENOENT)) + if (fstatat(dirfd(d), raw, &st, 0) < 0) { + + if (errno == ENOENT) + continue; + + return -errno; + } + + if (!S_ISREG(st.st_mode)) continue; + + r = image_make(name, dirfd(d), path, raw, &st, ret); + + } else { + if (!S_ISDIR(st.st_mode) && !S_ISBLK(st.st_mode)) + continue; + + r = image_make(name, dirfd(d), path, name, &st, ret); } + if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) + continue; if (r < 0) return r; + if (ret) + (*ret)->discoverable = true; + return 1; } - if (streq(name, ".host")) - return image_make(".host", AT_FDCWD, NULL, "/", ret); + if (class == IMAGE_MACHINE && streq(name, ".host")) { + r = image_make(".host", AT_FDCWD, NULL, "/", NULL, ret); + if (r < 0) + return r; - return 0; + if (ret) + (*ret)->discoverable = true; + + return r; + } + + return -ENOENT; }; -int image_discover(Hashmap *h) { +int image_from_path(const char *path, Image **ret) { + + /* Note that we don't set the 'discoverable' field of the returned object, because we don't check here whether + * the image is in the image search path. And if it is we don't know if the path we used is actually not + * overridden by another, different image earlier in the search path */ + + if (path_equal(path, "/")) + return image_make(".host", AT_FDCWD, NULL, "/", NULL, ret); + + return image_make(NULL, AT_FDCWD, NULL, path, NULL, ret); +} + +int image_find_harder(ImageClass class, const char *name_or_path, Image **ret) { + if (image_name_is_valid(name_or_path)) + return image_find(class, name_or_path, ret); + + return image_from_path(name_or_path, ret); +} + +int image_discover(ImageClass class, Hashmap *h) { const char *path; int r; + assert(class >= 0); + assert(class < _IMAGE_CLASS_MAX); assert(h); - NULSTR_FOREACH(path, image_search_path) { + NULSTR_FOREACH(path, image_search_path[class]) { _cleanup_closedir_ DIR *d = NULL; struct dirent *de; @@ -418,19 +537,53 @@ int image_discover(Hashmap *h) { FOREACH_DIRENT_ALL(de, d, return -errno) { _cleanup_(image_unrefp) Image *image = NULL; + _cleanup_free_ char *truncated = NULL; + const char *pretty; + struct stat st; - if (!image_name_is_valid(de->d_name)) + if (dot_or_dot_dot(de->d_name)) continue; - if (hashmap_contains(h, de->d_name)) + /* As mentioned above, we follow symlinks on this fstatat(), because we want to permit people + * to symlink block devices into the search path */ + if (fstatat(dirfd(d), de->d_name, &st, 0) < 0) { + if (errno == ENOENT) + continue; + + return -errno; + } + + if (S_ISREG(st.st_mode)) { + const char *e; + + e = endswith(de->d_name, ".raw"); + if (!e) + continue; + + truncated = strndup(de->d_name, e - de->d_name); + if (!truncated) + return -ENOMEM; + + pretty = truncated; + } else if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) + pretty = de->d_name; + else + continue; + + if (!image_name_is_valid(pretty)) + continue; + + if (hashmap_contains(h, pretty)) continue; - r = image_make(NULL, dirfd(d), path, de->d_name, &image); - if (IN_SET(r, 0, -ENOENT)) + r = image_make(pretty, dirfd(d), path, de->d_name, &st, &image); + if (IN_SET(r, -ENOENT, -EMEDIUMTYPE)) continue; if (r < 0) return r; + image->discoverable = true; + r = hashmap_put(h, image->name, image); if (r < 0) return r; @@ -439,26 +592,27 @@ int image_discover(Hashmap *h) { } } - if (!hashmap_contains(h, ".host")) { + if (class == IMAGE_MACHINE && !hashmap_contains(h, ".host")) { _cleanup_(image_unrefp) Image *image = NULL; - r = image_make(".host", AT_FDCWD, NULL, "/", &image); + r = image_make(".host", AT_FDCWD, NULL, "/", NULL, &image); if (r < 0) return r; + image->discoverable = true; + r = hashmap_put(h, image->name, image); if (r < 0) return r; image = NULL; - } return 0; } int image_remove(Image *i) { - _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; _cleanup_strv_free_ char **settings = NULL; _cleanup_free_ char *roothash = NULL; char **j; @@ -549,7 +703,7 @@ static int rename_auxiliary_file(const char *path, const char *new_name, const c } int image_rename(Image *i, const char *new_name) { - _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT, name_lock = LOCK_FILE_INIT; _cleanup_free_ char *new_path = NULL, *nn = NULL, *roothash = NULL; _cleanup_strv_free_ char **settings = NULL; unsigned file_attr = 0; @@ -584,11 +738,11 @@ int image_rename(Image *i, const char *new_name) { if (r < 0) return r; - r = image_find(new_name, NULL); - if (r < 0) - return r; - if (r > 0) + r = image_find(IMAGE_MACHINE, new_name, NULL); + if (r >= 0) return -EEXIST; + if (r != -ENOENT) + return r; switch (i->type) { @@ -670,7 +824,7 @@ static int clone_auxiliary_file(const char *path, const char *new_name, const ch } int image_clone(Image *i, const char *new_name, bool read_only) { - _cleanup_release_lock_file_ LockFile name_lock = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile name_lock = LOCK_FILE_INIT; _cleanup_strv_free_ char **settings = NULL; _cleanup_free_ char *roothash = NULL; const char *new_path; @@ -697,11 +851,11 @@ int image_clone(Image *i, const char *new_name, bool read_only) { if (r < 0) return r; - r = image_find(new_name, NULL); - if (r < 0) - return r; - if (r > 0) + r = image_find(IMAGE_MACHINE, new_name, NULL); + if (r >= 0) return -EEXIST; + if (r != -ENOENT) + return r; switch (i->type) { @@ -753,7 +907,7 @@ int image_clone(Image *i, const char *new_name, bool read_only) { } int image_read_only(Image *i, bool b) { - _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; int r; assert(i); @@ -881,8 +1035,12 @@ int image_path_lock(const char *path, int operation, LockFile *global, LockFile * block devices are device local anyway. */ if (!path_startswith(path, "/dev")) { r = make_lock_file_for(path, operation, &t); - if (r < 0) - return r; + if (r < 0) { + if ((operation & LOCK_SH) && r == -EROFS) + log_debug_errno(r, "Failed to create shared lock for '%s', ignoring: %m", path); + else + return r; + } } if (p) { @@ -920,7 +1078,7 @@ int image_set_limit(Image *i, uint64_t referenced_max) { } int image_read_metadata(Image *i) { - _cleanup_release_lock_file_ LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile global_lock = LOCK_FILE_INIT, local_lock = LOCK_FILE_INIT; int r; assert(i); @@ -938,7 +1096,7 @@ int image_read_metadata(Image *i) { _cleanup_free_ char *hostname = NULL; _cleanup_free_ char *path = NULL; - r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT, &path); + r = chase_symlinks("/etc/hostname", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/hostname in image %s: %m", i->name); else if (r >= 0) { @@ -949,7 +1107,7 @@ int image_read_metadata(Image *i) { path = mfree(path); - r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT, &path); + r = chase_symlinks("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name); else if (r >= 0) { @@ -967,7 +1125,7 @@ int image_read_metadata(Image *i) { path = mfree(path); - r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT, &path); + r = chase_symlinks("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path); if (r < 0 && r != -ENOENT) log_debug_errno(r, "Failed to chase /etc/machine-info in image %s: %m", i->name); else if (r >= 0) { @@ -976,18 +1134,9 @@ int image_read_metadata(Image *i) { log_debug_errno(r, "Failed to parse machine-info data of %s: %m", i->name); } - path = mfree(path); - - r = chase_symlinks("/etc/os-release", i->path, CHASE_PREFIX_ROOT, &path); - if (r == -ENOENT) - r = chase_symlinks("/usr/lib/os-release", i->path, CHASE_PREFIX_ROOT, &path); - if (r < 0 && r != -ENOENT) - log_debug_errno(r, "Failed to chase os-release in image: %m"); - else if (r >= 0) { - r = load_env_file_pairs(NULL, path, NULL, &os_release); - if (r < 0) - log_debug_errno(r, "Failed to parse os-release data of %s: %m", i->name); - } + r = load_os_release_pairs(i->path, &os_release); + if (r < 0) + log_debug_errno(r, "Failed to read os-release in image, ignoring: %m"); free_and_replace(i->hostname, hostname); i->machine_id = machine_id; @@ -1073,6 +1222,35 @@ bool image_name_is_valid(const char *s) { return true; } +bool image_in_search_path(ImageClass class, const char *image) { + const char *path; + + assert(image); + + NULSTR_FOREACH(path, image_search_path[class]) { + const char *p; + size_t k; + + p = path_startswith(image, path); + if (!p) + continue; + + /* Make sure there's a filename following */ + k = strcspn(p, "/"); + if (k == 0) + continue; + + p += k; + + /* Accept trailing slashes */ + if (p[strspn(p, "/")] == 0) + return true; + + } + + return false; +} + static const char* const image_type_table[_IMAGE_TYPE_MAX] = { [IMAGE_DIRECTORY] = "directory", [IMAGE_SUBVOLUME] = "subvolume", diff --git a/src/shared/machine-image.h b/src/shared/machine-image.h index 3df9a29a24..2e38522acd 100644 --- a/src/shared/machine-image.h +++ b/src/shared/machine-image.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <stdint.h> @@ -30,6 +11,13 @@ #include "string-util.h" #include "time-util.h" +typedef enum ImageClass { + IMAGE_MACHINE, + IMAGE_PORTABLE, + _IMAGE_CLASS_MAX, + _IMAGE_CLASS_INVALID = -1 +} ImageClass; + typedef enum ImageType { IMAGE_DIRECTORY, IMAGE_SUBVOLUME, @@ -40,6 +28,8 @@ typedef enum ImageType { } ImageType; typedef struct Image { + unsigned n_ref; + ImageType type; char *name; char *path; @@ -58,12 +48,15 @@ typedef struct Image { char **machine_info; char **os_release; - bool metadata_valid; + bool metadata_valid:1; + bool discoverable:1; /* true if we know for sure that image_find() would find the image given just the short name */ void *userdata; } Image; Image *image_unref(Image *i); +Image *image_ref(Image *i); + static inline Hashmap* image_hashmap_free(Hashmap *map) { return hashmap_free_with_destructor(map, image_unref); } @@ -71,8 +64,10 @@ static inline Hashmap* image_hashmap_free(Hashmap *map) { DEFINE_TRIVIAL_CLEANUP_FUNC(Image*, image_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, image_hashmap_free); -int image_find(const char *name, Image **ret); -int image_discover(Hashmap *map); +int image_find(ImageClass class, const char *name, Image **ret); +int image_from_path(const char *path, Image **ret); +int image_find_harder(ImageClass class, const char *name_or_path, Image **ret); +int image_discover(ImageClass class, Hashmap *map); int image_remove(Image *i); int image_rename(Image *i, const char *new_name); @@ -91,6 +86,8 @@ int image_set_limit(Image *i, uint64_t referenced_max); int image_read_metadata(Image *i); +bool image_in_search_path(ImageClass class, const char *image); + static inline bool IMAGE_IS_HIDDEN(const struct Image *i) { assert(i); diff --git a/src/shared/machine-pool.c b/src/shared/machine-pool.c index 031d443e9e..53c5609f9b 100644 --- a/src/shared/machine-pool.c +++ b/src/shared/machine-pool.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2015 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> @@ -89,11 +71,8 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) { * /var/lib/machines. */ fd = open("/var/lib/machines.raw", O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (fd >= 0) { - r = fd; - fd = -1; - return r; - } + if (fd >= 0) + return TAKE_FD(fd); if (errno != ENOENT) return sd_bus_error_set_errnof(error, errno, "Failed to open /var/lib/machines.raw: %m"); @@ -162,10 +141,7 @@ static int setup_machine_raw(uint64_t size, sd_bus_error *error) { goto fail; } - r = fd; - fd = -1; - - return r; + return TAKE_FD(fd); fail: unlink_noerrno(tmp); @@ -177,7 +153,7 @@ fail: } int setup_machine_directory(uint64_t size, sd_bus_error *error) { - _cleanup_release_lock_file_ LockFile lock_file = LOCK_FILE_INIT; + _cleanup_(release_lock_file) LockFile lock_file = LOCK_FILE_INIT; struct loop_info64 info = { .lo_flags = LO_FLAGS_AUTOCLEAR, }; diff --git a/src/shared/machine-pool.h b/src/shared/machine-pool.h index 6e390521e8..fd09296f23 100644 --- a/src/shared/machine-pool.h +++ b/src/shared/machine-pool.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2015 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 <stdint.h> #include "sd-bus.h" diff --git a/src/shared/meson.build b/src/shared/meson.build index 91fecf896c..54e77e9af6 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -1,21 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1+ -# -# Copyright 2017 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/>. -shared_sources = ''' +shared_sources = files(''' acl-util.h acpi-fpdt.c acpi-fpdt.h @@ -82,8 +67,6 @@ shared_sources = ''' nsflags.h output-mode.c output-mode.h - pager.c - pager.h path-lookup.c path-lookup.h ptyfwd.c @@ -119,25 +102,25 @@ shared_sources = ''' watchdog.c watchdog.h wireguard-netlink.h -'''.split() +'''.split()) test_tables_h = files('test-tables.h') shared_sources += [test_tables_h] if conf.get('HAVE_ACL') == 1 - shared_sources += ['acl-util.c'] + shared_sources += files('acl-util.c') endif if conf.get('ENABLE_UTMP') == 1 - shared_sources += ['utmp-wtmp.c'] + shared_sources += files('utmp-wtmp.c') endif if conf.get('HAVE_SECCOMP') == 1 - shared_sources += ['seccomp-util.c'] + shared_sources += files('seccomp-util.c') endif if conf.get('HAVE_LIBIPTC') == 1 - shared_sources += ['firewall-util.c'] + shared_sources += files('firewall-util.c') endif libshared_name = 'systemd-shared-@0@'.format(meson.project_version()) diff --git a/src/shared/nsflags.c b/src/shared/nsflags.c index 05ec9feb8d..a5beb9200f 100644 --- a/src/shared/nsflags.c +++ b/src/shared/nsflags.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 <sched.h> @@ -38,32 +20,7 @@ const struct namespace_flag_map namespace_flag_map[] = { {} }; -const char* namespace_flag_to_string(unsigned long flag) { - unsigned i; - - flag &= NAMESPACE_FLAGS_ALL; - - for (i = 0; namespace_flag_map[i].name; i++) - if (flag == namespace_flag_map[i].flag) - return namespace_flag_map[i].name; - - return NULL; /* either unknown namespace flag, or a combination of many. This call supports neither. */ -} - -unsigned long namespace_flag_from_string(const char *name) { - unsigned i; - - if (isempty(name)) - return 0; - - for (i = 0; namespace_flag_map[i].name; i++) - if (streq(name, namespace_flag_map[i].name)) - return namespace_flag_map[i].flag; - - return 0; -} - -int namespace_flag_from_string_many(const char *name, unsigned long *ret) { +int namespace_flags_from_string(const char *name, unsigned long *ret) { unsigned long flags = 0; int r; @@ -71,7 +28,8 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) { for (;;) { _cleanup_free_ char *word = NULL; - unsigned long f; + unsigned long f = 0; + unsigned i; r = extract_first_word(&name, &word, NULL, 0); if (r < 0) @@ -79,7 +37,12 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) { if (r == 0) break; - f = namespace_flag_from_string(word); + for (i = 0; namespace_flag_map[i].name; i++) + if (streq(word, namespace_flag_map[i].name)) { + f = namespace_flag_map[i].flag; + break; + } + if (f == 0) return -EINVAL; @@ -90,7 +53,7 @@ int namespace_flag_from_string_many(const char *name, unsigned long *ret) { return 0; } -int namespace_flag_to_string_many(unsigned long flags, char **ret) { +int namespace_flags_to_string(unsigned long flags, char **ret) { _cleanup_free_ char *s = NULL; unsigned i; @@ -98,14 +61,8 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) { if ((flags & namespace_flag_map[i].flag) != namespace_flag_map[i].flag) continue; - if (!s) { - s = strdup(namespace_flag_map[i].name); - if (!s) - return -ENOMEM; - } else { - if (!strextend(&s, " ", namespace_flag_map[i].name, NULL)) - return -ENOMEM; - } + if (!strextend_with_separator(&s, " ", namespace_flag_map[i].name, NULL)) + return -ENOMEM; } if (!s) { @@ -114,8 +71,7 @@ int namespace_flag_to_string_many(unsigned long flags, char **ret) { return -ENOMEM; } - *ret = s; - s = NULL; + *ret = TAKE_PTR(s); return 0; } diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h index 51bc590621..7cc26a441d 100644 --- a/src/shared/nsflags.h +++ b/src/shared/nsflags.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 <sched.h> #include "missing.h" @@ -37,17 +18,10 @@ CLONE_NEWUSER| \ CLONE_NEWUTS)) -const char* namespace_flag_to_string(unsigned long flag); -unsigned long namespace_flag_from_string(const char *name); -int namespace_flag_from_string_many(const char *name, unsigned long *ret); -int namespace_flag_to_string_many(unsigned long flags, char **ret); - -static inline int namespace_flag_to_string_many_with_check(unsigned long n, char **s) { - if ((n & NAMESPACE_FLAGS_ALL) != n) - return -EINVAL; +#define NAMESPACE_FLAGS_INITIAL ((unsigned long) -1) - return namespace_flag_to_string_many(n, s); -} +int namespace_flags_from_string(const char *name, unsigned long *ret); +int namespace_flags_to_string(unsigned long flags, char **ret); struct namespace_flag_map { unsigned long flag; diff --git a/src/shared/output-mode.c b/src/shared/output-mode.c index 5256e917a3..bb33ba3d10 100644 --- a/src/shared/output-mode.c +++ b/src/shared/output-mode.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2012 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 "output-mode.h" #include "string-table.h" @@ -34,7 +16,8 @@ static const char *const output_mode_table[_OUTPUT_MODE_MAX] = { [OUTPUT_JSON] = "json", [OUTPUT_JSON_PRETTY] = "json-pretty", [OUTPUT_JSON_SSE] = "json-sse", - [OUTPUT_CAT] = "cat" + [OUTPUT_CAT] = "cat", + [OUTPUT_WITH_UNIT] = "with-unit", }; DEFINE_STRING_TABLE_LOOKUP(output_mode, OutputMode); diff --git a/src/shared/output-mode.h b/src/shared/output-mode.h index 747f7eb1b9..fe3903b3c5 100644 --- a/src/shared/output-mode.h +++ b/src/shared/output-mode.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 "macro.h" typedef enum OutputMode { @@ -36,6 +17,7 @@ typedef enum OutputMode { OUTPUT_JSON_PRETTY, OUTPUT_JSON_SSE, OUTPUT_CAT, + OUTPUT_WITH_UNIT, _OUTPUT_MODE_MAX, _OUTPUT_MODE_INVALID = -1 } OutputMode; diff --git a/src/shared/pager.c b/src/shared/pager.c deleted file mode 100644 index 75db3c985b..0000000000 --- a/src/shared/pager.c +++ /dev/null @@ -1,224 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <signal.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/prctl.h> -#include <unistd.h> - -#include "copy.h" -#include "fd-util.h" -#include "locale-util.h" -#include "log.h" -#include "macro.h" -#include "pager.h" -#include "process-util.h" -#include "signal-util.h" -#include "string-util.h" -#include "strv.h" -#include "terminal-util.h" - -static pid_t pager_pid = 0; - -static int stored_stdout = -1; -static int stored_stderr = -1; -static bool stdout_redirected = false; -static bool stderr_redirected = false; - -noreturn static void pager_fallback(void) { - int r; - - r = copy_bytes(STDIN_FILENO, STDOUT_FILENO, (uint64_t) -1, 0); - if (r < 0) { - log_error_errno(r, "Internal pager failed: %m"); - _exit(EXIT_FAILURE); - } - - _exit(EXIT_SUCCESS); -} - -int pager_open(bool no_pager, bool jump_to_end) { - _cleanup_close_pair_ int fd[2] = { -1, -1 }; - const char *pager; - int r; - - if (no_pager) - return 0; - - if (pager_pid > 0) - return 1; - - if (terminal_is_dumb()) - return 0; - - if (!is_main_thread()) - return -EPERM; - - pager = getenv("SYSTEMD_PAGER"); - if (!pager) - pager = getenv("PAGER"); - - /* If the pager is explicitly turned off, honour it */ - if (pager && STR_IN_SET(pager, "", "cat")) - return 0; - - /* Determine and cache number of columns/lines before we spawn the pager so that we get the value from the - * actual tty */ - (void) columns(); - (void) lines(); - - if (pipe2(fd, O_CLOEXEC) < 0) - return log_error_errno(errno, "Failed to create pager pipe: %m"); - - r = safe_fork("(pager)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pager_pid); - if (r < 0) - return r; - if (r == 0) { - const char* less_opts, *less_charset; - - /* In the child start the pager */ - - (void) dup2(fd[0], STDIN_FILENO); - safe_close_pair(fd); - - /* Initialize a good set of less options */ - less_opts = getenv("SYSTEMD_LESS"); - if (!less_opts) - less_opts = "FRSXMK"; - if (jump_to_end) - less_opts = strjoina(less_opts, " +G"); - if (setenv("LESS", less_opts, 1) < 0) - _exit(EXIT_FAILURE); - - /* Initialize a good charset for less. This is - * particularly important if we output UTF-8 - * characters. */ - less_charset = getenv("SYSTEMD_LESSCHARSET"); - if (!less_charset && is_locale_utf8()) - less_charset = "utf-8"; - if (less_charset && - setenv("LESSCHARSET", less_charset, 1) < 0) - _exit(EXIT_FAILURE); - - if (pager) { - execlp(pager, pager, NULL); - execl("/bin/sh", "sh", "-c", pager, NULL); - } - - /* Debian's alternatives command for pagers is - * called 'pager'. Note that we do not call - * sensible-pagers here, since that is just a - * shell script that implements a logic that - * is similar to this one anyway, but is - * Debian-specific. */ - execlp("pager", "pager", NULL); - - execlp("less", "less", NULL); - execlp("more", "more", NULL); - - pager_fallback(); - /* not reached */ - } - - /* Return in the parent */ - stored_stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 3); - if (dup2(fd[1], STDOUT_FILENO) < 0) { - stored_stdout = safe_close(stored_stdout); - return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); - } - stdout_redirected = true; - - stored_stderr = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 3); - if (dup2(fd[1], STDERR_FILENO) < 0) { - stored_stderr = safe_close(stored_stderr); - return log_error_errno(errno, "Failed to duplicate pager pipe: %m"); - } - stderr_redirected = true; - - return 1; -} - -void pager_close(void) { - - if (pager_pid <= 0) - return; - - /* Inform pager that we are done */ - (void) fflush(stdout); - if (stdout_redirected) - if (stored_stdout < 0 || dup2(stored_stdout, STDOUT_FILENO) < 0) - (void) close(STDOUT_FILENO); - stored_stdout = safe_close(stored_stdout); - (void) fflush(stderr); - if (stderr_redirected) - if (stored_stderr < 0 || dup2(stored_stderr, STDERR_FILENO) < 0) - (void) close(STDERR_FILENO); - stored_stderr = safe_close(stored_stderr); - stdout_redirected = stderr_redirected = false; - - (void) kill(pager_pid, SIGCONT); - (void) wait_for_terminate(pager_pid, NULL); - pager_pid = 0; -} - -bool pager_have(void) { - return pager_pid > 0; -} - -int show_man_page(const char *desc, bool null_stdio) { - const char *args[4] = { "man", NULL, NULL, NULL }; - char *e = NULL; - pid_t pid; - size_t k; - int r; - - k = strlen(desc); - - if (desc[k-1] == ')') - e = strrchr(desc, '('); - - if (e) { - char *page = NULL, *section = NULL; - - page = strndupa(desc, e - desc); - section = strndupa(e + 1, desc + k - e - 2); - - args[1] = section; - args[2] = page; - } else - args[1] = desc; - - r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_LOG, &pid); - if (r < 0) - return r; - if (r == 0) { - /* Child */ - execvp(args[0], (char**) args); - log_error_errno(errno, "Failed to execute man: %m"); - _exit(EXIT_FAILURE); - } - - return wait_for_terminate_and_check(NULL, pid, 0); -} diff --git a/src/shared/pager.h b/src/shared/pager.h deleted file mode 100644 index 99716f8747..0000000000 --- a/src/shared/pager.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#pragma once - -/*** - 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 <stdbool.h> - -#include "macro.h" - -int pager_open(bool no_pager, bool jump_to_end); -void pager_close(void); -bool pager_have(void) _pure_; - -int show_man_page(const char *page, bool null_stdio); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 5f31831c99..42a5b62d5d 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <stdio.h> @@ -181,7 +163,6 @@ static char** user_dirs( _cleanup_strv_free_ char **config_dirs = NULL, **data_dirs = NULL; _cleanup_free_ char *data_home = NULL; _cleanup_strv_free_ char **res = NULL; - char **tmp; int r; r = xdg_user_dirs(&config_dirs, &data_dirs); @@ -242,10 +223,7 @@ static char** user_dirs( if (path_strv_make_absolute_cwd(res) < 0) return NULL; - tmp = res; - res = NULL; - - return tmp; + return TAKE_PTR(res); } bool path_is_user_data_dir(const char *path) { @@ -280,11 +258,10 @@ static int acquire_generator_dirs( if (tempdir) prefix = tempdir; - else if (scope == UNIT_FILE_SYSTEM) prefix = "/run/systemd"; - - else if (scope == UNIT_FILE_USER) { + else { + /* UNIT_FILE_USER */ const char *e; e = getenv("XDG_RUNTIME_DIR"); @@ -306,11 +283,10 @@ static int acquire_generator_dirs( if (!z) return -ENOMEM; - *generator = x; - *generator_early = y; - *generator_late = z; + *generator = TAKE_PTR(x); + *generator_early = TAKE_PTR(y); + *generator_late = TAKE_PTR(z); - x = y = z = NULL; return 0; } @@ -374,8 +350,7 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru *runtime = NULL; } - *persistent = a; - a = NULL; + *persistent = TAKE_PTR(a); return 0; @@ -386,9 +361,8 @@ static int acquire_config_dirs(UnitFileScope scope, char **persistent, char **ru if (!a || !b) return -ENOMEM; - *persistent = a; - *runtime = b; - a = b = NULL; + *persistent = TAKE_PTR(a); + *runtime = TAKE_PTR(b); return 0; } @@ -413,8 +387,7 @@ static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **r if (!b) return -ENOMEM; - *runtime = b; - b = NULL; + *runtime = TAKE_PTR(b); break; } @@ -443,8 +416,7 @@ static int acquire_control_dirs(UnitFileScope scope, char **persistent, char **r assert_not_reached("Hmm, unexpected scope value."); } - *persistent = a; - a = NULL; + *persistent = TAKE_PTR(a); return 0; } @@ -506,7 +478,11 @@ int lookup_paths_init( assert(scope >= 0); assert(scope < _UNIT_FILE_SCOPE_MAX); - if (!isempty(root_dir) && !path_equal(root_dir, "/")) { +#if HAVE_SPLIT_USR + flags |= LOOKUP_PATHS_SPLIT_USR; +#endif + + if (!empty_or_root(root_dir)) { if (scope == UNIT_FILE_USER) return -EINVAL; @@ -604,9 +580,7 @@ int lookup_paths_init( "/usr/local/lib/systemd/system", SYSTEM_DATA_UNIT_PATH, "/usr/lib/systemd/system", -#if HAVE_SPLIT_USR - "/lib/systemd/system", -#endif + STRV_IFNOTNULL(flags & LOOKUP_PATHS_SPLIT_USR ? "/lib/systemd/system" : NULL), STRV_IFNOTNULL(generator_late), NULL); break; @@ -654,12 +628,10 @@ int lookup_paths_init( r = strv_extend_strv(&paths, add, true); if (r < 0) return r; - } else { + } else /* Small optimization: if paths is NULL (and it usually is), we can simply assign 'add' to it, * and don't have to copy anything */ - paths = add; - add = NULL; - } + paths = TAKE_PTR(add); } r = patch_root_prefix(&persistent_config, root); @@ -698,27 +670,20 @@ int lookup_paths_init( p->search_path = strv_uniq(paths); paths = NULL; - p->persistent_config = persistent_config; - p->runtime_config = runtime_config; - persistent_config = runtime_config = NULL; + p->persistent_config = TAKE_PTR(persistent_config); + p->runtime_config = TAKE_PTR(runtime_config); - p->generator = generator; - p->generator_early = generator_early; - p->generator_late = generator_late; - generator = generator_early = generator_late = NULL; + p->generator = TAKE_PTR(generator); + p->generator_early = TAKE_PTR(generator_early); + p->generator_late = TAKE_PTR(generator_late); - p->transient = transient; - transient = NULL; + p->transient = TAKE_PTR(transient); - p->persistent_control = persistent_control; - p->runtime_control = runtime_control; - persistent_control = runtime_control = NULL; + p->persistent_control = TAKE_PTR(persistent_control); + p->runtime_control = TAKE_PTR(runtime_control); - p->root_dir = root; - root = NULL; - - p->temporary_dir = tempdir; - tempdir = NULL; + p->root_dir = TAKE_PTR(root); + p->temporary_dir = TAKE_PTR(tempdir); return 0; } @@ -748,22 +713,20 @@ void lookup_paths_free(LookupPaths *p) { int lookup_paths_reduce(LookupPaths *p) { _cleanup_free_ struct stat *stats = NULL; size_t n_stats = 0, allocated = 0; - unsigned c = 0; + size_t c = 0; int r; assert(p); /* Drop duplicates and non-existing directories from the search path. We figure out whether two directories are - * the same by comparing their device and inode numbers. Note one special tweak: when we have a root path set, - * we do not follow symlinks when retrieving them, because the kernel wouldn't take the root prefix into - * account when following symlinks. When we have no root path set this restriction does not apply however. */ + * the same by comparing their device and inode numbers. */ if (!p->search_path) return 0; while (p->search_path[c]) { struct stat st; - unsigned k; + size_t k; /* Never strip the transient and control directories from the path */ if (path_equal_ptr(p->search_path[c], p->transient) || @@ -773,25 +736,20 @@ int lookup_paths_reduce(LookupPaths *p) { continue; } - if (p->root_dir) - r = lstat(p->search_path[c], &st); - else - r = stat(p->search_path[c], &st); + r = chase_symlinks_and_stat(p->search_path[c], p->root_dir, 0, NULL, &st); + if (r == -ENOENT) + goto remove_item; if (r < 0) { - if (errno == ENOENT) - goto remove_item; - /* If something we don't grok happened, let's better leave it in. */ - log_debug_errno(errno, "Failed to stat %s: %m", p->search_path[c]); + log_debug_errno(r, "Failed to chase and stat %s: %m", p->search_path[c]); c++; continue; } - for (k = 0; k < n_stats; k++) { + for (k = 0; k < n_stats; k++) if (stats[k].st_dev == st.st_dev && stats[k].st_ino == st.st_ino) break; - } if (k < n_stats) /* Is there already an entry with the same device/inode? */ goto remove_item; @@ -866,14 +824,14 @@ void lookup_paths_flush_generator(LookupPaths *p) { /* Flush the generated unit files in full */ if (p->generator) - (void) rm_rf(p->generator, REMOVE_ROOT); + (void) rm_rf(p->generator, REMOVE_ROOT|REMOVE_PHYSICAL); if (p->generator_early) - (void) rm_rf(p->generator_early, REMOVE_ROOT); + (void) rm_rf(p->generator_early, REMOVE_ROOT|REMOVE_PHYSICAL); if (p->generator_late) - (void) rm_rf(p->generator_late, REMOVE_ROOT); + (void) rm_rf(p->generator_late, REMOVE_ROOT|REMOVE_PHYSICAL); if (p->temporary_dir) - (void) rm_rf(p->temporary_dir, REMOVE_ROOT); + (void) rm_rf(p->temporary_dir, REMOVE_ROOT|REMOVE_PHYSICAL); } char **generator_binary_paths(UnitFileScope scope) { diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index 42a870aa3e..963e09db67 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> typedef struct LookupPaths LookupPaths; @@ -30,6 +11,7 @@ typedef struct LookupPaths LookupPaths; typedef enum LookupPathsFlags { LOOKUP_PATHS_EXCLUDE_GENERATED = 1 << 0, LOOKUP_PATHS_TEMPORARY_GENERATED = 1 << 1, + LOOKUP_PATHS_SPLIT_USR = 1 << 2, } LookupPathsFlags; struct LookupPaths { @@ -82,6 +64,5 @@ void lookup_paths_trim_generator(LookupPaths *p); void lookup_paths_flush_generator(LookupPaths *p); void lookup_paths_free(LookupPaths *p); -#define _cleanup_lookup_paths_free_ _cleanup_(lookup_paths_free) char **generator_binary_paths(UnitFileScope scope); diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 94a4dd513f..c38ec81bbc 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2010-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 <errno.h> #include <limits.h> @@ -495,8 +477,7 @@ int pty_forward_new( (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); - *ret = f; - f = NULL; + *ret = TAKE_PTR(f); return 0; } diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index 6a0e0c6a2b..e4a083ac24 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2010-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 <stdbool.h> #include "sd-event.h" diff --git a/src/shared/resolve-util.c b/src/shared/resolve-util.c index edcb8e05e7..a5d4a14344 100644 --- a/src/shared/resolve-util.c +++ b/src/shared/resolve-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 "conf-parser.h" #include "resolve-util.h" @@ -24,6 +6,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_resolve_support, resolve_support, ResolveSupport, "Failed to parse resolve support setting"); DEFINE_CONFIG_PARSE_ENUM(config_parse_dnssec_mode, dnssec_mode, DnssecMode, "Failed to parse DNSSEC mode setting"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_over_tls_mode, dns_over_tls_mode, DnsOverTlsMode, "Failed to parse DNS-over-TLS mode setting"); static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = { [RESOLVE_SUPPORT_NO] = "no", @@ -38,3 +21,9 @@ static const char* const dnssec_mode_table[_DNSSEC_MODE_MAX] = { [DNSSEC_YES] = "yes", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dnssec_mode, DnssecMode, DNSSEC_YES); + +static const char* const dns_over_tls_mode_table[_DNS_OVER_TLS_MODE_MAX] = { + [DNS_OVER_TLS_NO] = "no", + [DNS_OVER_TLS_OPPORTUNISTIC] = "opportunistic", +}; +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_over_tls_mode, DnsOverTlsMode, _DNS_OVER_TLS_MODE_INVALID); diff --git a/src/shared/resolve-util.h b/src/shared/resolve-util.h index 975156ca96..5883342e65 100644 --- a/src/shared/resolve-util.h +++ b/src/shared/resolve-util.h @@ -1,29 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 "conf-parser.h" #include "macro.h" typedef enum ResolveSupport ResolveSupport; typedef enum DnssecMode DnssecMode; +typedef enum DnsOverTlsMode DnsOverTlsMode; enum ResolveSupport { RESOLVE_SUPPORT_NO, @@ -51,11 +34,27 @@ enum DnssecMode { _DNSSEC_MODE_INVALID = -1 }; -int config_parse_resolve_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_dnssec_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +enum DnsOverTlsMode { + /* No connection is made for DNS-over-TLS */ + DNS_OVER_TLS_NO, + + /* Try to connect using DNS-over-TLS, but if connection fails, + * fallback to using an unencrypted connection */ + DNS_OVER_TLS_OPPORTUNISTIC, + + _DNS_OVER_TLS_MODE_MAX, + _DNS_OVER_TLS_MODE_INVALID = -1 +}; + +CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support); +CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_mode); +CONFIG_PARSER_PROTOTYPE(config_parse_dns_over_tls_mode); const char* resolve_support_to_string(ResolveSupport p) _const_; ResolveSupport resolve_support_from_string(const char *s) _pure_; const char* dnssec_mode_to_string(DnssecMode p) _const_; DnssecMode dnssec_mode_from_string(const char *s) _pure_; + +const char* dns_over_tls_mode_to_string(DnsOverTlsMode p) _const_; +DnsOverTlsMode dns_over_tls_mode_from_string(const char *s) _pure_; diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c index 220658b3ad..c433cb90dc 100644 --- a/src/shared/seccomp-util.c +++ b/src/shared/seccomp-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <errno.h> #include <linux/seccomp.h> @@ -650,7 +632,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "setresuid32\0" "setreuid\0" "setreuid32\0" - "setuid\0" + "setuid\0" /* We list the explicit system calls here, as @setuid also includes setgid() which is not necessarily privileged */ "setuid32\0" "vhangup\0" }, @@ -774,6 +756,75 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { "sync_file_range\0" "syncfs\0" }, + [SYSCALL_FILTER_SET_SYSTEM_SERVICE] = { + .name = "@system-service", + .help = "General system service operations", + .value = + "@aio\0" + "@basic-io\0" + "@chown\0" + "@default\0" + "@file-system\0" + "@io-event\0" + "@ipc\0" + "@keyring\0" + "@memlock\0" + "@network-io\0" + "@process\0" + "@resources\0" + "@setuid\0" + "@signal\0" + "@sync\0" + "@timer\0" + "brk\0" + "capget\0" + "capset\0" + "copy_file_range\0" + "fadvise64\0" + "fadvise64_64\0" + "flock\0" + "get_mempolicy\0" + "getcpu\0" + "getpriority\0" + "getrandom\0" + "ioctl\0" + "ioprio_get\0" + "kcmp\0" + "madvise\0" + "mincore\0" + "mprotect\0" + "mremap\0" + "name_to_handle_at\0" + "oldolduname\0" + "olduname\0" + "personality\0" + "readahead\0" + "readdir\0" + "remap_file_pages\0" + "sched_get_priority_max\0" + "sched_get_priority_min\0" + "sched_getaffinity\0" + "sched_getattr\0" + "sched_getparam\0" + "sched_getscheduler\0" + "sched_rr_get_interval\0" + "sched_yield\0" + "sendfile\0" + "sendfile64\0" + "setfsgid\0" + "setfsgid32\0" + "setfsuid\0" + "setfsuid32\0" + "setpgid\0" + "setsid\0" + "splice\0" + "sysinfo\0" + "tee\0" + "umask\0" + "uname\0" + "userfaultfd\0" + "vmsplice\0" + }, [SYSCALL_FILTER_SET_TIMER] = { .name = "@timer", .help = "Schedule operations by time", @@ -1020,7 +1071,7 @@ int seccomp_restrict_namespaces(unsigned long retain) { if (DEBUG_LOGGING) { _cleanup_free_ char *s = NULL; - (void) namespace_flag_to_string_many(retain, &s); + (void) namespace_flags_to_string(retain, &s); log_debug("Restricting namespace to: %s.", strna(s)); } @@ -1182,16 +1233,22 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) { case SCMP_ARCH_X32: case SCMP_ARCH_ARM: case SCMP_ARCH_AARCH64: + case SCMP_ARCH_PPC: case SCMP_ARCH_PPC64: case SCMP_ARCH_PPC64LE: + case SCMP_ARCH_MIPSEL64N32: + case SCMP_ARCH_MIPS64N32: + case SCMP_ARCH_MIPSEL64: + case SCMP_ARCH_MIPS64: /* These we know we support (i.e. are the ones that do not use socketcall()) */ supported = true; break; case SCMP_ARCH_S390: case SCMP_ARCH_S390X: - case SCMP_ARCH_PPC: case SCMP_ARCH_X86: + case SCMP_ARCH_MIPSEL: + case SCMP_ARCH_MIPS: default: /* These we either know we don't support (i.e. are the ones that do use socketcall()), or we * don't know */ @@ -1607,8 +1664,7 @@ int parse_syscall_archs(char **l, Set **archs) { return -ENOMEM; } - *archs = _archs; - _archs = NULL; + *archs = TAKE_PTR(_archs); return 0; } diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h index 5915ceb9a3..eac857afb9 100644 --- a/src/shared/seccomp-util.h +++ b/src/shared/seccomp-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <seccomp.h> #include <stdbool.h> #include <stdint.h> @@ -66,6 +47,7 @@ enum { SYSCALL_FILTER_SET_SIGNAL, SYSCALL_FILTER_SET_SWAP, SYSCALL_FILTER_SET_SYNC, + SYSCALL_FILTER_SET_SYSTEM_SERVICE, SYSCALL_FILTER_SET_TIMER, _SYSCALL_FILTER_SET_MAX }; @@ -82,10 +64,10 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action); typedef enum SeccompParseFlags { - SECCOMP_PARSE_INVERT = 1U << 0, - SECCOMP_PARSE_WHITELIST = 1U << 1, - SECCOMP_PARSE_LOG = 1U << 2, - SECCOMP_PARSE_PERMISSIVE = 1U << 3, + SECCOMP_PARSE_INVERT = 1 << 0, + SECCOMP_PARSE_WHITELIST = 1 << 1, + SECCOMP_PARSE_LOG = 1 << 2, + SECCOMP_PARSE_PERMISSIVE = 1 << 3, } SeccompParseFlags; int seccomp_parse_syscall_filter_full( diff --git a/src/shared/sleep-config.c b/src/shared/sleep-config.c index ecac98e0ab..9e4ce183d3 100644 --- a/src/shared/sleep-config.c +++ b/src/shared/sleep-config.c @@ -1,24 +1,10 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** - This file is part of systemd. - - 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/>. + Copyright © 2018 Dell Inc. ***/ #include <errno.h> +#include <linux/fs.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> @@ -39,15 +25,14 @@ #include "string-util.h" #include "strv.h" -#define USE(x, y) do { (x) = (y); (y) = NULL; } while (0) - -int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { +int parse_sleep_config(const char *verb, char ***_modes, char ***_states, usec_t *_delay) { _cleanup_strv_free_ char **suspend_mode = NULL, **suspend_state = NULL, **hibernate_mode = NULL, **hibernate_state = NULL, **hybrid_mode = NULL, **hybrid_state = NULL; - char **modes, **states; + _cleanup_strv_free_ char **modes, **states; /* always initialized below */ + usec_t delay = 180 * USEC_PER_MINUTE; const ConfigTableItem items[] = { { "Sleep", "SuspendMode", config_parse_strv, 0, &suspend_mode }, @@ -56,6 +41,7 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { { "Sleep", "HibernateState", config_parse_strv, 0, &hibernate_state }, { "Sleep", "HybridSleepMode", config_parse_strv, 0, &hybrid_mode }, { "Sleep", "HybridSleepState", config_parse_strv, 0, &hybrid_state }, + { "Sleep", "HibernateDelaySec", config_parse_sec, 0, &delay}, {} }; @@ -66,46 +52,51 @@ int parse_sleep_config(const char *verb, char ***_modes, char ***_states) { if (streq(verb, "suspend")) { /* empty by default */ - USE(modes, suspend_mode); + modes = TAKE_PTR(suspend_mode); if (suspend_state) - USE(states, suspend_state); + states = TAKE_PTR(suspend_state); else states = strv_new("mem", "standby", "freeze", NULL); } else if (streq(verb, "hibernate")) { if (hibernate_mode) - USE(modes, hibernate_mode); + modes = TAKE_PTR(hibernate_mode); else modes = strv_new("platform", "shutdown", NULL); if (hibernate_state) - USE(states, hibernate_state); + states = TAKE_PTR(hibernate_state); else states = strv_new("disk", NULL); } else if (streq(verb, "hybrid-sleep")) { if (hybrid_mode) - USE(modes, hybrid_mode); + modes = TAKE_PTR(hybrid_mode); else modes = strv_new("suspend", "platform", "shutdown", NULL); if (hybrid_state) - USE(states, hybrid_state); + states = TAKE_PTR(hybrid_state); else states = strv_new("disk", NULL); - } else + } else if (streq(verb, "suspend-then-hibernate")) + modes = states = NULL; + else assert_not_reached("what verb"); - if ((!modes && !streq(verb, "suspend")) || !states) { - strv_free(modes); - strv_free(states); + if ((!modes && STR_IN_SET(verb, "hibernate", "hybrid-sleep")) || + (!states && !streq(verb, "suspend-then-hibernate"))) return log_oom(); - } - *_modes = modes; - *_states = states; + if (_modes) + *_modes = TAKE_PTR(modes); + if (_states) + *_states = TAKE_PTR(states); + if (_delay) + *_delay = delay; + return 0; } @@ -176,13 +167,10 @@ int can_sleep_disk(char **types) { #define HIBERNATION_SWAP_THRESHOLD 0.98 -static int hibernation_partition_size(size_t *size, size_t *used) { +int find_hibernate_location(char **device, char **type, size_t *size, size_t *used) { _cleanup_fclose_ FILE *f; unsigned i; - assert(size); - assert(used); - f = fopen("/proc/swaps", "re"); if (!f) { log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, @@ -194,7 +182,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) { (void) fscanf(f, "%*s %*s %*s %*s %*s\n"); for (i = 1;; i++) { - _cleanup_free_ char *dev = NULL, *type = NULL; + _cleanup_free_ char *dev_field = NULL, *type_field = NULL; size_t size_field, used_field; int k; @@ -204,7 +192,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) { "%zu " /* swap size */ "%zu " /* used */ "%*i\n", /* priority */ - &dev, &type, &size_field, &used_field); + &dev_field, &type_field, &size_field, &used_field); if (k != 4) { if (k == EOF) break; @@ -213,13 +201,18 @@ static int hibernation_partition_size(size_t *size, size_t *used) { continue; } - if (streq(type, "partition") && endswith(dev, "\\040(deleted)")) { - log_warning("Ignoring deleted swapfile '%s'.", dev); + if (streq(type_field, "partition") && endswith(dev_field, "\\040(deleted)")) { + log_warning("Ignoring deleted swapfile '%s'.", dev_field); continue; } - - *size = size_field; - *used = used_field; + if (device) + *device = TAKE_PTR(dev_field); + if (type) + *type = TAKE_PTR(type_field); + if (size) + *size = size_field; + if (used) + *used = used_field; return 0; } @@ -227,7 +220,7 @@ static int hibernation_partition_size(size_t *size, size_t *used) { return -ENOSYS; } -static bool enough_memory_for_hibernation(void) { +static bool enough_swap_for_hibernation(void) { _cleanup_free_ char *active = NULL; unsigned long long act = 0; size_t size = 0, used = 0; @@ -236,7 +229,7 @@ static bool enough_memory_for_hibernation(void) { if (getenv_bool("SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK") > 0) return true; - r = hibernation_partition_size(&size, &used); + r = find_hibernate_location(NULL, NULL, &size, &used); if (r < 0) return false; @@ -260,20 +253,135 @@ static bool enough_memory_for_hibernation(void) { return r; } +int read_fiemap(int fd, struct fiemap **ret) { + _cleanup_free_ struct fiemap *fiemap = NULL, *result_fiemap = NULL; + struct stat statinfo; + uint32_t result_extents = 0; + uint64_t fiemap_start = 0, fiemap_length; + const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent)); + size_t fiemap_allocated = n_extra, result_fiemap_allocated = n_extra; + + if (fstat(fd, &statinfo) < 0) + return log_debug_errno(errno, "Cannot determine file size: %m"); + if (!S_ISREG(statinfo.st_mode)) + return -ENOTTY; + fiemap_length = statinfo.st_size; + + /* Zero this out in case we run on a file with no extents */ + fiemap = calloc(n_extra, sizeof(struct fiemap_extent)); + if (!fiemap) + return -ENOMEM; + + result_fiemap = malloc_multiply(n_extra, sizeof(struct fiemap_extent)); + if (!result_fiemap) + return -ENOMEM; + + /* XFS filesystem has incorrect implementation of fiemap ioctl and + * returns extents for only one block-group at a time, so we need + * to handle it manually, starting the next fiemap call from the end + * of the last extent + */ + while (fiemap_start < fiemap_length) { + *fiemap = (struct fiemap) { + .fm_start = fiemap_start, + .fm_length = fiemap_length, + .fm_flags = FIEMAP_FLAG_SYNC, + }; + + /* Find out how many extents there are */ + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) + return log_debug_errno(errno, "Failed to read extents: %m"); + + /* Nothing to process */ + if (fiemap->fm_mapped_extents == 0) + break; + + /* Resize fiemap to allow us to read in the extents, result fiemap has to hold all + * the extents for the whole file. Add space for the initial struct fiemap. */ + if (!greedy_realloc0((void**) &fiemap, &fiemap_allocated, + n_extra + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent))) + return -ENOMEM; + + fiemap->fm_extent_count = fiemap->fm_mapped_extents; + fiemap->fm_mapped_extents = 0; + + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) + return log_debug_errno(errno, "Failed to read extents: %m"); + + /* Resize result_fiemap to allow us to copy in the extents */ + if (!greedy_realloc((void**) &result_fiemap, &result_fiemap_allocated, + n_extra + result_extents + fiemap->fm_mapped_extents, sizeof(struct fiemap_extent))) + return -ENOMEM; + + memcpy(result_fiemap->fm_extents + result_extents, + fiemap->fm_extents, + sizeof(struct fiemap_extent) * fiemap->fm_mapped_extents); + + result_extents += fiemap->fm_mapped_extents; + + /* Highly unlikely that it is zero */ + if (_likely_(fiemap->fm_mapped_extents > 0)) { + uint32_t i = fiemap->fm_mapped_extents - 1; + + fiemap_start = fiemap->fm_extents[i].fe_logical + + fiemap->fm_extents[i].fe_length; + + if (fiemap->fm_extents[i].fe_flags & FIEMAP_EXTENT_LAST) + break; + } + } + + memcpy(result_fiemap, fiemap, sizeof(struct fiemap)); + result_fiemap->fm_mapped_extents = result_extents; + *ret = TAKE_PTR(result_fiemap); + return 0; +} + +static bool can_s2h(void) { + const char *p; + int r; + + r = access("/sys/class/rtc/rtc0/wakealarm", W_OK); + if (r < 0) { + log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, + "/sys/class/rct/rct0/wakealarm is not writable %m"); + return false; + } + + FOREACH_STRING(p, "suspend", "hibernate") { + r = can_sleep(p); + if (IN_SET(r, 0, -ENOSPC)) { + log_debug("Unable to %s system.", p); + return false; + } + if (r < 0) + return log_debug_errno(r, "Failed to check if %s is possible: %m", p); + } + + return true; +} + int can_sleep(const char *verb) { _cleanup_strv_free_ char **modes = NULL, **states = NULL; int r; - assert(streq(verb, "suspend") || - streq(verb, "hibernate") || - streq(verb, "hybrid-sleep")); + assert(STR_IN_SET(verb, "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate")); - r = parse_sleep_config(verb, &modes, &states); + if (streq(verb, "suspend-then-hibernate")) + return can_s2h(); + + r = parse_sleep_config(verb, &modes, &states, NULL); if (r < 0) return false; if (!can_sleep_state(states) || !can_sleep_disk(modes)) return false; - return streq(verb, "suspend") || enough_memory_for_hibernation(); + if (streq(verb, "suspend")) + return true; + + if (!enough_swap_for_hibernation()) + return -ENOSPC; + + return true; } diff --git a/src/shared/sleep-config.h b/src/shared/sleep-config.h index fc5a81d954..6bf035969a 100644 --- a/src/shared/sleep-config.h +++ b/src/shared/sleep-config.h @@ -1,26 +1,12 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. +#include <linux/fiemap.h> +#include "time-util.h" - 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/>. -***/ - -int parse_sleep_config(const char *verb, char ***modes, char ***states); +int read_fiemap(int fd, struct fiemap **ret); +int parse_sleep_config(const char *verb, char ***modes, char ***states, usec_t *delay); +int find_hibernate_location(char **device, char **type, size_t *size, size_t *used); int can_sleep(const char *verb); int can_sleep_disk(char **types); diff --git a/src/shared/spawn-ask-password-agent.c b/src/shared/spawn-ask-password-agent.c index f78167c25c..309071c89d 100644 --- a/src/shared/spawn-ask-password-agent.c +++ b/src/shared/spawn-ask-password-agent.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2011 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 <signal.h> #include <stdlib.h> diff --git a/src/shared/spawn-ask-password-agent.h b/src/shared/spawn-ask-password-agent.h index 158f8839ab..97e73bda44 100644 --- a/src/shared/spawn-ask-password-agent.h +++ b/src/shared/spawn-ask-password-agent.h @@ -1,24 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2011 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/>. -***/ - int ask_password_agent_open(void); void ask_password_agent_close(void); diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c index 3c93c79ceb..180cb7964c 100644 --- a/src/shared/spawn-polkit-agent.c +++ b/src/shared/spawn-polkit-agent.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2011 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 <poll.h> diff --git a/src/shared/spawn-polkit-agent.h b/src/shared/spawn-polkit-agent.h index 9f26fa10a7..190b970b6f 100644 --- a/src/shared/spawn-polkit-agent.h +++ b/src/shared/spawn-polkit-agent.h @@ -1,41 +1,22 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2012 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 "bus-util.h" int polkit_agent_open(void); void polkit_agent_close(void); -static inline void polkit_agent_open_if_enabled( +static inline int polkit_agent_open_if_enabled( BusTransport transport, bool ask_password) { /* Open the polkit agent as a child process if necessary */ if (transport != BUS_TRANSPORT_LOCAL) - return; + return 0; if (!ask_password) - return; + return 0; - polkit_agent_open(); + return polkit_agent_open(); } diff --git a/src/shared/specifier.c b/src/shared/specifier.c index 23aaa88c4b..d698b42e07 100644 --- a/src/shared/specifier.c +++ b/src/shared/specifier.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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> @@ -28,6 +10,7 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "fs-util.h" #include "hostname-util.h" #include "macro.h" #include "specifier.h" @@ -46,7 +29,7 @@ #define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%" int specifier_printf(const char *text, const Specifier table[], void *userdata, char **_ret) { - size_t l; + size_t l, allocated = 0; _cleanup_free_ char *ret = NULL; char *t; const char *f; @@ -57,14 +40,11 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata, assert(table); l = strlen(text); - ret = new(char, l+1); - if (!ret) + if (!GREEDY_REALLOC(ret, allocated, l + 1)) return -ENOMEM; - t = ret; - for (f = text; *f; f++, l--) { - + for (f = text; *f; f++, l--) if (percent) { if (*f == '%') *(t++) = '%'; @@ -77,7 +57,6 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata, if (i->lookup) { _cleanup_free_ char *w = NULL; - char *n; size_t k, j; r = i->lookup(i->specifier, i->data, userdata, &w); @@ -87,14 +66,9 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata, j = t - ret; k = strlen(w); - n = new(char, j + k + l + 1); - if (!n) + if (!GREEDY_REALLOC(ret, allocated, j + k + l + 1)) return -ENOMEM; - - memcpy(n, ret, j); - memcpy(n + j, w, k); - - free_and_replace(ret, n); + memcpy(ret + j, w, k); t = ret + j + k; } else if (strchr(POSSIBLE_SPECIFIERS, *f)) /* Oops, an unknown specifier. */ @@ -110,15 +84,20 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata, percent = true; else *(t++) = *f; - } - /* if string ended with a stray %, also end with % */ + /* If string ended with a stray %, also end with % */ if (percent) *(t++) = '%'; + *(t++) = 0; + + /* Try to deallocate unused bytes, but don't sweat it too much */ + if ((size_t)(t - ret) < allocated) { + t = realloc(ret, t - ret); + if (t) + ret = t; + } - *t = 0; - *_ret = ret; - ret = NULL; + *_ret = TAKE_PTR(ret); return 0; } @@ -239,6 +218,40 @@ int specifier_user_shell(char specifier, void *data, void *userdata, char **ret) return get_shell(ret); } +int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret) { + const char *p; + char *copy; + int r; + + r = tmp_dir(&p); + if (r < 0) + return r; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + +int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret) { + const char *p; + char *copy; + int r; + + r = var_tmp_dir(&p); + if (r < 0) + return r; + + copy = strdup(p); + if (!copy) + return -ENOMEM; + + *ret = copy; + return 0; +} + int specifier_escape_strv(char **l, char ***ret) { char **z, **p, **q; diff --git a/src/shared/specifier.h b/src/shared/specifier.h index bd6bc55577..e1895129d7 100644 --- a/src/shared/specifier.h +++ b/src/shared/specifier.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 "string-util.h" typedef int (*SpecifierCallback)(char specifier, void *data, void *userdata, char **ret); @@ -44,6 +25,9 @@ int specifier_user_id(char specifier, void *data, void *userdata, char **ret); int specifier_user_home(char specifier, void *data, void *userdata, char **ret); int specifier_user_shell(char specifier, void *data, void *userdata, char **ret); +int specifier_tmp_dir(char specifier, void *data, void *userdata, char **ret); +int specifier_var_tmp_dir(char specifier, void *data, void *userdata, char **ret); + static inline char* specifier_escape(const char *string) { return strreplace(string, "%", "%%"); } diff --git a/src/shared/switch-root.c b/src/shared/switch-root.c index 3c51fa36f3..28740cb474 100644 --- a/src/shared/switch-root.c +++ b/src/shared/switch-root.c @@ -1,21 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ /*** - This file is part of systemd. - - Copyright 2012 Harald Hoyer, 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/>. + Copyright © 2012 Harald Hoyer ***/ #include <errno.h> diff --git a/src/shared/switch-root.h b/src/shared/switch-root.h index abcdc1c65f..83294a4525 100644 --- a/src/shared/switch-root.h +++ b/src/shared/switch-root.h @@ -1,24 +1,10 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -#include <stdbool.h> /*** - This file is part of systemd. - - Copyright 2012 Harald Hoyer, 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/>. + Copyright © 2012 Harald Hoyer ***/ +#include <stdbool.h> + int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot, unsigned long mountflags); diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c index 0bc81aaa56..326652273c 100644 --- a/src/shared/sysctl-util.c +++ b/src/shared/sysctl-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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> diff --git a/src/shared/sysctl-util.h b/src/shared/sysctl-util.h index 446aa6f384..fd7c78b2b8 100644 --- a/src/shared/sysctl-util.h +++ b/src/shared/sysctl-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2011 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/>. -***/ - char *sysctl_normalize(char *s); int sysctl_read(const char *property, char **value); int sysctl_write(const char *property, const char *value); diff --git a/src/shared/test-tables.h b/src/shared/test-tables.h index dd8bf0b582..4eeda3b1bb 100644 --- a/src/shared/test-tables.h +++ b/src/shared/test-tables.h @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd - - 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 <stdio.h> #include <stdlib.h> diff --git a/src/shared/tests.c b/src/shared/tests.c index d4781acabf..6b3df0aa07 100644 --- a/src/shared/tests.c +++ b/src/shared/tests.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 <alloc-util.h> #include <fs-util.h> diff --git a/src/shared/tests.h b/src/shared/tests.h index b070f386e3..b88135ed93 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -1,24 +1,5 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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/>. -***/ - char* setup_fake_runtime_dir(void); const char* get_testdata_dir(const char *suffix); diff --git a/src/shared/tomoyo-util.c b/src/shared/tomoyo-util.c index 390fff6152..75c24d8007 100644 --- a/src/shared/tomoyo-util.c +++ b/src/shared/tomoyo-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2017 Shawn Landden - - 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 <unistd.h> diff --git a/src/shared/tomoyo-util.h b/src/shared/tomoyo-util.h index 4fb309fd54..03e6975469 100644 --- a/src/shared/tomoyo-util.h +++ b/src/shared/tomoyo-util.h @@ -1,24 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2017 Shawn Landden - - 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 <stdbool.h> diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 65a09e9c2e..16a0eed841 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2017 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 <string.h> @@ -31,7 +13,7 @@ int udev_parse_config(void) { size_t n; int r; - r = parse_env_file("/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL); + r = parse_env_file(NULL, "/etc/udev/udev.conf", NEWLINE, "udev_log", &val, NULL); if (r == -ENOENT || !val) return 0; if (r < 0) @@ -55,3 +37,26 @@ int udev_parse_config(void) { return 0; } + +int udev_device_new_from_stat_rdev(struct udev *udev, const struct stat *st, struct udev_device **ret) { + struct udev_device *nd; + char type; + + assert(udev); + assert(st); + assert(ret); + + if (S_ISBLK(st->st_mode)) + type = 'b'; + else if (S_ISCHR(st->st_mode)) + type = 'c'; + else + return -ENOTTY; + + nd = udev_device_new_from_devnum(udev, type, st->st_rdev); + if (!nd) + return -errno; + + *ret = nd; + return 0; +} diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index c5e4197dff..f36c568b5a 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - 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 "udev.h" #include "util.h" @@ -33,15 +14,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_u DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref); -#define _cleanup_udev_unref_ _cleanup_(udev_unrefp) -#define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp) -#define _cleanup_udev_enumerate_unref_ _cleanup_(udev_enumerate_unrefp) -#define _cleanup_udev_event_unref_ _cleanup_(udev_event_unrefp) -#define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp) -#define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp) -#define _cleanup_udev_ctrl_connection_unref_ _cleanup_(udev_ctrl_connection_unrefp) -#define _cleanup_udev_ctrl_msg_unref_ _cleanup_(udev_ctrl_msg_unrefp) -#define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp) -#define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup) - int udev_parse_config(void); + +int udev_device_new_from_stat_rdev(struct udev *udev, const struct stat *st, struct udev_device **ret); diff --git a/src/shared/uid-range.c b/src/shared/uid-range.c index 37d7c981f2..434ce6ff4d 100644 --- a/src/shared/uid-range.c +++ b/src/shared/uid-range.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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 <errno.h> #include <stdlib.h> @@ -61,7 +43,6 @@ static void uid_range_coalesce(UidRange **p, unsigned *n) { } } } - } static int uid_range_compare(const void *a, const void *b) { diff --git a/src/shared/uid-range.h b/src/shared/uid-range.h index 882f6624cd..49ba38287e 100644 --- a/src/shared/uid-range.h +++ b/src/shared/uid-range.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <sys/types.h> diff --git a/src/shared/utmp-wtmp.c b/src/shared/utmp-wtmp.c index cab1cd6a2d..ef9427fa7b 100644 --- a/src/shared/utmp-wtmp.c +++ b/src/shared/utmp-wtmp.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - 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> @@ -288,7 +270,6 @@ int utmp_put_dead_process(const char *id, pid_t pid, int code, int status) { return write_utmp_wtmp(&store, &store_wtmp); } - int utmp_put_runlevel(int runlevel, int previous) { struct utmpx store = {}; int r; diff --git a/src/shared/utmp-wtmp.h b/src/shared/utmp-wtmp.h index 2c75d4097e..9e433cf73e 100644 --- a/src/shared/utmp-wtmp.h +++ b/src/shared/utmp-wtmp.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - 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 <stdbool.h> #include <sys/types.h> diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c index fa270164bb..400994a354 100644 --- a/src/shared/vlan-util.c +++ b/src/shared/vlan-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2016 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 "conf-parser.h" #include "parse-util.h" diff --git a/src/shared/vlan-util.h b/src/shared/vlan-util.h index 6d287fd32a..ebe4331ed4 100644 --- a/src/shared/vlan-util.h +++ b/src/shared/vlan-util.h @@ -1,28 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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 <stdbool.h> #include <inttypes.h> +#include "conf-parser.h" + #define VLANID_MAX 4094 #define VLANID_INVALID UINT16_MAX @@ -33,5 +16,5 @@ static inline bool vlanid_is_valid(uint16_t id) { int parse_vlanid(const char *p, uint16_t *ret); -int config_parse_default_port_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -int config_parse_vlanid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +CONFIG_PARSER_PROTOTYPE(config_parse_default_port_vlanid); +CONFIG_PARSER_PROTOTYPE(config_parse_vlanid); diff --git a/src/shared/volatile-util.c b/src/shared/volatile-util.c index c92ad0adc0..4d75bc0e96 100644 --- a/src/shared/volatile-util.c +++ b/src/shared/volatile-util.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2015 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> @@ -24,27 +6,10 @@ #include "macro.h" #include "parse-util.h" #include "proc-cmdline.h" +#include "string-table.h" #include "string-util.h" #include "volatile-util.h" -VolatileMode volatile_mode_from_string(const char *s) { - int b; - - if (isempty(s)) - return _VOLATILE_MODE_INVALID; - - b = parse_boolean(s); - if (b > 0) - return VOLATILE_YES; - if (b == 0) - return VOLATILE_NO; - - if (streq(s, "state")) - return VOLATILE_STATE; - - return _VOLATILE_MODE_INVALID; -} - int query_volatile_mode(VolatileMode *ret) { _cleanup_free_ char *mode = NULL; VolatileMode m = VOLATILE_NO; @@ -69,3 +34,11 @@ finish: *ret = m; return r; } + +static const char* const volatile_mode_table[_VOLATILE_MODE_MAX] = { + [VOLATILE_NO] = "no", + [VOLATILE_YES] = "yes", + [VOLATILE_STATE] = "state", +}; + +DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(volatile_mode, VolatileMode, VOLATILE_YES); diff --git a/src/shared/volatile-util.h b/src/shared/volatile-util.h index 3ad037af8b..8761c44ab8 100644 --- a/src/shared/volatile-util.h +++ b/src/shared/volatile-util.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2016 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/>. -***/ - typedef enum VolatileMode { VOLATILE_NO, VOLATILE_YES, @@ -29,5 +10,6 @@ typedef enum VolatileMode { } VolatileMode; VolatileMode volatile_mode_from_string(const char *s); +const char* volatile_mode_to_string(VolatileMode m); int query_volatile_mode(VolatileMode *ret); diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c index b0a422da84..c423af6917 100644 --- a/src/shared/watchdog.c +++ b/src/shared/watchdog.c @@ -1,22 +1,4 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ -/*** - This file is part of systemd. - - Copyright 2012 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> @@ -54,7 +36,7 @@ static int update_timeout(void) { int sec, flags; char buf[FORMAT_TIMESPAN_MAX]; - sec = (int) ((watchdog_timeout + USEC_PER_SEC - 1) / USEC_PER_SEC); + sec = (int) DIV_ROUND_UP(watchdog_timeout, USEC_PER_SEC); r = ioctl(watchdog_fd, WDIOC_SETTIMEOUT, &sec); if (r < 0) return log_warning_errno(errno, "Failed to set timeout to %is: %m", sec); diff --git a/src/shared/watchdog.h b/src/shared/watchdog.h index 5694338db3..a345e4ba7d 100644 --- a/src/shared/watchdog.h +++ b/src/shared/watchdog.h @@ -1,25 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -/*** - This file is part of systemd. - - Copyright 2012 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 <stdbool.h> #include "time-util.h" |