]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
import: Handle small files 42150/head
authorKai Lüke <kai@amutable.com>
Mon, 18 May 2026 07:46:28 +0000 (16:46 +0900)
committerKai Lüke <kai@amutable.com>
Mon, 18 May 2026 10:30:10 +0000 (19:30 +0900)
When systemd-pull encountered a file shorter than the compression magic
headers it looks for, then it would complete the download in the
analysis state and fail.
When we are still in the analysis state and the download is done, we
know there is no compression and we should leave the analysis state and
continue writing out to disk as usual.

src/import/pull-job.c
test/units/TEST-72-SYSUPDATE.sh

index 2dc960c39292d518ea08a9770130ef13cf414b4e..31d6d34af6bc7766c1dab995cd7546338b80f357 100644 (file)
@@ -299,6 +299,29 @@ static int pull_job_open_disk(PullJob *j) {
         return 0;
 }
 
+static int pull_job_begin_running(PullJob *j) {
+        int r;
+
+        assert(j);
+        assert(j->state == PULL_JOB_ANALYZING);
+        assert(j->compress);
+
+        r = pull_job_open_disk(j);
+        if (r < 0)
+                return r;
+
+        /* Now, take the payload we read so far, and decompress it */
+        _cleanup_(iovec_done) struct iovec stub = TAKE_STRUCT(j->payload);
+
+        j->state = PULL_JOB_RUNNING;
+
+        r = pull_job_write_compressed(j, &stub);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 static int pull_job_curl_on_finished(CurlSlot *slot, CURL *curl, CURLcode result, void *userdata) {
         PullJob *j = ASSERT_PTR(userdata);
         char *scheme = NULL;
@@ -382,6 +405,20 @@ static int pull_job_curl_on_finished(CurlSlot *slot, CURL *curl, CURLcode result
                         return pull_job_finish(j, log_error_errno(SYNTHETIC_ERRNO(EIO), "HTTP request to %s finished with unexpected code %li.", j->url, status));
         }
 
+        if (j->state == PULL_JOB_ANALYZING) {
+                /* When curl finished the download while we were still looking for a compression magic
+                 * header the content isn't compressed but should be written out as is. */
+                assert(result == CURLE_OK);
+
+                r = decompressor_force_off(&j->compress);
+                if (r < 0)
+                        return pull_job_finish(j, r);
+
+                r = pull_job_begin_running(j);
+                if (r < 0)
+                        return pull_job_finish(j, r);
+        }
+
         if (j->state != PULL_JOB_RUNNING)
                 return pull_job_finish(j, log_error_errno(SYNTHETIC_ERRNO(EIO), "Premature connection termination."));
 
@@ -483,20 +520,7 @@ static int pull_job_detect_compression(PullJob *j) {
 
         log_debug("Stream is compressed: %s", compression_to_string(compressor_type(j->compress)));
 
-        r = pull_job_open_disk(j);
-        if (r < 0)
-                return r;
-
-        /* Now, take the payload we read so far, and decompress it */
-        _cleanup_(iovec_done) struct iovec stub = TAKE_STRUCT(j->payload);
-
-        j->state = PULL_JOB_RUNNING;
-
-        r = pull_job_write_compressed(j, &stub);
-        if (r < 0)
-                return r;
-
-        return 0;
+        return pull_job_begin_running(j);
 }
 
 static size_t pull_job_write_callback(void *contents, size_t size, size_t nmemb, void *userdata) {
index 0e1c9afa837fb9bcb46f46726337457cf58ecbbb..21a3ea00a59046b745a05038d2b21c0621f8cfe3 100755 (executable)
@@ -552,4 +552,28 @@ EOF
 done
 done
 
+# Make sure the processing of compressed streams still handles uncompressed streams shorter than
+# COMPRESSION_MAGIC_BYTES_MAX correctly.
+rm -rf "$CONFIGDIR" "$WORKDIR/blobs"
+mkdir -p "$CONFIGDIR" "$WORKDIR/blobs"
+printf 'xx' >"$WORKDIR/source/tiny-v1.bin"
+(cd "$WORKDIR/source" && sha256sum tiny-v1.bin >SHA256SUMS)
+cat >"$CONFIGDIR/01-tiny-url.transfer" <<EOF
+[Source]
+Type=url-file
+Path=file://$WORKDIR/source
+MatchPattern=tiny-@v.bin
+
+[Target]
+Type=regular-file
+Path=$WORKDIR/blobs
+MatchPattern=tiny-@v.bin
+InstancesMax=1
+EOF
+"$SYSUPDATE" --verify=no update
+cmp "$WORKDIR/source/tiny-v1.bin" "$WORKDIR/blobs/tiny-v1.bin"
+rm "$CONFIGDIR/01-tiny-url.transfer"
+rm "$WORKDIR/source/tiny-v1.bin"
+rm "$WORKDIR/source/SHA256SUMS"
+
 touch /testok