]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkctl: introduce --runtime for editing network config under /run/ 30085/head
authorMike Yuan <me@yhndnzj.com>
Fri, 17 Nov 2023 14:08:28 +0000 (22:08 +0800)
committerMike Yuan <me@yhndnzj.com>
Sat, 2 Dec 2023 09:04:57 +0000 (17:04 +0800)
man/networkctl.xml
src/network/networkctl.c
test/units/testsuite-74.networkctl.sh

index 68b1d97f09cf6d4e692c504a8c0c3a1cad8509f8..3a2dc09eccbe6b28c8aa6a37b801feb35c419504 100644 (file)
@@ -430,7 +430,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
         </term>
         <listitem><para>Edit network configuration files, which include <filename>.network</filename>,
         <filename>.netdev</filename>, and <filename>.link</filename> files. If no network config file
-        matching the given name is found, a new one will be created under <filename>/etc/</filename>.
+        matching the given name is found, a new one will be created under <filename>/etc/</filename> or
+        <filename>/run/</filename>, depending on whether <option>--runtime</option> is specified.
         Specially, if the name is prefixed by <literal>@</literal>, 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 <literal>:network</literal> (default)
@@ -541,6 +542,17 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
 
         <xi:include href="version-info.xml" xpointer="v254"/>
         </listitem>
+
+      <varlistentry>
+        <term><option>--runtime</option></term>
+
+        <listitem>
+          <para>When used with <command>edit</command>, edit the file under <filename>/run/</filename>
+          instead of <filename>/etc/</filename>.</para>
+
+          <xi:include href="version-info.xml" xpointer="v256"/>
+        </listitem>
+      </varlistentry>
       </varlistentry>
 
       <xi:include href="standard-options.xml" xpointer="json" />
index 123ae62514dbfd2d87fdd89d829b7b6bade62ced..939b590a6d07ed89e43f7c5342aaabe976b9a318 100644 (file)
@@ -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.");
index 0a687af6e4d7db9037975fed366004870c3a9269..b857abcf9a6ebb604ce628c6b9bed34cae0c4340 100755 (executable)
@@ -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 <<EOF
 Name=test2
 EOF
 
-EDITOR='mv new' script -ec 'networkctl edit "$NETWORK_NAME"' /dev/null
+EDITOR='mv new' script -ec 'networkctl edit --runtime "$NETWORK_NAME"' /dev/null
+printf '%s\n' '[Match]' 'Name=test2' | cmp - "/run/systemd/network/$NETWORK_NAME"
+
+EDITOR='true' script -ec 'networkctl edit "$NETWORK_NAME"' /dev/null
 printf '%s\n' '[Match]' 'Name=test2' | cmp - "/etc/systemd/network/$NETWORK_NAME"
 
+(! EDITOR='true' script -ec 'networkctl edit --runtime "$NETWORK_NAME"' /dev/null)
+
 cat >"+4" <<EOF
 [Network]
 IPv6AcceptRA=no
@@ -80,6 +85,9 @@ networkctl cat @test2:network | cmp - <(networkctl cat "$NETWORK_NAME")
 EDITOR='cp' script -ec 'networkctl edit @test2 --drop-in test2.conf' /dev/null
 cmp "+4" "/etc/systemd/network/${NETWORK_NAME}.d/test2.conf"
 
+sleep 1
+(! EDITOR='true' script -ec 'networkctl edit @test2 --runtime --drop-in test2.conf' /dev/null)
+
 ip_link="$(ip link show test2)"
 if systemctl --quiet is-active systemd-udevd; then
     assert_in 'alias test_alias' "$ip_link"