From: Zbigniew Jędrzejewski-Szmek Date: Mon, 8 Sep 2025 17:47:28 +0000 (+0200) Subject: generators: when creating symlinks, silently ignore existing links in one more place X-Git-Tag: v258~12 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8a9ab3dbbc86cf72ef8f511a3214f66a61f6bd01;p=thirdparty%2Fsystemd.git generators: when creating symlinks, silently ignore existing links in one more place After the update to systemd 257.7 in Fedora, there are reports that we fail to create a symlink: systemd-gpt-auto-generator[585]: Failed to create symlink /run/systemd/generator/local-fs.target.wants/systemd-fsck-root.service: File exists (sd-exec-[574]: /usr/lib/systemd/system-generators/systemd-gpt-auto-generator failed with exit status 1. I guess that some other generator created the symlink. We silently ignore EEXIST in similar codepaths, so add that in one more place. (The target of the symlink doesn't really matter. The name of the link matters. So something like symlink_idempotent would not be better. For example, a different generator might use a slightly different target path, and symlink_idempotent would be too strict.) --- diff --git a/src/shared/generator.c b/src/shared/generator.c index f978d43fe89..f7ae848d6e1 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -26,6 +26,14 @@ #include "tmpfile-util.h" #include "unit-name.h" +static int symlink_unless_exists(const char *to, const char *from) { + (void) mkdir_parents(from, 0755); + + if (symlink(to, from) < 0 && errno != EEXIST) + return log_error_errno(errno, "Failed to create symlink %s: %m", from); + return 0; +} + int generator_open_unit_file_full( const char *dir, const char *source, @@ -134,12 +142,7 @@ int generator_add_symlink_full( if (!to) return log_oom(); - (void) mkdir_parents_label(to, 0755); - - if (symlink(from, to) < 0 && errno != EEXIST) - return log_error_errno(errno, "Failed to create symlink \"%s\": %m", to); - - return 0; + return symlink_unless_exists(from, to); } static int generator_add_ordering( @@ -331,19 +334,16 @@ int generator_write_fsck_deps( } if (path_equal(where, "/")) { - const char *lnk; - /* We support running the fsck instance for the root fs while it is already mounted, for * compatibility with non-initrd boots. It's ugly, but it is how it is. Since – unlike for * regular file systems – this means the ordering is reversed (i.e. mount *before* fsck) we * have a separate fsck unit for this, independent of systemd-fsck@.service. */ - lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE); - - (void) mkdir_parents(lnk, 0755); - if (symlink(SYSTEM_DATA_UNIT_DIR "/" SPECIAL_FSCK_ROOT_SERVICE, lnk) < 0) - return log_error_errno(errno, "Failed to create symlink %s: %m", lnk); + const char *lnk = strjoina(dir, "/" SPECIAL_LOCAL_FS_TARGET ".wants/" SPECIAL_FSCK_ROOT_SERVICE); + r = symlink_unless_exists(SYSTEM_DATA_UNIT_DIR "/" SPECIAL_FSCK_ROOT_SERVICE, lnk); + if (r < 0) + return r; } else { _cleanup_free_ char *_fsck = NULL; const char *fsck, *dep;