Commit Graph
484 Commits
Author SHA1 Message Date
Mike Yuan c27d1b3eec ssh-generator: follow symlink when searching for sshd@.service
unit_file_exists() currently does not follow symlinks, as it is
mainly used to test whether the unit (of any install state)
has been seen under search dirs. However, in ssh-generator
we should search for and honor whatever the distro ships,
which might be an alias or linked externally.
2026-02-03 08:17:34 +09:00
Zbigniew Jędrzejewski-Szmek 64eb78135c shared/install: rework error propagation again
The immediate impulse for this change is the fedora scriptlet which called:
  /usr/lib/systemd/systemd-update-helper install-system-units cryptsetup-pre.target cryptsetup.target getty@.service ... system-systemd\x2dcryptsetup.slice system-systemd\x2dveritysetup.slice ...
which called
  systemctl preset cryptsetup-pre.target cryptsetup.target getty@.service ... system-systemd\x2dcryptsetup.slice system-systemd\x2dveritysetup.slice ...
which threw an error that system-systemdx2dcryptsetup.slice does not exist
and did nothing at all. (The backslash is consumed by the shell.)
The obvious fix here is to figure out more levels of escaping… But we should
do something more robust in such cases.

If we fail in processing of a single unit, let preset all continue processing
units, report the failure through 'changes'. At the end, return failure. In
general, for operations which operate on a list of units specified by the user,
fail the whole operation if any of the individual operations failed. The only
operation where we don't do this is 'preset-all'.

$ SYSTEMD_LOG_LEVEL=debug build/systemctl --root=/ preset asdf1.servie asdf2.path; echo $?
Cannot find unit asdf1.servie.service.
Cannot find unit asdf2.path.
Failed to preset unit: Unit asdf1.servie.service does not exist
Failed to preset unit: Unit asdf2.path does not exist
1

While at it, fix double logging in the manager: dump_unit_changes() already
logs about errors, so the manager should only log on success.
2026-01-29 08:49:44 +01:00
Zbigniew Jędrzejewski-Szmek c67d64add6 shared/install: fix bogus error handling
This partially reverts a4f0e0da35. The
intent was good, we gather the errors, but we have no mechanism to
propagate the result, so the gathered result was ignored. In 'changes'
we can only report errors for specific units. If reading of the
directory fails, we might just as well report the error immediately.
This isn't great, but it's better then ignoring the errors. In practice,
failing halfway in this manner is unlikely, since it'd mean that the fs
is corrupted or something like that. We might as well return immediately
on such catastrophic errors.
2026-01-29 07:45:55 +01:00
Zbigniew Jędrzejewski-Szmek 8a27100d06 shared/install: ignore aliasing failure when doing presets
In recent Fedora, preset-all fails:
[  155s] Failed to preset unit: File '/buildroot/etc/systemd/user/dbus.service'
         already exists and is a symlink to /usr/lib/systemd/user/dbus-broker.service
[  155s] ‣ "systemctl --root=/buildroot --global preset-all" returned non-zero exit code 1.

Strictly speaking, this is an error in configuration. The presets specify that
both dbus-broker.service and dbus-daemon.service shall be enabled and they both
claim the 'dbus.service' alias. But this kind of error is very easy to make.
Failing the preset operation is too harsh, since in most cases the system will
work fine without an alias and changes in unrelated components can cause the
conflict.

Let's reuse the same logic that was added in
ad5fdd3912: when enabling the unit through
'preset' or 'preset-all', print the message, but suppress the error. When
enabling through 'enable', fail the operation.
2026-01-05 03:06:37 +09:00
Yu Watanabe 93378148d4 tree-wide: normalize comment style 2025-12-15 08:50:13 +09:00
Daan De Meyer 41ae31a9ac install: Fall back to system presets if there are no initrd presets
We might be operating with a newer systemctl on an image with older
systemd and thus without an initrd-preset directory. Before
4a8c395167, we would use the system
presets, let's make sure we keep doing that if we're operating on an
image without initrd presets.

