]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pull-job: optionally take expected content length and compare it with what we are...
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Nov 2025 15:58:09 +0000 (16:58 +0100)
committerLennart Poettering <lennart@poettering.net>
Sat, 8 Nov 2025 08:27:46 +0000 (09:27 +0100)
src/import/pull-job.c
src/import/pull-job.h

index 6c7b328a0c481bb9631e9e636f7112886dd3b5e2..9459a89ceaaab8423ca57ccdaa1fdf7f95ec9c5e 100644 (file)
@@ -93,6 +93,7 @@ static int pull_job_restart(PullJob *j, const char *new_url) {
         j->etag_exists = false;
         j->mtime = 0;
         j->checksum = mfree(j->checksum);
+        j->expected_content_length = UINT64_MAX;
 
         curl_glue_remove_and_free(j->glue, j->curl);
         j->curl = NULL;
@@ -114,6 +115,15 @@ static int pull_job_restart(PullJob *j, const char *new_url) {
         return 0;
 }
 
+static uint64_t pull_job_content_length_effective(PullJob *j) {
+        assert(j);
+
+        if (j->expected_content_length != UINT64_MAX)
+                return j->expected_content_length;
+
+        return j->content_length;
+}
+
 void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
         PullJob *j = NULL;
         char *scheme = NULL;
@@ -214,8 +224,9 @@ void pull_job_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result) {
                 goto finish;
         }
 
-        if (j->content_length != UINT64_MAX &&
-            j->content_length != j->written_compressed) {
+        uint64_t cl = pull_job_content_length_effective(j);
+        if (cl != UINT64_MAX &&
+            cl != j->written_compressed) {
                 r = log_error_errno(SYNTHETIC_ERRNO(EIO), "Download truncated.");
                 goto finish;
         }
@@ -374,8 +385,9 @@ static int pull_job_write_compressed(PullJob *j, void *p, size_t sz) {
         if (j->written_compressed + sz > j->compressed_max)
                 return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing.");
 
-        if (j->content_length != UINT64_MAX &&
-            j->written_compressed + sz > j->content_length)
+        uint64_t cl = pull_job_content_length_effective(j);
+        if (cl != UINT64_MAX &&
+            j->written_compressed + sz > cl)
                 return log_error_errno(SYNTHETIC_ERRNO(EFBIG),
                                        "Content length incorrect.");
 
@@ -589,6 +601,12 @@ static size_t pull_job_header_callback(void *contents, size_t size, size_t nmemb
                                 goto fail;
                         }
 
+                        if (j->expected_content_length != UINT64_MAX &&
+                            j->expected_content_length != j->content_length) {
+                                r = log_error_errno(SYNTHETIC_ERRNO(EPROTO), "Content does not have expected size.");
+                                goto fail;
+                        }
+
                         log_info("Downloading %s for %s.", FORMAT_BYTES(j->content_length), j->url);
                 }
 
@@ -691,6 +709,7 @@ int pull_job_new(
                 .url = TAKE_PTR(u),
                 .offset = UINT64_MAX,
                 .sync = true,
+                .expected_content_length = UINT64_MAX,
         };
 
         *ret = TAKE_PTR(j);
index b39e11929fc6c79c47c4db224682b57d65aa5c88..34156e9dd6fc25985fe053d381f0c60ed0572594 100644 (file)
@@ -58,6 +58,8 @@ typedef struct PullJob {
         uint64_t uncompressed_max;
         uint64_t compressed_max;
 
+        uint64_t expected_content_length;
+
         uint8_t *payload;
         size_t payload_size;