]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hostnamectl: try to set transient hostname even if updating static or pretty hostname...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 22 Jan 2021 02:20:50 +0000 (11:20 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 9 Feb 2021 04:49:15 +0000 (13:49 +0900)
If no target (--pretty, --static, or --transient) is specified, then
let's try to set transient hostname even if setting static or pretty
hostname failed. This may be useful for read-only filesystem.

src/hostname/hostnamectl.c

index 99c9883efa544953beb9db52ed90d7f625af94ee..aaba1deacd4a1d84f3fdbbfa77a3df3af9f148e9 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "alloc-util.h"
 #include "architecture.h"
+#include "bus-common-errors.h"
 #include "bus-error.h"
 #include "bus-map-properties.h"
 #include "hostname-util.h"
@@ -222,36 +223,45 @@ static int show_status(int argc, char **argv, void *userdata) {
         }
 }
 
-static int set_simple_string(sd_bus *bus, const char *target, const char *method, const char *value) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+static int set_simple_string_internal(sd_bus *bus, sd_bus_error *error, const char *target, const char *method, const char *value) {
+        _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
         int r;
 
         polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
 
+        if (!error)
+                error = &e;
+
         r = sd_bus_call_method(
                         bus,
                         "org.freedesktop.hostname1",
                         "/org/freedesktop/hostname1",
                         "org.freedesktop.hostname1",
                         method,
-                        &error, NULL,
+                        error, NULL,
                         "sb", value, arg_ask_password);
         if (r < 0)
-                return log_error_errno(r, "Could not set %s: %s", target, bus_error_message(&error, r));
+                return log_error_errno(r, "Could not set %s: %s", target, bus_error_message(error, r));
 
         return 0;
 }
 
+static int set_simple_string(sd_bus *bus, const char *target, const char *method, const char *value) {
+        return set_simple_string_internal(bus, NULL, target, method, value);
+}
+
 static int set_hostname(int argc, char **argv, void *userdata) {
         _cleanup_free_ char *h = NULL;
         const char *hostname = argv[1];
         sd_bus *bus = userdata;
-        int r;
+        bool implicit = false, show_hint = false;
+        int r, ret = 0;
 
         if (!arg_pretty && !arg_static && !arg_transient)
-                arg_pretty = arg_static = arg_transient = true;
+                arg_pretty = arg_static = arg_transient = implicit = true;
 
         if (arg_pretty) {
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
                 const char *p;
 
                 /* If the passed hostname is already valid, then assume the user doesn't know anything about pretty
@@ -262,9 +272,17 @@ static int set_hostname(int argc, char **argv, void *userdata) {
                 else
                         p = hostname; /* Use the passed name as pretty hostname */
 
-                r = set_simple_string(bus, "pretty hostname", "SetPrettyHostname", p);
-                if (r < 0)
-                        return r;
+                r = set_simple_string_internal(bus, &error, "pretty hostname", "SetPrettyHostname", p);
+                if (r < 0) {
+                        if (implicit &&
+                            sd_bus_error_has_names(&error,
+                                                   BUS_ERROR_FILE_IS_PROTECTED,
+                                                   BUS_ERROR_READ_ONLY_FILESYSTEM)) {
+                                show_hint = true;
+                                ret = r;
+                        } else
+                                return r;
+                }
 
                 /* Now that we set the pretty hostname, let's clean up the parameter and use that as static
                  * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing
@@ -280,9 +298,19 @@ static int set_hostname(int argc, char **argv, void *userdata) {
         }
 
         if (arg_static) {
-                r = set_simple_string(bus, "static hostname", "SetStaticHostname", hostname);
-                if (r < 0)
-                        return r;
+                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                r = set_simple_string_internal(bus, &error, "static hostname", "SetStaticHostname", hostname);
+                if (r < 0) {
+                        if (implicit &&
+                            sd_bus_error_has_names(&error,
+                                                   BUS_ERROR_FILE_IS_PROTECTED,
+                                                   BUS_ERROR_READ_ONLY_FILESYSTEM)) {
+                                show_hint = true;
+                                ret = r;
+                        } else
+                                return r;
+                }
         }
 
         if (arg_transient) {
@@ -291,7 +319,10 @@ static int set_hostname(int argc, char **argv, void *userdata) {
                         return r;
         }
 
-        return 0;
+        if (show_hint)
+                log_info("Hint: use --transient option when /etc/machine-info or /etc/hostname cannot be modified (e.g. located in read-only filesystem).");
+
+        return ret;
 }
 
 static int set_icon_name(int argc, char **argv, void *userdata) {