Follow up for 4a8c395167.
2025-09-04 08:55:40 +02:00
Daan De Meyer c8e1e5814f install: Coding style fixlet 2025-09-04 08:42:32 +02:00
Yu Watanabe c119eb0edc install: skip later first_word() calls if one of earlier calls passes
Prompted by CID#1587764, that is false-positive.
2025-07-26 05:00:02 +09:00
DaanDeMeyer 4a8c395167 tree-wide: Add initrd presets
Currently, when running "systemctl preset-all --root=xxx" in mkosi
to enable/disable units for initrds, the system presets are used.
The problem with this approach is that the system presets are written
for the system, and that is not necessarily ideal for an initrd, but we
still want to use the same packages in the initrd that we install in the
system, so let's introduce a separate directory for initrd presets which
is used to pick up preset files from when we detect that we're configuring
an initrd (by looking for /etc/initrd-release).

We also introduce a systemd preset file for the initrd, which is based on
the system one, except with all the stuff unnecessary for the initrd removed.
2025-07-03 17:43:01 +02:00
Yu Watanabe b351ebdc97 Revert "tree-wide: use CONF_FILES_CHASE_BASENAME where root directory is specified"
This reverts commit 6b606f3586.

The commit was mistakenly merged without review, and has several issues.
Let's revert at least now.
2025-06-29 10:15:56 +09:00
Yu Watanabe 6b606f3586 tree-wide: use CONF_FILES_CHASE_BASENAME where root directory is specified
Otherwise, the result may point to outside of the root directory.

This also sets CONF_FILES_REGULAR and CONF_FILES_FILTER_MASKED, as the
callers will call fopen() or friends for the result, thus the enumerated
results must be non-empty regular files.
2025-06-28 04:13:43 +09:00
Daan De Meyer 69a283c5f2 shared: Clean up includes
Split out of #37344.
2025-05-24 14:00:44 +02:00
Daan De Meyer 1fbfbe81b5 tree-wide: Get rid of prefix_roota() in favor of path_join()
We deprecated prefix_roota() in favor of chase() and path_join().
Let's finish the removal by replacing the few remaining call sites
with path_join().
2025-05-06 17:40:33 +02:00
Daan De Meyer 1cf40697e3 tree-wide: Sort includes
This was done by running a locally built clang-format with
https://github.com/llvm/llvm-project/pull/137617 and
https://github.com/llvm/llvm-project/pull/137840 applied on all .c
and .h files.
2025-04-30 09:30:51 +02:00
Yu Watanabe f9ae1f5cf5 install: use hash_ops with destructor for InstallInfo 2025-04-13 09:49:39 +09:00
Yu Watanabe 8d190e990e install: use path_hash_ops_free 2025-04-13 09:49:39 +09:00
Zbigniew Jędrzejewski-Szmek 1ae9b0cfa8 basic/glyph-util: rename "special glyph" to just "glyph"
Admittedly, some of our glyphs _are_ special, e.g. "O=" for SPECIAL_GLYPH_TOUCH ;)
But we don't need this in the name. The very long names make some invocations
very wordy, e.g. special_glyph(SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY).
Also, I want to add GLYPH_SPACE, which is not special at all.
2025-03-15 14:40:39 +01:00
Yu Watanabe 223a67e572 tree-wide: replace reallocarray() with GREEDY_REALLOC() 2024-10-08 19:56:09 +09:00
Lennart Poettering 64d61d1918 install: shorten code a bit
This changes behaviour a bit, since we now keep track of OOM errors in
install_changes_add(). Which I'd argue is a good thing.
2024-06-21 16:27:13 +02:00
Lennart Poettering 422f80d59b install: collect more install_changes_add() errors
We so far collected most unexpected errors from install_changes_add()
and propagated them – but for some invocations we forgot to do that. Add
that, and take care we only propagated unexpected errors (i.e. ENOMEM
and such), but treat expected errors as before.

Follow-up for 5163c9b1e5
2024-06-21 16:25:57 +02:00
Mike Yuan 4441cf330b shared/install: correctly report changes in install_info_symlink_alias()
Follow-up for b2751cf039

Also make the conditions consistent for install_info_symlink_wants().

Fixes #33411
2024-06-19 21:28:55 +02:00
Mike Yuan a159aa07e1 shared/install: propagate all errors in install_info_apply()
Currently, install_info_apply() only updates r if it's 0,
meaning that if one of the earlier install_info_symlink_alias/wants()
calls returns > 0, errors generated by later calls will be discarded.
Fix that.
2024-06-19 21:28:40 +02:00
Mike Yuan dd6b325a05 shared/install: drop unneeded initialization 2024-06-19 21:19:13 +02:00
Luca Boccassi 5163c9b1e5 install: allow removing symlinks even for units that are gone
If a symlink is leftover, still allow cleaning it up via 'disable'. This
happens when a unit is stopped and removed, but not disabled, and a reload
has already happened. At that point, cleaning up the old symlinks becomes
impossible through the APIs, and needs to be done manually. Always allow
cleaning up symlinks, if they exist, by only erroring out if there is an
OOM.

Follow-up for f31f10a620
2024-06-18 16:07:26 +02:00
Mike Yuan 521a7c9bb9 shared/install: use FOREACH_ARRAY at one more place 2024-06-11 23:17:21 +01:00
Mike Yuan 3e02c8d87d shared/install: replace streq + basename with path_equal_filename 2024-06-11 23:17:21 +01:00
Mike Yuan d51c404507 shared/install: use path_extract_filename in install_info_traverse 2024-06-11 23:17:21 +01:00
Mike Yuan ca3c95c1c5 shared/install: modernize unit_file_get_list, use key destructor
The rest of the basename()s are easy to drop.
2024-06-11 23:17:21 +01:00
Mike Yuan 0bb4614adc shared/install: modernize unit_file_link
Also eliminate one more use of basename(), yay!
2024-06-11 23:17:21 +01:00
Mike Yuan e9e77e443d install,dbus-manager: make unit_file_* take (char* const*) for strv 2024-06-11 23:17:21 +01:00
Mike Yuan 1ac0056cc2 shared/install: modernize install_info_add 2024-06-11 23:17:21 +01:00
Mike Yuan df152dbbe5 shared/install: modernize find_symlinks and friends 2024-06-11 23:17:21 +01:00
Mike Yuan 1d2e1cad30 shared/install: modernize remove_marked_symlink_fd
Note that we now collect errors from
install_changes_add(), too.
2024-06-11 23:17:21 +01:00
Mike Yuan 05adb256f1 shared/install: return bool where appropriate 2024-06-11 23:17:21 +01:00
Zbigniew Jędrzejewski-Szmek a4f0e0da35 preset-all: continue on errors, report more errors
Firstly, if we encounter an error when iterating over the directory, gather
the error but continue. This is unlikely to happen, but if it happens, then
it doesn't seem very useful to break the preset processing at a random
point. If we can't process a unit — too bad, but since we already might
have processed some units earlier, we might as well try to process the
remaining ones.

Secondly, add missing error codes for units that are in a bad state to the
exclusion list. Those, we report them in the changes list, but consider the
whole operation a success. (-ETXTBSY and -ENOLINK were missing.)

Thirdly, add a message generator for -ENOLINK.

