systemd System and Service Manager
-CHANGES WITH 242 in spe:
+CHANGES WITH 242:
* In .link files, MACAddressPolicy=persistent (the default) is changed
to cover more devices. For devices like bridges, tun, tap, bond, and
Jungel, Tom Yan, Tony Asleson, Topi Miettinen, unixsysadmin, Van Laser,
Vesa Jääskeläinen, Yu, Li-Yu, Yu Watanabe, Zbigniew Jędrzejewski-Szmek
- — Somewhere, 2019-0X-YZ
+ — Warsaw, 2019-04-03
CHANGES WITH 241:
above, it could consist of this:
```
-/usr/bin/minimald # a statically compiled binary
-/usr/lib/systemd/minimal-test.service # the unit file for the service, with ExecStart=/usr/bin/minimald
-/usr/lib/os-release # an os-release file explaining what this is
-/etc/resolv.conf # empty file to mount over with host's version
-/etc/machine-id # ditto
-/proc/ # empty directory to use as mount point for host's API fs
-/sys/ # ditto
-/dev/ # ditto
-/run/ # ditto
-/tmp/ # ditto
-/var/tmp/ # ditto
+/usr/bin/minimald # a statically compiled binary
+/usr/lib/systemd/system/minimal-test.service # the unit file for the service, with ExecStart=/usr/bin/minimald
+/usr/lib/os-release # an os-release file explaining what this is
+/etc/resolv.conf # empty file to mount over with host's version
+/etc/machine-id # ditto
+/proc/ # empty directory to use as mount point for host's API fs
+/sys/ # ditto
+/dev/ # ditto
+/run/ # ditto
+/tmp/ # ditto
+/var/tmp/ # ditto
```
And that's it.
pkgincludedir = join_paths(includedir, 'systemd')
systemgeneratordir = join_paths(rootlibexecdir, 'system-generators')
usergeneratordir = join_paths(prefixdir, 'lib/systemd/user-generators')
-pkgsysconfsystemgeneratordir = join_paths(pkgsysconfdir, 'system-generators')
-pkgsysconfusergeneratordir = join_paths(pkgsysconfdir, 'user-generators')
systemenvgeneratordir = join_paths(prefixdir, 'lib/systemd/system-environment-generators')
userenvgeneratordir = join_paths(prefixdir, 'lib/systemd/user-environment-generators')
systemshutdowndir = join_paths(rootlibexecdir, 'system-shutdown')
assert(ret_description);
*ret_badness =
- (isempty(info->root_directory) ||
- path_equal(info->root_directory, "/")) &&
- (isempty(info->root_image) ||
- path_equal(info->root_image, "/"));
+ empty_or_root(info->root_directory) ||
+ empty_or_root(info->root_image);
*ret_description = NULL;
return 0;
/* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an
* O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */
- if ((flags & O_PATH) == O_PATH)
+ if (FLAGS_SET(flags, O_PATH))
flags |= O_DIRECTORY;
- else if ((flags & O_TMPFILE) != O_TMPFILE)
+ else if (!FLAGS_SET(flags, O_TMPFILE))
flags |= O_DIRECTORY|O_RDONLY;
fd = open(parent, flags, mode);
}
/* extend array */
- t = realloc(order, (n + 1) * sizeof(uint16_t));
+ t = reallocarray(order, n + 1, sizeof(uint16_t));
if (!t)
return -ENOMEM;
order = t;
case KEYPRESS(0, 0, CHAR_LINEFEED):
case KEYPRESS(0, 0, CHAR_CARRIAGE_RETURN):
- if (StrCmp(line, line_in) != 0) {
- *line_out = line;
- line = NULL;
- }
+ if (StrCmp(line, line_in) != 0)
+ *line_out = TAKE_PTR(line);
enter = TRUE;
exit = TRUE;
break;
/* If the file we just renamed is the loader path, then let's update that. */
if (StrCmp(entry->loader, old_path) == 0) {
FreePool(entry->loader);
- entry->loader = new_path;
- new_path = NULL;
+ entry->loader = TAKE_PTR(new_path);
}
}
s = PoolPrint(L"%s %s", entry->options, new);
FreePool(entry->options);
entry->options = s;
- } else {
- entry->options = new;
- new = NULL;
- }
+ } else
+ entry->options = TAKE_PTR(new);
continue;
}
s = PoolPrint(L"%s %s", initrd, entry->options);
FreePool(entry->options);
entry->options = s;
- } else {
- entry->options = initrd;
- initrd = NULL;
- }
+ } else
+ entry->options = TAKE_PTR(initrd);
}
entry->device = device;
/* Return buffer directly if it happens to be NUL terminated already */
if (size >= 2 && buf[size-2] == 0 && buf[size-1] == 0) {
- *value = (CHAR16*) buf;
- buf = NULL;
+ *value = (CHAR16*) TAKE_PTR(buf);
return EFI_SUCCESS;
}
arg_count = (mask & CGROUP_MASK_PIDS) ? COUNT_PIDS : COUNT_USERSPACE_PROCESSES;
- if (arg_recursive_unset && arg_count == COUNT_PIDS) {
- log_error("Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
- return -EINVAL;
- }
+ if (arg_recursive_unset && arg_count == COUNT_PIDS)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Non-recursive counting is only supported when counting processes, not tasks. Use -P or -k.");
r = show_cgroup_get_path_and_warn(arg_machine, arg_root, &root);
if (r < 0)
$1.MemoryDenyWriteExecute, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictNamespaces, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictRealtime, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
-$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION 0
+$1.RestrictSUIDSGID, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.RestrictAddressFamilies, config_parse_warn_compat, DISABLED_CONFIGURATION, 0
$1.LockPersonality, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
$1.LimitCPU, config_parse_rlimit, RLIMIT_CPU, offsetof($1, exec_context.rlimit)
meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
-meson.add_install_script('sh', '-c', mkdir_p.format(pkgsysconfsystemgeneratordir))
-meson.add_install_script('sh', '-c', mkdir_p.format(pkgsysconfusergeneratordir))
meson.add_install_script('sh', '-c',
mkdir_p.format(join_paths(pkgsysconfdir, 'system/multi-user.target.wants')))
assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
/* use /sys/dev/{block,char}/<maj>:<min> link */
- snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum));
+ xsprintf(id, "%u:%u", major(devnum), minor(devnum));
syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
timeout = 0;
m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max,
- timeout == (uint64_t) -1 ? -1 : (int) ((timeout + USEC_PER_MSEC - 1) / USEC_PER_MSEC));
+ timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC));
if (m < 0) {
if (errno == EINTR) {
e->state = SD_EVENT_PENDING;
uid_t *t;
n = MAX(16, 2*r);
- t = realloc(l, sizeof(uid_t) * n);
+ t = reallocarray(l, sizeof(uid_t), n);
if (!t)
return -ENOMEM;
case ARG_LINK_JOURNAL:
r = parse_link_journal(optarg, &arg_link_journal, &arg_link_journal_try);
- if (r < 0) {
- log_error_errno(r, "Failed to parse link journal mode %s", optarg);
- return -EINVAL;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse link journal mode %s", optarg);
arg_settings_mask |= SETTING_LINK_JOURNAL;
break;
if (r < 0)
return log_error_errno(r, "Failed to parse root hash: %s", optarg);
if (l < sizeof(sd_id128_t)) {
- log_error("Root hash must be at least 128bit long: %s", optarg);
free(k);
- return -EINVAL;
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root hash must be at least 128bit long: %s", optarg);
}
free(arg_root_hash);
"read-only\n"
"passive\n"
"pipe");
- else {
- log_error("Unknown console mode: %s", optarg);
- return -EINVAL;
- }
+ else
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg);
arg_settings_mask |= SETTING_CONSOLE_MODE;
break;
return log_error_errno(r, "Failed to determine current directory: %m");
}
- if (!arg_directory && !arg_image) {
- log_error("Failed to determine path, please use -D or -i.");
- return -EINVAL;
- }
+ if (!arg_directory && !arg_image)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine path, please use -D or -i.");
}
if (!arg_machine) {
return log_oom();
hostname_cleanup(arg_machine);
- if (!machine_name_is_valid(arg_machine)) {
- log_error("Failed to determine machine name automatically, please use -M.");
- return -EINVAL;
- }
+ if (!machine_name_is_valid(arg_machine))
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine machine name automatically, please use -M.");
if (arg_ephemeral) {
char *b;
break;
}
- if (!good) {
- log_error("Refusing to write to sysctl '%s', as it is not safe in the selected namespaces.", *k);
- return -EPERM;
- }
+ if (!good)
+ return log_error_errno(SYNTHETIC_ERRNO(EPERM), "Refusing to write to sysctl '%s', as it is not safe in the selected namespaces.", *k);
r = sysctl_write(*k, *v);
if (r < 0)
log_debug_errno(r, "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does.", arg_network_namespace_path);
else if (r < 0)
return log_error_errno(r, "Failed to check %s fs type: %m", arg_network_namespace_path);
- else if (r == 0) {
- log_error("Path %s doesn't refer to a network namespace, refusing.", arg_network_namespace_path);
- return -EINVAL;
- }
+ else if (r == 0)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "Path %s doesn't refer to a network namespace, refusing.", arg_network_namespace_path);
}
*pid = raw_clone(SIGCHLD|CLONE_NEWNS);
l = recv(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, 0);
if (l < 0)
return log_error_errno(errno, "Failed to read UID shift: %m");
- if (l != sizeof arg_uid_shift) {
- log_error("Short read while reading UID shift.");
- return -EIO;
- }
+ if (l != sizeof arg_uid_shift)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading UID shift.");
if (arg_userns_mode == USER_NAMESPACE_PICK) {
/* If we are supposed to pick the UID shift, let's try to use the shift read from the
l = send(uid_shift_socket_pair[0], &arg_uid_shift, sizeof arg_uid_shift, MSG_NOSIGNAL);
if (l < 0)
return log_error_errno(errno, "Failed to send UID shift: %m");
- if (l != sizeof arg_uid_shift) {
- log_error("Short write while writing UID shift.");
- return -EIO;
- }
+ if (l != sizeof arg_uid_shift)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing UID shift.");
}
}
l = recv(unified_cgroup_hierarchy_socket_pair[0], &arg_unified_cgroup_hierarchy, sizeof(arg_unified_cgroup_hierarchy), 0);
if (l < 0)
return log_error_errno(errno, "Failed to read cgroup mode: %m");
- if (l != sizeof(arg_unified_cgroup_hierarchy)) {
- log_error("Short read while reading cgroup mode (%zu bytes).%s",
- l, l == 0 ? " The child is most likely dead." : "");
- return -EIO;
- }
+ if (l != sizeof(arg_unified_cgroup_hierarchy))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading cgroup mode (%zu bytes).%s",
+ l, l == 0 ? " The child is most likely dead." : "");
}
/* Wait for the outer child. */
l = recv(pid_socket_pair[0], pid, sizeof *pid, 0);
if (l < 0)
return log_error_errno(errno, "Failed to read inner child PID: %m");
- if (l != sizeof *pid) {
- log_error("Short read while reading inner child PID.");
- return -EIO;
- }
+ if (l != sizeof *pid)
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading inner child PID.");
/* We also retrieve container UUID in case it was generated by outer child */
l = recv(uuid_socket_pair[0], &arg_uuid, sizeof arg_uuid, 0);
if (l < 0)
return log_error_errno(errno, "Failed to read container machine ID: %m");
- if (l != sizeof(arg_uuid)) {
- log_error("Short read while reading container machined ID.");
- return -EIO;
- }
+ if (l != sizeof(arg_uuid))
+ return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short read while reading container machined ID.");
/* We also retrieve the socket used for notifications generated by outer child */
notify_socket = receive_one_fd(notify_socket_pair[0], 0);
log_debug("Init process invoked as PID "PID_FMT, *pid);
if (arg_userns_mode != USER_NAMESPACE_NO) {
- if (!barrier_place_and_sync(&barrier)) { /* #1 */
- log_error("Child died too early.");
- return -ESRCH;
- }
+ if (!barrier_place_and_sync(&barrier)) /* #1 */
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early.");
r = setup_uid_map(*pid);
if (r < 0)
if (arg_private_network) {
if (!arg_network_namespace_path) {
/* Wait until the child has unshared its network namespace. */
- if (!barrier_place_and_sync(&barrier)) { /* #3 */
- log_error("Child died too early");
- return -ESRCH;
- }
+ if (!barrier_place_and_sync(&barrier)) /* #3 */
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early");
}
r = move_network_interfaces(*pid, arg_network_interfaces);
return r;
/* Let the child know that we are ready and wait that the child is completely ready now. */
- if (!barrier_place_and_sync(&barrier)) { /* #5 */
- log_error("Child died too early.");
- return -ESRCH;
- }
+ if (!barrier_place_and_sync(&barrier)) /* #5 */
+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early.");
/* At this point we have made use of the UID we picked, and thus nss-mymachines
* will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */
}
}
- if (arg_ifindex > 0 && arg_ifindex != ifi) {
- log_error("Specified multiple different interfaces. Refusing.");
- return -EINVAL;
- }
+ if (arg_ifindex > 0 && arg_ifindex != ifi)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified multiple different interfaces. Refusing.");
arg_ifindex = ifi;
free_and_replace(arg_ifname, iface);
if ((u & NAMESPACE_FLAGS_ALL) == 0)
result = "yes";
- else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
+ else if (FLAGS_SET(u, NAMESPACE_FLAGS_ALL))
result = "no";
else {
r = namespace_flags_to_string(u, &s);
assert(variant);
assert(b);
- if (!json_variant_is_boolean(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not a boolean.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_boolean(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
*b = json_variant_boolean(variant);
return 0;
assert(variant);
assert(b);
- if (!json_variant_is_boolean(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not a boolean.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_boolean(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
*b = json_variant_boolean(variant);
return 0;
assert(variant);
assert(i);
- if (!json_variant_is_integer(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not an integer.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_integer(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
*i = json_variant_integer(variant);
return 0;
assert(variant);
assert(u);
- if (!json_variant_is_unsigned(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not an unsigned integer.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_unsigned(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
*u = json_variant_unsigned(variant);
return 0;
assert(variant);
assert(u);
- if (!json_variant_is_unsigned(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not an unsigned integer.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_unsigned(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
- if (json_variant_unsigned(variant) > UINT32_MAX) {
- json_log(variant, flags, 0, "JSON field '%s' out of bounds.", strna(name));
- return -ERANGE;
- }
+ if (json_variant_unsigned(variant) > UINT32_MAX)
+ return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
*u = (uint32_t) json_variant_unsigned(variant);
return 0;
assert(variant);
assert(i);
- if (!json_variant_is_integer(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not an integer.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_integer(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
- if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX) {
- json_log(variant, flags, 0, "JSON field '%s' out of bounds.", strna(name));
- return -ERANGE;
- }
+ if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX)
+ return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
*i = (int32_t) json_variant_integer(variant);
return 0;
return 0;
}
- if (!json_variant_is_string(variant)) {
- json_log(variant, flags, 0, "JSON field '%s' is not a string.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_string(variant))
+ return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
r = free_and_strdup(s, json_variant_string(variant));
if (r < 0)
return 0;
}
- if (!json_variant_is_array(variant)) {
- json_log(variant, 0, flags, "JSON field '%s' is not an array.", strna(name));
- return -EINVAL;
- }
+ if (!json_variant_is_array(variant))
+ return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name));
for (i = 0; i < json_variant_elements(variant); i++) {
JsonVariant *e;
assert_se(e = json_variant_by_index(variant, i));
- if (!json_variant_is_string(e)) {
- json_log(e, 0, flags, "JSON array element is not a string.");
- return -EINVAL;
- }
+ if (!json_variant_is_string(e))
+ return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string.");
r = strv_extend(&l, json_variant_string(e));
if (r < 0)
char *pos;
bool match = false;
- if (!val)
- val = "";
+ val = strempty(val);
switch (token->key.glob) {
case GL_PLAIN: