From: Kai Lüke Date: Fri, 15 May 2026 14:49:44 +0000 (+0900) Subject: import: Move pull_job_curl_on_finished after pull_job_open_disk X-Git-Tag: v261-rc1~110^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=326ab6d43029b6aaf46ab4a246aa0e43022a276d;p=thirdparty%2Fsystemd.git import: Move pull_job_curl_on_finished after pull_job_open_disk To call into pull_job_write_(un)compressed and pull_job_open_disk from pull_job_curl_on_finished it has to be defined after them. This is in preparation for a bug fix for small files where we need to leave the compression analysis state to finish the download successfully. --- diff --git a/src/import/pull-job.c b/src/import/pull-job.c index 5b8aa6da269..2dc960c3929 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -163,6 +163,142 @@ static uint64_t pull_job_content_length_effective(PullJob *j) { return j->content_length; } +static int pull_job_write_uncompressed(const void *p, size_t sz, void *userdata) { + PullJob *j = ASSERT_PTR(userdata); + bool too_much = false; + int r; + + assert(p); + assert(sz > 0); + + if (j->written_uncompressed > UINT64_MAX - sz) + return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow"); + + if (j->written_uncompressed >= j->uncompressed_max) { + too_much = true; + goto finish; + } + + if (j->written_uncompressed + sz > j->uncompressed_max) { + too_much = true; + sz = j->uncompressed_max - j->written_uncompressed; /* since we have the data in memory + * already, we might as well write it to + * disk to the max */ + } + + if (j->disk_fd >= 0) { + + if (S_ISREG(j->disk_stat.st_mode) && j->offset == UINT64_MAX) { + ssize_t n; + + n = sparse_write(j->disk_fd, p, sz, 64); + if (n < 0) + return log_error_errno((int) n, "Failed to write file: %m"); + if ((size_t) n < sz) + return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write"); + } else { + r = loop_write(j->disk_fd, p, sz); + if (r < 0) + return log_error_errno(r, "Failed to write file: %m"); + } + } + + if (j->disk_fd < 0 || j->force_memory) { + uint8_t *a = j->payload.iov_base; + + if (!GREEDY_REALLOC(a, j->payload.iov_len + sz + 1)) + return log_oom(); + + *((uint8_t*) mempcpy(a + j->payload.iov_len, p, sz)) = 0; + j->payload.iov_base = a; + j->payload.iov_len += sz; + } + + j->written_uncompressed += sz; + +finish: + if (too_much) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing."); + + return 0; +} + +static int pull_job_write_compressed(PullJob *j, const struct iovec *data) { + int r; + + assert(j); + assert(iovec_is_valid(data)); + + if (!iovec_is_set(data)) + return 0; + + if (j->written_compressed + data->iov_len < j->written_compressed) + return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow"); + + if (j->written_compressed + data->iov_len > j->compressed_max) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing."); + + uint64_t cl = pull_job_content_length_effective(j); + if (cl != UINT64_MAX && + j->written_compressed + data->iov_len > cl) + return log_error_errno(SYNTHETIC_ERRNO(EFBIG), + "Content length incorrect."); + + if (j->checksum_ctx) { + r = sym_EVP_DigestUpdate(j->checksum_ctx, data->iov_base, data->iov_len); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Could not hash chunk."); + } + + r = decompressor_push(j->compress, data->iov_base, data->iov_len, pull_job_write_uncompressed, j); + if (r < 0) + return r; + + j->written_compressed += data->iov_len; + + return 0; +} + +static int pull_job_open_disk(PullJob *j) { + int r; + + assert(j); + + if (j->on_open_disk) { + r = j->on_open_disk(j); + if (r < 0) + return r; + } + + if (j->disk_fd >= 0) { + if (fstat(j->disk_fd, &j->disk_stat) < 0) + return log_error_errno(errno, "Failed to stat disk file: %m"); + + if (j->offset != UINT64_MAX) { + if (lseek(j->disk_fd, j->offset, SEEK_SET) < 0) + return log_error_errno(errno, "Failed to seek on file descriptor: %m"); + } + } + + if (j->calc_checksum) { + r = dlopen_libcrypto(LOG_ERR); + if (r < 0) + return r; + + j->checksum_ctx = sym_EVP_MD_CTX_new(); + if (!j->checksum_ctx) + return log_oom(); + + r = sym_EVP_DigestInit_ex(j->checksum_ctx, sym_EVP_sha256(), NULL); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EIO), + "Failed to initialize hash context."); + } + + 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; @@ -334,142 +470,6 @@ static int pull_job_curl_on_finished(CurlSlot *slot, CURL *curl, CURLcode result return pull_job_finish(j, 0); } -static int pull_job_write_uncompressed(const void *p, size_t sz, void *userdata) { - PullJob *j = ASSERT_PTR(userdata); - bool too_much = false; - int r; - - assert(p); - assert(sz > 0); - - if (j->written_uncompressed > UINT64_MAX - sz) - return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow"); - - if (j->written_uncompressed >= j->uncompressed_max) { - too_much = true; - goto finish; - } - - if (j->written_uncompressed + sz > j->uncompressed_max) { - too_much = true; - sz = j->uncompressed_max - j->written_uncompressed; /* since we have the data in memory - * already, we might as well write it to - * disk to the max */ - } - - if (j->disk_fd >= 0) { - - if (S_ISREG(j->disk_stat.st_mode) && j->offset == UINT64_MAX) { - ssize_t n; - - n = sparse_write(j->disk_fd, p, sz, 64); - if (n < 0) - return log_error_errno((int) n, "Failed to write file: %m"); - if ((size_t) n < sz) - return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write"); - } else { - r = loop_write(j->disk_fd, p, sz); - if (r < 0) - return log_error_errno(r, "Failed to write file: %m"); - } - } - - if (j->disk_fd < 0 || j->force_memory) { - uint8_t *a = j->payload.iov_base; - - if (!GREEDY_REALLOC(a, j->payload.iov_len + sz + 1)) - return log_oom(); - - *((uint8_t*) mempcpy(a + j->payload.iov_len, p, sz)) = 0; - j->payload.iov_base = a; - j->payload.iov_len += sz; - } - - j->written_uncompressed += sz; - -finish: - if (too_much) - return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing."); - - return 0; -} - -static int pull_job_write_compressed(PullJob *j, const struct iovec *data) { - int r; - - assert(j); - assert(iovec_is_valid(data)); - - if (!iovec_is_set(data)) - return 0; - - if (j->written_compressed + data->iov_len < j->written_compressed) - return log_error_errno(SYNTHETIC_ERRNO(EOVERFLOW), "File too large, overflow"); - - if (j->written_compressed + data->iov_len > j->compressed_max) - return log_error_errno(SYNTHETIC_ERRNO(EFBIG), "File overly large, refusing."); - - uint64_t cl = pull_job_content_length_effective(j); - if (cl != UINT64_MAX && - j->written_compressed + data->iov_len > cl) - return log_error_errno(SYNTHETIC_ERRNO(EFBIG), - "Content length incorrect."); - - if (j->checksum_ctx) { - r = sym_EVP_DigestUpdate(j->checksum_ctx, data->iov_base, data->iov_len); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), - "Could not hash chunk."); - } - - r = decompressor_push(j->compress, data->iov_base, data->iov_len, pull_job_write_uncompressed, j); - if (r < 0) - return r; - - j->written_compressed += data->iov_len; - - return 0; -} - -static int pull_job_open_disk(PullJob *j) { - int r; - - assert(j); - - if (j->on_open_disk) { - r = j->on_open_disk(j); - if (r < 0) - return r; - } - - if (j->disk_fd >= 0) { - if (fstat(j->disk_fd, &j->disk_stat) < 0) - return log_error_errno(errno, "Failed to stat disk file: %m"); - - if (j->offset != UINT64_MAX) { - if (lseek(j->disk_fd, j->offset, SEEK_SET) < 0) - return log_error_errno(errno, "Failed to seek on file descriptor: %m"); - } - } - - if (j->calc_checksum) { - r = dlopen_libcrypto(LOG_ERR); - if (r < 0) - return r; - - j->checksum_ctx = sym_EVP_MD_CTX_new(); - if (!j->checksum_ctx) - return log_oom(); - - r = sym_EVP_DigestInit_ex(j->checksum_ctx, sym_EVP_sha256(), NULL); - if (r == 0) - return log_error_errno(SYNTHETIC_ERRNO(EIO), - "Failed to initialize hash context."); - } - - return 0; -} - static int pull_job_detect_compression(PullJob *j) { int r;