Bound FTP range transfers to requested size

This commit is contained in:
Mario Fetka
2026-07-14 17:26:14 +02:00
parent 4a80e32f3e
commit 9d8296bf66
2 changed files with 25 additions and 3 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(libprozilla VERSION 1.2.0 LANGUAGES C)
project(libprozilla VERSION 1.2.1 LANGUAGES C)
include(CTest)
+24 -2
View File
@@ -12,7 +12,9 @@ typedef struct {
CURL *curl;
int write_failed;
int require_partial_response;
int range_complete;
size_t bytes_written;
off_t expected_bytes;
} curl_write_context;
static CURLcode configure_curl(CURL *curl, connection_t *connection)
@@ -122,6 +124,20 @@ static size_t curl_write(void *data, size_t size, size_t count, void *opaque)
if (size != 0 && count > SIZE_MAX / size)
return 0;
bytes = size * count;
if (ctx->expected_bytes > 0)
{
off_t remaining = ctx->expected_bytes - (off_t) ctx->bytes_written;
if (remaining <= 0)
{
ctx->range_complete = 1;
return 0;
}
if ((uintmax_t) bytes > (uintmax_t) remaining)
{
bytes = (size_t) remaining;
ctx->range_complete = 1;
}
}
if (ctx->require_partial_response)
{
curl_easy_getinfo(ctx->curl, CURLINFO_RESPONSE_CODE, &response);
@@ -139,6 +155,8 @@ static size_t curl_write(void *data, size_t size, size_t count, void *opaque)
ctx->bytes_written += bytes;
connection_calc_ratebps(ctx->connection);
connection_throttle_bps(ctx->connection);
if (ctx->range_complete)
return 0;
return bytes;
}
@@ -146,7 +164,7 @@ static uerr_t curl_get_file(connection_t *connection)
{
CURL *curl = curl_easy_init();
CURLcode result;
curl_write_context ctx = { connection, curl, 0, 0, 0 };
curl_write_context ctx = { connection, curl, 0, 0, 0, 0, 0 };
char range[96];
long response = 0;
@@ -161,6 +179,8 @@ static uerr_t curl_get_file(connection_t *connection)
(intmax_t) connection->remote_startpos,
(intmax_t) (connection->remote_endpos - 1));
curl_easy_setopt(curl, CURLOPT_RANGE, range);
ctx.expected_bytes =
connection->remote_endpos - connection->remote_startpos;
if (connection->u.proto == URLHTTP
|| connection->u.proto == URLHTTPS)
ctx.require_partial_response = 1;
@@ -181,7 +201,9 @@ static uerr_t curl_get_file(connection_t *connection)
&& (off_t) ctx.bytes_written
!= connection->remote_endpos - connection->remote_startpos)
return READERR;
if (result == CURLE_OK && response < 400)
if ((ctx.expected_bytes > 0
&& (off_t) ctx.bytes_written == ctx.expected_bytes)
|| ((result == CURLE_OK || ctx.range_complete) && response < 400))
{
connection_change_status(connection, COMPLETED);
return HOK;