From: Zbigniew Jędrzejewski-Szmek Date: Thu, 21 May 2026 08:08:09 +0000 (+0200) Subject: various: add -Dbuild-static and alternatives to libc functions X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bbeef4b948a3d7f178950777ae7479480fd2633a;p=thirdparty%2Fsystemd.git various: add -Dbuild-static and alternatives to libc functions When we try to build with -static, the linker refuses dlopen and various functions related to nss. This commit adds the basic support to compile with -static and allow the link to pass. --- diff --git a/meson.build b/meson.build index 0fcd12f0bdd..abdde0040b3 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,8 @@ conf.set10('SD_BOOT', false) conf.set10('SYSTEMD_MULTICALL_BINARY', get_option('systemd-multicall-binary')) +conf.set10('BUILD_STATIC', get_option('build-static')) + # Create a title-less summary section early, so it ends up first in the output. # More items are added later after they have been detected. summary({ diff --git a/meson_options.txt b/meson_options.txt index ced6fac1e39..8df682742d1 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -42,6 +42,8 @@ option('static-libudev', type : 'combo', description : 'install a static library for libudev') option('standalone-binaries', type : 'boolean', value : false, description : 'also build standalone versions of supported binaries') +option('build-static', type : 'boolean', value : false, + description : 'build static versions of supported binaries') option('sysvinit-path', type : 'string', value : '/etc/init.d', deprecated : true, description : 'This option is deprecated and will be removed in a future release') diff --git a/src/basic/dlfcn-util.c b/src/basic/dlfcn-util.c index 86ec2d28fd5..fe2f6a5f884 100644 --- a/src/basic/dlfcn-util.c +++ b/src/basic/dlfcn-util.c @@ -101,6 +101,10 @@ void block_dlopen(void) { } int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) { +#if BUILD_STATIC + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "dlopen is not supported in static builds, cannot load %s.", filename); +#else _cleanup_(dlclosep) void *dl = NULL; int r; @@ -142,4 +146,5 @@ int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) { *ret = TAKE_PTR(dl); return 0; +#endif } diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 6252ecc4d99..5c7f783f5ce 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -1171,6 +1171,9 @@ int lookup_pwent_in_files( return -ESRCH; } + +#if !BUILD_STATIC + static size_t getpw_buffer_size(void) { long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); return bufsize <= 0 ? 4096U : (size_t) bufsize; @@ -1182,15 +1185,25 @@ static bool errno_is_user_doesnt_exist(int error) { return IN_SET(abs(error), ENOENT, ESRCH, EBADF, EPERM); } +#endif + int getpwnam_malloc(const char *name, struct passwd **ret) { + /* For static builds use a very simplistic implementation that looks at 'passwd' in /etc/ + * and /usr/lib/, and for non-static builds use NSS. The first matching entry wins. The + * same logic is implemented in getpwnam_malloc, getpwuid_malloc, getgrnam_malloc, and + * getgrgid_malloc. */ + + if (isempty(name)) + return -EINVAL; + +#if BUILD_STATIC + return lookup_pwent_in_files(PASSWD_FILES, name, UID_INVALID, ret); +#else size_t bufsize = getpw_buffer_size(); int r; /* A wrapper around getpwnam_r() that allocates the necessary buffer on the heap. The caller must - * free() the returned structures! */ - - if (isempty(name)) - return -EINVAL; + * free() the returned structure! */ for (;;) { _cleanup_free_ void *buf = NULL; @@ -1226,15 +1239,19 @@ int getpwnam_malloc(const char *name, struct passwd **ret) { return -ENOMEM; bufsize *= 2; } +#endif } int getpwuid_malloc(uid_t uid, struct passwd **ret) { - size_t bufsize = getpw_buffer_size(); - int r; - if (!uid_is_valid(uid)) return -EINVAL; +#if BUILD_STATIC + return lookup_pwent_in_files(PASSWD_FILES, /* name= */ NULL, uid, ret); +#else + size_t bufsize = getpw_buffer_size(); + int r; + for (;;) { _cleanup_free_ void *buf = NULL; @@ -1267,6 +1284,7 @@ int getpwuid_malloc(uid_t uid, struct passwd **ret) { return -ENOMEM; bufsize *= 2; } +#endif } static int copy_struct_group(const struct group *gr, struct group **ret) { @@ -1427,18 +1445,25 @@ ssize_t lookup_groups_in_files( return n_arr; } +#if !BUILD_STATIC + static size_t getgr_buffer_size(void) { long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX); return bufsize <= 0 ? 4096U : (size_t) bufsize; } -int getgrnam_malloc(const char *name, struct group **ret) { - size_t bufsize = getgr_buffer_size(); - int r; +#endif +int getgrnam_malloc(const char *name, struct group **ret) { if (isempty(name)) return -EINVAL; +#if BUILD_STATIC + return lookup_grent_in_files(GROUP_FILES, name, GID_INVALID, ret); +#else + size_t bufsize = getgr_buffer_size(); + int r; + for (;;) { _cleanup_free_ void *buf = NULL; @@ -1471,15 +1496,19 @@ int getgrnam_malloc(const char *name, struct group **ret) { return -ENOMEM; bufsize *= 2; } +#endif } int getgrgid_malloc(gid_t gid, struct group **ret) { - size_t bufsize = getgr_buffer_size(); - int r; - if (!gid_is_valid(gid)) return -EINVAL; +#if BUILD_STATIC + return lookup_grent_in_files(GROUP_FILES, /* name= */ NULL, gid, ret); +#else + size_t bufsize = getgr_buffer_size(); + int r; + for (;;) { _cleanup_free_ void *buf = NULL; @@ -1512,4 +1541,5 @@ int getgrgid_malloc(gid_t gid, struct group **ret) { return -ENOMEM; bufsize *= 2; } +#endif } diff --git a/src/basic/user-util.h b/src/basic/user-util.h index e95ad038e58..6f90c8c4530 100644 --- a/src/basic/user-util.h +++ b/src/basic/user-util.h @@ -159,6 +159,10 @@ static inline bool hashed_password_is_locked_or_invalid(const char *password) { return password && password[0] != '$'; } +/* Places where we will try to load account data from */ +#define PASSWD_FILES STRV_MAKE("/etc/passwd", "/usr/lib/passwd") +#define GROUP_FILES STRV_MAKE("/etc/group", "/usr/lib/group") + /* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */ #define PASSWORD_LOCKED_AND_INVALID "!*" diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index e44c439fad8..2bd0439c597 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -827,6 +827,10 @@ static int parse_unix_address(sd_bus *b, const char **p, char **guid) { } static int parse_tcp_address(sd_bus *b, const char **p, char **guid) { +#if BUILD_STATIC + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "tcp:// connections are not supported in static builds"); +#else _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL; int r; struct addrinfo *result, hints = { @@ -889,6 +893,7 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) { b->is_local = false; return 0; +#endif } static int parse_exec_address(sd_bus *b, const char **p, char **guid) { diff --git a/src/tmpfiles/offline-passwd.c b/src/tmpfiles/offline-passwd.c index 75e9085c26b..c0490546b8d 100644 --- a/src/tmpfiles/offline-passwd.c +++ b/src/tmpfiles/offline-passwd.c @@ -53,10 +53,10 @@ static int populate_uid_cache(const char *root, Hashmap **ret) { /* The directory list is hardcoded here: /etc is the standard, and rpm-ostree uses /usr/lib. This * could be made configurable, but I don't see the point right now. */ - FOREACH_STRING(fname, "/etc/passwd", "/usr/lib/passwd") { + STRV_FOREACH(fname, PASSWD_FILES) { _cleanup_fclose_ FILE *f = NULL; - r = open_passwd_file(root, fname, &f); + r = open_passwd_file(root, *fname, &f); if (r == -ENOENT) continue; if (r < 0) @@ -93,10 +93,10 @@ static int populate_gid_cache(const char *root, Hashmap **ret) { if (!cache) return -ENOMEM; - FOREACH_STRING(fname, "/etc/group", "/usr/lib/group") { + STRV_FOREACH(fname, GROUP_FILES) { _cleanup_fclose_ FILE *f = NULL; - r = open_passwd_file(root, fname, &f); + r = open_passwd_file(root, *fname, &f); if (r == -ENOENT) continue; if (r < 0)