From: Mike Yuan Date: Fri, 17 Nov 2023 14:08:28 +0000 (+0800) Subject: networkctl: introduce --runtime for editing network config under /run/ X-Git-Tag: v256-rc1~1567^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2b98926f9809eb858a5abe4f64ebd067df5059d5;p=thirdparty%2Fsystemd.git networkctl: introduce --runtime for editing network config under /run/ --- diff --git a/man/networkctl.xml b/man/networkctl.xml index 68b1d97f09c..3a2dc09eccb 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -430,7 +430,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) Edit network configuration files, which include .network, .netdev, and .link files. If no network config file - matching the given name is found, a new one will be created under /etc/. + matching the given name is found, a new one will be created under /etc/ or + /run/, depending on whether is specified. Specially, if the name is prefixed by @, it will be treated as a network interface, and editing will be performed on the network config files associated with it. Additionally, the interface name can be suffixed with :network (default) @@ -541,6 +542,17 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR) + + + + + + When used with edit, edit the file under /run/ + instead of /etc/. + + + + diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 123ae62514d..939b590a6d0 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -87,6 +87,7 @@ static bool arg_no_reload = false; static bool arg_all = false; static bool arg_stats = false; static bool arg_full = false; +static bool arg_runtime = false; static unsigned arg_lines = 10; static char *arg_drop_in = NULL; static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; @@ -3076,14 +3077,20 @@ static int add_config_to_edit( assert(context); assert(path); - if (path_startswith(path, "/usr")) { + /* If we're supposed to edit main config file in /run/, but a config with the same name is present + * under /etc/, we bail out since the one in /etc/ always overrides that in /run/. */ + if (arg_runtime && !arg_drop_in && path_startswith(path, "/etc")) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Cannot edit runtime config file: overriden by %s", path); + + if (path_startswith(path, "/usr") || arg_runtime != !!path_startswith(path, "/run")) { _cleanup_free_ char *name = NULL; r = path_extract_filename(path, &name); if (r < 0) return log_error_errno(r, "Failed to extract filename from '%s': %m", path); - new_path = path_join(NETWORK_DIRS[0], name); + new_path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], name); if (!new_path) return log_oom(); } @@ -3091,16 +3098,27 @@ static int add_config_to_edit( if (!arg_drop_in) return edit_files_add(context, new_path ?: path, path, NULL); + bool need_new_dropin; + r = get_dropin_by_name(arg_drop_in, dropins, &old_dropin); if (r < 0) return log_error_errno(r, "Failed to acquire drop-in '%s': %m", arg_drop_in); + if (r > 0) { + /* See the explanation above */ + if (arg_runtime && path_startswith(old_dropin, "/etc")) + return log_error_errno(SYNTHETIC_ERRNO(EEXIST), + "Cannot edit runtime config file: overriden by %s", old_dropin); + + need_new_dropin = path_startswith(old_dropin, "/usr") || arg_runtime != !!path_startswith(old_dropin, "/run"); + } else + need_new_dropin = true; - if (r > 0 && !path_startswith(old_dropin, "/usr")) - /* An existing drop-in is found and not in /usr/. Let's edit it directly. */ + if (!need_new_dropin) + /* An existing drop-in is found in the correct scope. Let's edit it directly. */ dropin_path = TAKE_PTR(old_dropin); else { - /* No drop-in was found or an existing drop-in resides in /usr/. Let's create - * a new drop-in file. */ + /* No drop-in was found or an existing drop-in is in a different scope. Let's create a new + * drop-in file. */ dropin_path = strjoin(new_path ?: path, ".d/", arg_drop_in); if (!dropin_path) return log_oom(); @@ -3209,7 +3227,7 @@ static int verb_edit(int argc, char *argv[], void *userdata) { log_debug("No existing network config '%s' found, creating a new file.", *name); - path = path_join(NETWORK_DIRS[0], *name); + path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], *name); if (!path) return log_oom(); @@ -3340,6 +3358,7 @@ static int help(void) { " --no-reload Do not reload systemd-networkd or systemd-udevd\n" " after editing network config\n" " --drop-in=NAME Edit specified drop-in instead of main config file\n" + " --runtime Edit runtime config files\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -3357,6 +3376,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_JSON, ARG_NO_RELOAD, ARG_DROP_IN, + ARG_RUNTIME, }; static const struct option options[] = { @@ -3371,6 +3391,7 @@ static int parse_argv(int argc, char *argv[]) { { "json", required_argument, NULL, ARG_JSON }, { "no-reload", no_argument, NULL, ARG_NO_RELOAD }, { "drop-in", required_argument, NULL, ARG_DROP_IN }, + { "runtime", no_argument, NULL, ARG_RUNTIME }, {} }; @@ -3401,6 +3422,10 @@ static int parse_argv(int argc, char *argv[]) { arg_no_reload = true; break; + case ARG_RUNTIME: + arg_runtime = true; + break; + case ARG_DROP_IN: if (isempty(optarg)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name."); diff --git a/test/units/testsuite-74.networkctl.sh b/test/units/testsuite-74.networkctl.sh index 0a687af6e4d..b857abcf9a6 100755 --- a/test/units/testsuite-74.networkctl.sh +++ b/test/units/testsuite-74.networkctl.sh @@ -11,7 +11,7 @@ at_exit() { systemctl stop systemd-networkd if [[ -v NETWORK_NAME && -v NETDEV_NAME && -v LINK_NAME ]]; then - rm -fvr {/usr/lib,/etc}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \ + rm -fvr {/usr/lib,/etc,/run}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \ {/usr/lib,/etc}/systemd/network/"$LINK_NAME" "/etc/systemd/network/${NETWORK_NAME}.d" \ "new" "+4" fi @@ -35,9 +35,14 @@ cat >new <"+4" <