Fixes https://github.com/systemd/systemd/issues/21224.
2024-05-08 08:18:55 +02:00
Mike Yuan a4d733db9f shared/install: reduce variable scope 2024-05-01 17:35:20 +08:00
Zbigniew Jędrzejewski-Szmek acb27fba43 shared/install: use PATH_IN_SET() 2024-03-23 13:30:24 +01:00
Zbigniew Jędrzejewski-Szmek 1934242b72 Drop unnecessary path_equal_ptr() wrapper
path_equal already works with NULL pointers.
2024-03-23 13:21:06 +01:00
Zbigniew Jędrzejewski-Szmek 4f77ddca59 various: also use strdup_to() in cases where we don't return immediately 2024-03-20 15:18:21 +01:00
Zbigniew Jędrzejewski-Szmek 454318d3e8 various: use strdup_to() in various obvious cases
strdup_to() returns 0 on success and here we convert obvious blocks
which either return -ENOMEM or 0.
2024-03-20 15:13:44 +01:00
Nick Rosbrook 6fec0fed10 shared/install: correctly install alias for units outside search path
Currently, if a unit file is enabled from outside of the search path,
and that unit has an alias, then the symlink ends up pointing outside of
the search path too. For example:

 $ cat /tmp/a.service
 [Service]
 ExecStart=sleep infinity

 [Install]
 Alias=b.service
 WantedBy=multi-user.target

 $ systemctl enable /tmp/a.service
 Created symlink /etc/systemd/system/a.service → /tmp/a.service.
 Created symlink /etc/systemd/system/b.service → /tmp/a.service.
 Created symlink /etc/systemd/system/multi-user.target.wants/a.service → /tmp/a.service.

This then means the alias is treated as a separate unit:

 $ systemctl start a.service
 $ sudo systemctl status a
 ● a.service
  Loaded: loaded (/etc/systemd/system/a.service; enabled; preset: enabled)
  Active: active (running) since Fri 2024-03-15 15:17:49 EDT; 9s ago
 Main PID: 769593 (sleep)
   Tasks: 1 (limit: 18898)
  Memory: 220.0K
     CPU: 5ms
  CGroup: /system.slice/a.service
          └─769593 sleep infinity

 Mar 15 15:17:49 six systemd[1]: Started a.service.
 $ sudo systemctl status b
 ○ b.service
  Loaded: loaded (/etc/systemd/system/b.service; alias)
  Active: inactive (dead)

To fix this, make sure the alias uses a target that is inside the search
path. Since the unit file itself is outside of the search path, a
symlink inside the search path will have been created already. Hence,
just point the alias symlink to that recently created symlink.
2024-03-18 11:58:07 +00:00
Zbigniew Jędrzejewski-Szmek ec596fe34e Merge pull request #30480 from keszybz/kernel-install-more-paths
Read kernel-install config from /run/kernel too
2024-03-08 08:25:07 +01:00
Zbigniew Jędrzejewski-Szmek 76d75d8b7b constants: drop duplicated CONF_PATHS defines
Follow-up for b0d3095fd6.
2024-03-07 18:47:50 +01:00
Mike Yuan d41f08bd2a core,install: generalize install error handling 2024-03-07 02:05:15 +08:00
Mike Yuan b412274fd0 shared/install: use FOREACH_ARRAY at one more place 2024-03-07 02:02:00 +08:00
Mike Yuan b2751cf039 shared/install: use RET_GATHER more 2024-03-07 02:02:00 +08:00
Mike Yuan 7dfc71399d path-lookup: rename lookup_paths_free -> _done
This is stack-allocated, so update to match our usual rules.
2024-03-07 02:01:57 +08:00
Luca Boccassi 8040fa55a1 install: fix compiler warning about empty directive argument
On ppc64el with gcc 13.2 on Ubuntu 24.04:

3s In file included from ../src/basic/macro.h:386,
483s                  from ../src/basic/alloc-util.h:10,
483s                  from ../src/shared/install.c:12:
483s ../src/shared/install.c: In function ‘install_changes_dump’:
483s ../src/shared/install.c:432:64: error: ‘%s’ directive argument is null [-Werror=format-overflow=]
483s   432 |                         err = log_error_errno(changes[i].type, "Failed to %s unit, unit %s does not exist.",
483s       |                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
483s ../src/shared/install.c:432:75: note: format string is defined here
483s   432 |                         err = log_error_errno(changes[i].type, "Failed to %s unit, unit %s does not exist.",
2024-02-28 01:08:56 +00:00
Lennart Poettering e09c255d2e install: optionally return discovered unit file path in unit_file_exists() 2024-01-11 16:05:20 +01:00
Yu Watanabe b3a9d980f3 tree-wide: drop space between variable and an increment/decrement 2023-12-25 01:56:40 +09:00