]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysupdate: Factor out temporary path computation for transfers
authorPhilip Withnall <pwithnall@gnome.org>
Wed, 31 Dec 2025 00:36:22 +0000 (00:36 +0000)
committerPhilip Withnall <pwithnall@gnome.org>
Mon, 9 Feb 2026 12:04:52 +0000 (12:04 +0000)
This helper function will be reused in a following commit.

This introduces no functional changes.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: https://github.com/systemd/systemd/issues/34814

src/sysupdate/sysupdate-transfer.c

index f624a50cf40a9feb24efa81502b4acc298f3e22a..5af2f4cf301fac52280b9099e78853688a6d591e 100644 (file)
@@ -1168,27 +1168,15 @@ static int run_callout(
         return sd_event_loop(event);
 }
 
-int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, void *userdata) {
-        _cleanup_free_ char *formatted_pattern = NULL, *digest = NULL;
-        _cleanup_free_ char *formatted_partial_pattern = NULL;
-        _cleanup_free_ char *formatted_pending_pattern = NULL;
-        char offset[DECIMAL_STR_MAX(uint64_t)+1], max_size[DECIMAL_STR_MAX(uint64_t)+1];
-        const char *where = NULL;
-        InstanceMetadata f;
-        Instance *existing;
+/* Build the filenames and paths which is normally done by transfer_acquire_instance(), but for partial
+ * and pending instances which are about to be installed (in which case, transfer_acquire_instance() is
+ * skipped). */
+static int transfer_compute_temporary_paths(Transfer *t, Instance *i, InstanceMetadata *f) {
+        _cleanup_free_ char *formatted_pattern = NULL, *formatted_partial_pattern = NULL, *formatted_pending_pattern = NULL;
         int r;
 
         assert(t);
         assert(i);
-        assert(i->resource == &t->source);
-        assert(cb);
-
-        /* Does this instance already exist in the target? Then we don't need to acquire anything */
-        existing = resource_find_instance(&t->target, i->metadata.version);
-        if (existing) {
-                log_info("No need to acquire '%s', already installed.", i->path);
-                return 0;
-        }
 
         assert(!t->final_path);
         assert(!t->temporary_partial_path);
@@ -1199,8 +1187,8 @@ int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, voi
         assert(!strv_isempty(t->target.patterns));
 
         /* Format the target name using the first pattern specified */
-        compile_pattern_fields(t, i, &f);
-        r = pattern_format(t->target.patterns[0], &f, &formatted_pattern);
+        compile_pattern_fields(t, i, f);
+        r = pattern_format(t->target.patterns[0], f, &formatted_pattern);
         if (r < 0)
                 return log_error_errno(r, "Failed to format target pattern: %m");
 
@@ -1214,10 +1202,6 @@ int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, voi
                 if (!t->final_path)
                         return log_oom();
 
-                r = mkdir_parents(t->final_path, 0755);
-                if (r < 0)
-                        return log_error_errno(r, "Cannot create target directory: %m");
-
                 /* Build the paths for the partial and pending files, which hold the resource while it’s
                  * being acquired and after it’s been acquired (but before it’s moved to the final_path
                  * when it’s installed).
@@ -1238,19 +1222,9 @@ int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, voi
                 if (!t->temporary_partial_path)
                         return log_oom();
 
-                r = mkdir_parents(t->temporary_partial_path, 0755);
-                if (r < 0)
-                        return log_error_errno(r, "Cannot create target directory: %m");
-
                 t->temporary_pending_path = path_join(final_dir, pending_filename);
                 if (!t->temporary_pending_path)
                         return log_oom();
-
-                r = mkdir_parents(t->temporary_pending_path, 0755);
-                if (r < 0)
-                        return log_error_errno(r, "Cannot create target directory: %m");
-
-                where = t->final_path;
         }
 
         if (t->target.type == RESOURCE_PARTITION) {
@@ -1281,7 +1255,55 @@ int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, voi
                 free_and_replace(t->temporary_pending_partition_label, formatted_pending_pattern);
 
                 t->final_partition_label = TAKE_PTR(formatted_pattern);
+        }
+
+        return 0;
+}
 
+int transfer_acquire_instance(Transfer *t, Instance *i, TransferProgress cb, void *userdata) {
+        _cleanup_free_ char *digest = NULL;
+        char offset[DECIMAL_STR_MAX(uint64_t)+1], max_size[DECIMAL_STR_MAX(uint64_t)+1];
+        const char *where = NULL;
+        InstanceMetadata f;
+        Instance *existing;
+        int r;
+
+        assert(t);
+        assert(i);
+        assert(i->resource == &t->source);
+        assert(cb);
+
+        /* Does this instance already exist in the target? Then we don't need to acquire anything */
+        existing = resource_find_instance(&t->target, i->metadata.version);
+        if (existing && (existing->is_partial || existing->is_pending))
+                return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to acquire '%s', instance is already partial or pending in the target.", i->path);
+        if (existing) {
+                log_info("No need to acquire '%s', already installed.", i->path);
+                return 0;
+        }
+
+        /* Compute up the temporary paths */
+        r = transfer_compute_temporary_paths(t, i, &f);
+        if (r < 0)
+                return r;
+
+        if (RESOURCE_IS_FILESYSTEM(t->target.type)) {
+                r = mkdir_parents(t->temporary_partial_path, 0755);
+                if (r < 0)
+                        return log_error_errno(r, "Cannot create target directory: %m");
+
+                r = mkdir_parents(t->temporary_pending_path, 0755);
+                if (r < 0)
+                        return log_error_errno(r, "Cannot create target directory: %m");
+
+                r = mkdir_parents(t->final_path, 0755);
+                if (r < 0)
+                        return log_error_errno(r, "Cannot create target directory: %m");
+
+                where = t->final_path;
+        }
+
+        if (t->target.type == RESOURCE_PARTITION) {
                 r = find_suitable_partition(
                                 t->target.path,
                                 i->metadata.size,