]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: add basic Varlink support, for now only with a ListCandidateDevices() call
authorLennart Poettering <lennart@poettering.net>
Thu, 28 Aug 2025 09:19:41 +0000 (11:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Sep 2025 07:22:04 +0000 (09:22 +0200)
src/repart/repart.c
src/shared/meson.build
src/shared/varlink-io.systemd.Repart.c [new file with mode: 0644]
src/shared/varlink-io.systemd.Repart.h [new file with mode: 0644]
units/meson.build
units/systemd-repart.socket [new file with mode: 0644]
units/systemd-repart@.service [new file with mode: 0644]

index 74c348d030e7044057920a1aeb2d32f059fb2eaa..0c7b77f8450dc74e71f04653129eed5a69b0d501 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "sd-id128.h"
 #include "sd-json.h"
+#include "sd-varlink.h"
 
 #include "alloc-util.h"
 #include "ask-password-api.h"
@@ -79,6 +80,8 @@
 #include "tpm2-pcr.h"
 #include "tpm2-util.h"
 #include "utf8.h"
+#include "varlink-io.systemd.Repart.h"
+#include "varlink-util.h"
 #include "xattr-util.h"
 
 /* If not configured otherwise use a minimal partition size of 10M */
@@ -202,6 +205,7 @@ static char *arg_generate_fstab = NULL;
 static char *arg_generate_crypttab = NULL;
 static Set *arg_verity_settings = NULL;
 static bool arg_relax_copy_block_security = false;
+static bool arg_varlink = false;
 
 STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
 STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
@@ -9347,6 +9351,14 @@ static int parse_argv(
         if (arg_append_fstab && !arg_generate_fstab)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No --generate-fstab= specified for --append-fstab=%s.", append_mode_to_string(arg_append_fstab));
 
+        r = sd_varlink_invocation(SD_VARLINK_ALLOW_ACCEPT);
+        if (r < 0)
+                return log_error_errno(r, "Failed to check if invoked in Varlink mode: %m");
+        if (r > 0) {
+                arg_varlink = true;
+                arg_pager_flags |= PAGER_DISABLE;
+        }
+
         *ret_certificate = TAKE_PTR(certificate);
         *ret_private_key = TAKE_PTR(private_key);
         *ret_ui = TAKE_PTR(ui);
@@ -9771,6 +9783,88 @@ static int determine_auto_size(Context *c) {
         return 0;
 }
 
+static int vl_method_list_candidate_devices(
+                sd_varlink *link,
+                sd_json_variant *parameters,
+                sd_varlink_method_flags_t flags,
+                void *userdata) {
+
+        int r;
+
+        assert(link);
+
+        r = sd_varlink_dispatch(link, parameters, /* dispatch_table= */ NULL, /* userdata= */ NULL);
+        if (r != 0)
+                return r;
+
+        if (!FLAGS_SET(flags, SD_VARLINK_METHOD_MORE))
+                return sd_varlink_error(link, SD_VARLINK_ERROR_EXPECTED_MORE, NULL);
+
+        BlockDevice *l = NULL;
+        size_t n = 0;
+        CLEANUP_ARRAY(l, n, block_device_array_free);
+
+        r = blockdev_list(BLOCKDEV_LIST_SHOW_SYMLINKS|BLOCKDEV_LIST_REQUIRE_PARTITION_SCANNING|BLOCKDEV_LIST_IGNORE_ZRAM, &l, &n);
+        if (r < 0)
+                return r;
+
+        if (n == 0)
+                return sd_varlink_error(link, "io.systemd.Repart.NoCandidateDevices", NULL);
+
+        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
+        FOREACH_ARRAY(d, l, n) {
+                if (v) {
+                        r = sd_varlink_notify(link, v);
+                        if (r < 0)
+                                return r;
+
+                        v = sd_json_variant_unref(v);
+                }
+
+                r = sd_json_buildo(
+                                &v,
+                                SD_JSON_BUILD_PAIR_STRING("node", d->node),
+                                JSON_BUILD_PAIR_STRV_NON_EMPTY("symlinks", d->symlinks),
+                                SD_JSON_BUILD_PAIR_CONDITION(d->diskseq != UINT64_MAX, "diskseq", SD_JSON_BUILD_INTEGER(d->diskseq)),
+                                SD_JSON_BUILD_PAIR_CONDITION(d->size != UINT64_MAX, "sizeBytes", SD_JSON_BUILD_INTEGER(d->size)));
+                if (r < 0)
+                        return r;
+        }
+
+        assert(v);
+        return sd_varlink_reply(link, v);
+}
+
+static int vl_server(void) {
+        _cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
+        int r;
+
+        /* Invocation as Varlink service */
+
+        r = varlink_server_new(
+                        &varlink_server,
+                        SD_VARLINK_SERVER_ROOT_ONLY,
+                        /* userdata= */ NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate Varlink server: %m");
+
+        r = sd_varlink_server_add_interface(varlink_server, &vl_interface_io_systemd_Repart);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add Varlink interface: %m");
+
+        r = sd_varlink_server_bind_method_many(
+                        varlink_server,
+                        "io.systemd.Repart.ListCandidateDevices", vl_method_list_candidate_devices);
+        if (r < 0)
+                return log_error_errno(r, "Failed to bind Varlink methods: %m");
+
+        r = sd_varlink_server_loop_auto(varlink_server);
+        if (r < 0)
+                return log_error_errno(r, "Failed to run Varlink event loop: %m");
+
+        return 0;
+}
+
 static int run(int argc, char *argv[]) {
         _cleanup_(X509_freep) X509 *certificate = NULL;
         _cleanup_(openssl_ask_password_ui_freep) OpenSSLAskPasswordUI *ui = NULL;
@@ -9787,6 +9881,13 @@ static int run(int argc, char *argv[]) {
         if (r <= 0)
                 return r;
 
+#if HAVE_LIBCRYPTSETUP
+        cryptsetup_enable_logging(NULL);
+#endif
+
+        if (arg_varlink)
+                return vl_server();
+
         r = parse_proc_cmdline_factory_reset();
         if (r < 0)
                 return r;
@@ -9795,10 +9896,6 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return r;
 
-#if HAVE_LIBCRYPTSETUP
-        cryptsetup_enable_logging(NULL);
-#endif
-
         if (arg_image) {
                 assert(!arg_root);
 
index 790b1f2825c525cae5e2fd40884683db1dddddd9..4b84dd9cea3bd392b86b061099ab9f843f2ec594 100644 (file)
@@ -204,6 +204,7 @@ shared_sources = files(
         'varlink-io.systemd.Network.c',
         'varlink-io.systemd.PCRExtend.c',
         'varlink-io.systemd.PCRLock.c',
+        'varlink-io.systemd.Repart.c',
         'varlink-io.systemd.Resolve.c',
         'varlink-io.systemd.Resolve.Monitor.c',
         'varlink-io.systemd.Udev.c',
diff --git a/src/shared/varlink-io.systemd.Repart.c b/src/shared/varlink-io.systemd.Repart.c
new file mode 100644 (file)
index 0000000..4f531fe
--- /dev/null
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "sd-varlink-idl.h"
+
+#include "varlink-io.systemd.Repart.h"
+
+static SD_VARLINK_DEFINE_METHOD(
+                ListCandidateDevices,
+                SD_VARLINK_FIELD_COMMENT("The device node path of the block device."),
+                SD_VARLINK_DEFINE_OUTPUT(node, SD_VARLINK_STRING, 0),
+                SD_VARLINK_FIELD_COMMENT("List of symlinks pointing to the device node, if any."),
+                SD_VARLINK_DEFINE_OUTPUT(symlinks, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("The Linux kernel disk sequence number identifying the medium."),
+                SD_VARLINK_DEFINE_OUTPUT(diskseq, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
+                SD_VARLINK_FIELD_COMMENT("The size of the block device in bytes."),
+                SD_VARLINK_DEFINE_OUTPUT(sizeBytes, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
+
+static SD_VARLINK_DEFINE_ERROR(NoCandidateDevices);
+
+SD_VARLINK_DEFINE_INTERFACE(
+                io_systemd_Repart,
+                "io.systemd.Repart",
+                SD_VARLINK_INTERFACE_COMMENT("API for declaratively re-partitioning disks using systemd-repart."),
+                SD_VARLINK_SYMBOL_COMMENT("Return a list of candidate block devices, i.e. that support partition scanning and other requirements for successful operation."),
+                &vl_method_ListCandidateDevices,
+                SD_VARLINK_SYMBOL_COMMENT("Not a single candidate block device could be found."),
+                &vl_error_NoCandidateDevices);
diff --git a/src/shared/varlink-io.systemd.Repart.h b/src/shared/varlink-io.systemd.Repart.h
new file mode 100644 (file)
index 0000000..7c7cb7d
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "sd-varlink-idl.h"
+
+extern const sd_varlink_interface vl_interface_io_systemd_Repart;
index 4f47a3b2bdebfac2ab7b611b6a9543eee2259893..c5b99e4e04c35092acfdd79effe5c36db3fa3a8e 100644 (file)
@@ -651,6 +651,15 @@ units = [
           'conditions' : ['ENABLE_REPART'],
           'symlinks' : ['sysinit.target.wants/', 'initrd-root-fs.target.wants/'],
         },
+        {
+          'file' : 'systemd-repart.socket',
+          'conditions' : ['ENABLE_REPART'],
+          'symlinks' : ['sockets.target.wants/'],
+        },
+        {
+          'file' : 'systemd-repart@.service',
+          'conditions' : ['ENABLE_REPART'],
+        },
         {
           'file' : 'systemd-resolved.service.in',
           'conditions' : ['ENABLE_RESOLVE'],
diff --git a/units/systemd-repart.socket b/units/systemd-repart.socket
new file mode 100644 (file)
index 0000000..0c77165
--- /dev/null
@@ -0,0 +1,22 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Disk Repartitioning Service Socket
+Documentation=man:systemd-repart(8)
+DefaultDependencies=no
+Before=sockets.target
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Socket]
+ListenStream=/run/systemd/io.systemd.Repart
+FileDescriptorName=varlink
+SocketMode=0600
+Accept=yes
diff --git a/units/systemd-repart@.service b/units/systemd-repart@.service
new file mode 100644 (file)
index 0000000..f8061ed
--- /dev/null
@@ -0,0 +1,20 @@
+#  SPDX-License-Identifier: LGPL-2.1-or-later
+#
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Disk Repartitioning Service
+Documentation=man:systemd-repart.service(8)
+DefaultDependencies=no
+Wants=modprobe@loop.service modprobe@dm_mod.service
+After=modprobe@loop.service modprobe@dm_mod.service systemd-tpm2-setup-early.service
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+ExecStart=systemd-repart