]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hostname: introduce gethostname_full() and use it in various gethostname() variants 20418/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 10 Aug 2021 18:44:24 +0000 (03:44 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 12 Aug 2021 04:48:15 +0000 (13:48 +0900)
src/basic/hostname-util.c
src/basic/hostname-util.h
src/hostname/hostnamed.c
src/shared/hostname-setup.c
src/shared/hostname-setup.h

index 29d69910d2486cc1e431d00c0503a52279be0812..1d0640e075685f5143115d409910aa1cf90fc29f 100644 (file)
@@ -36,66 +36,39 @@ char* get_default_hostname(void) {
         return strdup(FALLBACK_HOSTNAME);
 }
 
-char* gethostname_malloc(void) {
+int gethostname_full(GetHostnameFlags flags, char **ret) {
+        _cleanup_free_ char *buf = NULL, *fallback = NULL;
         struct utsname u;
         const char *s;
 
-        /* This call tries to return something useful, either the actual hostname
-         * or it makes something up. The only reason it might fail is OOM.
-         * It might even return "localhost" if that's set. */
+        assert(ret);
 
         assert_se(uname(&u) >= 0);
 
         s = u.nodename;
-        if (isempty(s) || streq(s, "(none)"))
-                return get_default_hostname();
-
-        return strdup(s);
-}
-
-char* gethostname_short_malloc(void) {
-        struct utsname u;
-        const char *s;
-        _cleanup_free_ char *f = NULL;
-
-        /* Like above, but kills the FQDN part if present. */
-
-        assert_se(uname(&u) >= 0);
-
-        s = u.nodename;
-        if (isempty(s) || streq(s, "(none)") || s[0] == '.') {
-                s = f = get_default_hostname();
+        if (isempty(s) ||
+            (!FLAGS_SET(flags, GET_HOSTNAME_ALLOW_NONE) && streq(s, "(none)")) ||
+            (!FLAGS_SET(flags, GET_HOSTNAME_ALLOW_LOCALHOST) && is_localhost(s)) ||
+            (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')) {
+                if (!FLAGS_SET(flags, GET_HOSTNAME_FALLBACK_DEFAULT))
+                        return -ENXIO;
+
+                s = fallback = get_default_hostname();
                 if (!s)
-                        return NULL;
+                        return -ENOMEM;
 
-                assert(s[0] != '.');
+                if (FLAGS_SET(flags, GET_HOSTNAME_SHORT) && s[0] == '.')
+                        return -ENXIO;
         }
 
-        return strndup(s, strcspn(s, "."));
-}
-
-int gethostname_strict(char **ret) {
-        struct utsname u;
-        char *k;
-
-        /* This call will rather fail than make up a name. It will not return "localhost" either. */
-
-        assert_se(uname(&u) >= 0);
-
-        if (isempty(u.nodename))
-                return -ENXIO;
-
-        if (streq(u.nodename, "(none)"))
-                return -ENXIO;
-
-        if (is_localhost(u.nodename))
-                return -ENXIO;
-
-        k = strdup(u.nodename);
-        if (!k)
+        if (FLAGS_SET(flags, GET_HOSTNAME_SHORT))
+                buf = strndup(s, strcspn(s, "."));
+        else
+                buf = strdup(s);
+        if (!buf)
                 return -ENOMEM;
 
-        *ret = k;
+        *ret = TAKE_PTR(buf);
         return 0;
 }
 
index c3fc6752cbae43369ebfdbfcb64274da817bd358..28975c879203f6af1467a5319a136ed1a8d9d34e 100644 (file)
@@ -7,10 +7,37 @@
 #include "macro.h"
 #include "strv.h"
 
+typedef enum GetHostnameFlags {
+        GET_HOSTNAME_ALLOW_NONE       = 1 << 0, /* accepts "(none)". */
+        GET_HOSTNAME_ALLOW_LOCALHOST  = 1 << 1, /* accepts "localhost" or friends. */
+        GET_HOSTNAME_FALLBACK_DEFAULT = 1 << 2, /* use default hostname if no hostname is set. */
+        GET_HOSTNAME_SHORT            = 1 << 3, /* kills the FQDN part if present. */
+} GetHostnameFlags;
+
+int gethostname_full(GetHostnameFlags flags, char **ret);
+static inline int gethostname_strict(char **ret) {
+        return gethostname_full(0, ret);
+}
+
+static inline char* gethostname_malloc(void) {
+        char *s;
+
+        if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT, &s) < 0)
+                return NULL;
+
+        return s;
+}
+
+static inline char* gethostname_short_malloc(void) {
+        char *s;
+
+        if (gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST | GET_HOSTNAME_FALLBACK_DEFAULT | GET_HOSTNAME_SHORT, &s) < 0)
+                return NULL;
+
+        return s;
+}
+
 char* get_default_hostname(void);
-char* gethostname_malloc(void);
-char* gethostname_short_malloc(void);
-int gethostname_strict(char **ret);
 
 bool valid_ldh_char(char c) _const_;
 
index 36702f2fb0cd22ffbff8443a6ddd3c069c7d34e8..2557d6d8071033def8281df883269b1964581054 100644 (file)
@@ -575,8 +575,7 @@ static int property_get_default_hostname(
 }
 
 static void context_determine_hostname_source(Context *c) {
-        char hostname[HOST_NAME_MAX + 1] = {};
-        _cleanup_free_ char *fallback = NULL;
+        _cleanup_free_ char *hostname = NULL;
         int r;
 
         assert(c);
@@ -584,11 +583,13 @@ static void context_determine_hostname_source(Context *c) {
         if (c->hostname_source >= 0)
                 return;
 
-        (void) get_hostname_filtered(hostname);
+        (void) gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &hostname);
 
         if (streq_ptr(hostname, c->data[PROP_STATIC_HOSTNAME]))
                 c->hostname_source = HOSTNAME_STATIC;
         else {
+                _cleanup_free_ char *fallback = NULL;
+
                 /* If the hostname was not set by us, try to figure out where it came from. If we set it to
                  * the default hostname, the file will tell us. We compare the string because it is possible
                  * that the hostname was set by an older version that had a different fallback, in the
index 742174d6c8907c1602e04b6c203e51f3d86dddbd..1329b0d1894b91105a5c67f29f7047a11ba5011f 100644 (file)
 #include "util.h"
 
 static int sethostname_idempotent_full(const char *s, bool really) {
-        char buf[HOST_NAME_MAX + 1];
+        _cleanup_free_ char *buf = NULL;
+        int r;
 
         assert(s);
 
-        if (gethostname(buf, sizeof(buf)) < 0)
-                return -errno;
+        r = gethostname_full(GET_HOSTNAME_ALLOW_NONE | GET_HOSTNAME_ALLOW_LOCALHOST, &buf);
+        if (r < 0)
+                return r;
 
         if (streq(buf, s))
                 return 0;
@@ -41,26 +43,6 @@ int sethostname_idempotent(const char *s) {
         return sethostname_idempotent_full(s, true);
 }
 
-bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]) {
-        char buf[HOST_NAME_MAX + 1];
-
-        /* Returns true if we got a good hostname, false otherwise. */
-
-        if (gethostname(buf, sizeof(buf)) < 0)
-                return false;  /* This can realistically only fail with ENAMETOOLONG.
-                                * Let's treat that case the same as an invalid hostname. */
-
-        if (isempty(buf))
-                return false;
-
-        /* This is the built-in kernel default hostname */
-        if (streq(buf, "(none)"))
-                return false;
-
-        memcpy(ret, buf, sizeof buf);
-        return true;
-}
-
 int shorten_overlong(const char *s, char **ret) {
         char *h, *p;
 
@@ -195,10 +177,14 @@ int hostname_setup(bool really) {
         }
 
         if (!hn) {
+                _cleanup_free_ char *buf = NULL;
+
                 /* Don't override the hostname if it is already set and not explicitly configured */
 
-                char buf[HOST_NAME_MAX + 1] = {};
-                if (get_hostname_filtered(buf)) {
+                r = gethostname_full(GET_HOSTNAME_ALLOW_LOCALHOST, &buf);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r >= 0) {
                         log_debug("No hostname configured, leaving existing hostname <%s> in place.", buf);
                         return 0;
                 }
index 5ac7241a59fae20f297eef41a8bb26bfe74b94cd..6def36c350e1b90dbb4edae236650d3c21046ef2 100644 (file)
@@ -21,6 +21,5 @@ int shorten_overlong(const char *s, char **ret);
 int read_etc_hostname_stream(FILE *f, char **ret);
 int read_etc_hostname(const char *path, char **ret);
 
-bool get_hostname_filtered(char ret[static HOST_NAME_MAX + 1]);
 void hostname_update_source_hint(const char *hostname, HostnameSource source);
 int hostname_setup(bool really);