From: Michael Tremer Date: Wed, 18 Oct 2023 09:50:55 +0000 (+0000) Subject: downloader: Add support for uploading files X-Git-Tag: 0.9.30~1451 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fcb74f5031d76e82a1e1cf963b1acee761065f46;p=pakfire.git downloader: Add support for uploading files Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/downloader.c b/src/libpakfire/downloader.c index f0a515637..1002e102d 100644 --- a/src/libpakfire/downloader.c +++ b/src/libpakfire/downloader.c @@ -70,6 +70,12 @@ struct pakfire_transfer { // POST MIME Object curl_mime* mime; + // Transfer direction + enum { + PAKFIRE_TRANSFER_DOWNLOAD = 0, + PAKFIRE_TRANSFER_UPLOAD = 1, + } direction; + // Size size_t expected_size; size_t transferred; @@ -288,6 +294,24 @@ static int debug_callback(CURL *handle, curl_infotype type, } #endif +static size_t pakfire_downloader_transfer_read(char* data, size_t size, size_t nmemb, void* p) { + struct pakfire_transfer* transfer = p; + + return fread(data, size, nmemb, transfer->f); +} + +static int pakfire_downloader_transfer_seek(void* p, curl_off_t offset, int origin) { + struct pakfire_transfer* transfer = p; + int r; + + // Perform the seek + r = fseek(transfer->f, (long)offset, origin); + if (r < 0) + return CURL_SEEKFUNC_CANTSEEK; + + return CURL_SEEKFUNC_OK; +} + static size_t pakfire_downloader_transfer_write( char* data, size_t size, size_t nmemb, void* p) { struct pakfire_transfer* transfer = p; @@ -348,11 +372,21 @@ static int pakfire_downloader_transfer_setup( // Follow any redirects curl_easy_setopt(transfer->handle, CURLOPT_FOLLOWLOCATION, 1); + // Read any data from a callback function + curl_easy_setopt(transfer->handle, + CURLOPT_READFUNCTION, pakfire_downloader_transfer_read); + curl_easy_setopt(transfer->handle, CURLOPT_READDATA, transfer); + // Write all data to the callback function curl_easy_setopt(transfer->handle, CURLOPT_WRITEFUNCTION, pakfire_downloader_transfer_write); curl_easy_setopt(transfer->handle, CURLOPT_WRITEDATA, transfer); + // Register the seek callback + curl_easy_setopt(transfer->handle, + CURLOPT_SEEKFUNCTION, pakfire_downloader_transfer_seek); + curl_easy_setopt(transfer->handle, CURLOPT_SEEKDATA, transfer); + // Success r = 0; @@ -601,6 +635,32 @@ int pakfire_downloader_transfer_set_output(struct pakfire_transfer* transfer, FI return 0; } +int pakfire_downloader_transfer_set_input(struct pakfire_transfer* transfer, FILE* f) { + struct stat stat; + int r; + + // Fetch the file descriptor + const int fd = fileno(f); + + // Change direction + transfer->direction = PAKFIRE_TRANSFER_UPLOAD; + + // Store the file handle + transfer->f = f; + + // Try to find the upload size + if (fd > 0) { + r = fstat(fd, &stat); + if (r) + return 0; + + // Store the expected filesize + transfer->expected_size = stat.st_size; + } + + return 0; +} + int pakfire_downloader_transfer_set_target( struct pakfire_transfer* transfer, const char* path) { return pakfire_string_set(transfer->path, path); @@ -1050,6 +1110,31 @@ static int pakfire_downloader_transfer_prepare(struct pakfire_downloader* downlo } } + // Set special options for direction + switch (transfer->direction) { + case PAKFIRE_TRANSFER_DOWNLOAD: + break; + + case PAKFIRE_TRANSFER_UPLOAD: + // Let cURL know that we are uploading things + r = curl_easy_setopt(transfer->handle, CURLOPT_UPLOAD, 1L); + if (r) { + CTX_ERROR(downloader->ctx, "Could not enable upload\n"); + return r; + } + + // Tell it the expected upload size + if (transfer->expected_size) { + r = curl_easy_setopt(transfer->handle, + CURLOPT_INFILESIZE_LARGE, (curl_off_t)transfer->expected_size); + if (r) { + CTX_ERROR(downloader->ctx, "Could not set upload size\n"); + return r; + } + } + break; + } + // If we do not have an output file, we will create a temporary file if (!transfer->f) { r = pakfire_downloader_transfer_prepare_tmpfile(transfer); diff --git a/src/libpakfire/include/pakfire/downloader.h b/src/libpakfire/include/pakfire/downloader.h index 93d140f2c..3f236e96b 100644 --- a/src/libpakfire/include/pakfire/downloader.h +++ b/src/libpakfire/include/pakfire/downloader.h @@ -60,6 +60,7 @@ int pakfire_downloader_transfer_verify_digest( int pakfire_downloader_transfer_add_param(struct pakfire_transfer* transfer, const char* key, const char* format, ...) __attribute__((format(printf, 3, 4))); int pakfire_downloader_transfer_set_output(struct pakfire_transfer* transfer, FILE* f); +int pakfire_downloader_transfer_set_input(struct pakfire_transfer* transfer, FILE* f); int pakfire_downloader_transfer_set_target(struct pakfire_transfer* transfer, const char* path); int pakfire_downloader_transfer_run(struct pakfire_transfer* transfer, int flags);