From 0995accdfd8d6c8ab5d237398cfaf58c64246274 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 11 Aug 2021 03:44:24 +0900 Subject: [PATCH] hostname: introduce gethostname_full() and use it in various gethostname() variants --- src/basic/hostname-util.c | 67 +++++++++++-------------------------- src/basic/hostname-util.h | 33 ++++++++++++++++-- src/hostname/hostnamed.c | 7 ++-- src/shared/hostname-setup.c | 36 ++++++-------------- src/shared/hostname-setup.h | 1 - 5 files changed, 65 insertions(+), 79 deletions(-) diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c index 29d69910d24..1d0640e0756 100644 --- a/src/basic/hostname-util.c +++ b/src/basic/hostname-util.c @@ -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; } diff --git a/src/basic/hostname-util.h b/src/basic/hostname-util.h index c3fc6752cba..28975c87920 100644 --- a/src/basic/hostname-util.h +++ b/src/basic/hostname-util.h @@ -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_; diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 36702f2fb0c..2557d6d8071 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -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 diff --git a/src/shared/hostname-setup.c b/src/shared/hostname-setup.c index 742174d6c89..1329b0d1894 100644 --- a/src/shared/hostname-setup.c +++ b/src/shared/hostname-setup.c @@ -20,12 +20,14 @@ #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; } diff --git a/src/shared/hostname-setup.h b/src/shared/hostname-setup.h index 5ac7241a59f..6def36c350e 100644 --- a/src/shared/hostname-setup.h +++ b/src/shared/hostname-setup.h @@ -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); -- 2.47.3