]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
various: add -Dbuild-static and alternatives to libc functions
authorZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 21 May 2026 08:08:09 +0000 (10:08 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
Thu, 2 Jul 2026 15:19:18 +0000 (17:19 +0200)
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.

meson.build
meson_options.txt
src/basic/dlfcn-util.c
src/basic/user-util.c
src/basic/user-util.h
src/libsystemd/sd-bus/sd-bus.c
src/tmpfiles/offline-passwd.c

index 0fcd12f0bddbb6ae0abbe09ac55d09825ecd4d27..abdde0040b3c0b5957ad054c71cc626f3aa4c737 100644 (file)
@@ -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({
index ced6fac1e39fb44fe6a06dc49882e5d99a93ae9f..8df682742d1b2c547dcc3a7d2833cfe535dbee9d 100644 (file)
@@ -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')
index 86ec2d28fd5a01abfcd9bcd4cb47b930af50e79f..fe2f6a5f88487ddae6a0f8c38f4ec19ad47d1ae5 100644 (file)
@@ -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
 }
index 6252ecc4d99bbaf61501fee853ce2f8ede055f47..5c7f783f5ce7a2dc0dee78e6fa283bab3c2d7110 100644 (file)
@@ -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
 }
index e95ad038e58adec3bd5831b80c752e0464bec505..6f90c8c4530e12d62bb29314b4fc2db2ed893dda 100644 (file)
@@ -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 "!*"
 
index e44c439fad862aa4e262b437edf6d6363a395e26..2bd0439c59795cb95f798cc646e4a3f6ea7ef86c 100644 (file)
@@ -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) {
index 75e9085c26bf0f525448baa79b6e4e383c6d849e..c0490546b8d907f474976dfc86f9bb9f5f7f0fa0 100644 (file)
@@ -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)