#############################################################################*/
#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
#include <sys/queue.h>
#include <utime.h>
char url[PATH_MAX];
char title[NAME_MAX];
char path[PATH_MAX];
- pakfire_xfer_flags_t flags;
int tries;
// POST MIME Object
size_t expected_size;
size_t xferred;
- // Temporary file
- char tempfile[PATH_MAX];
-
// File handles for streams
FILE* fin;
FILE* fout;
};
static void pakfire_xfer_free(struct pakfire_xfer* xfer) {
- if (xfer->handle)
- curl_easy_cleanup(xfer->handle);
-
- // Unlink the temporary file
- if (*xfer->tempfile)
- unlink(xfer->tempfile);
-
// Close any streams
if (xfer->fin)
fclose(xfer->fin);
if (xfer->evp)
EVP_MD_CTX_free(xfer->evp);
+ // cURL stuff
+ if (xfer->handle)
+ curl_easy_cleanup(xfer->handle);
if (xfer->headers)
curl_slist_free_all(xfer->headers);
if (xfer->mime)
pakfire_mirrorlist_unref(xfer->mirrors);
if (xfer->progress)
pakfire_progress_unref(xfer->progress);
+ if (xfer->client)
+ pakfire_httpclient_unref(xfer->client);
if (xfer->ctx)
pakfire_ctx_unref(xfer->ctx);
}
}
+ // If there is no output steam, we just pretent that we have consumed the data
+ if (!xfer->fin)
+ return nmemb;
+
// Write everything to the allocated file descriptor
return fwrite(data, size, nmemb, xfer->fin);
}
return 0;
}
-int pakfire_xfer_set_target(
- struct pakfire_xfer* xfer, const char* path) {
- return pakfire_string_set(xfer->path, path);
+static int pakfire_xfer_allocate_tmpfile(struct pakfire_xfer* xfer, const char* path) {
+ char dirname[PATH_MAX];
+ FILE* f = NULL;
+ int fd = -1;
+ int r;
+
+ // Find the directory name
+ r = pakfire_path_dirname(dirname, path);
+ if (r)
+ return r;
+
+ // Ensure the directory exists
+ r = pakfire_mkdir(dirname, 0755);
+ if (r)
+ return r;
+
+ // Open a new temporary file
+ fd = open(dirname, O_TMPFILE|O_RDWR, 0600);
+ if (fd < 0) {
+ CTX_ERROR(xfer->ctx, "Could not open temporary file in %s: %s\n",
+ dirname, strerror(errno));
+ return -errno;
+ }
+
+ // Turn the file descriptor into a FILE handle
+ f = fdopen(fd, "w+");
+ if (!f)
+ return -errno;
+
+ // Set the handle as output
+ return pakfire_xfer_set_output(xfer, f);
+}
+
+int pakfire_xfer_set_output_path(struct pakfire_xfer* xfer, const char* path) {
+ int r;
+
+ // Store the output path
+ r = pakfire_string_set(xfer->path, path);
+ if (r)
+ return r;
+
+ // Allocate a temporary file
+ r = pakfire_xfer_allocate_tmpfile(xfer, path);
+ if (r)
+ return r;
+
+ return 0;
}
int pakfire_xfer_auth(struct pakfire_xfer* xfer) {
CTX_DEBUG(xfer->ctx, "Download successful. Storing result in %s\n", xfer->path);
+ int fd = fileno(xfer->fin);
+
// Make sure the parent directory exists
r = pakfire_mkparentdir(xfer->path, 0755);
if (r)
unlink(xfer->path);
// Move the temporary file to its destination
- r = link(xfer->tempfile, xfer->path);
+ r = linkat(fd, "", AT_FDCWD, xfer->path, AT_EMPTY_PATH);
if (r) {
CTX_ERROR(xfer->ctx, "Could not link destination file %s: %m\n",
xfer->path);
// Filetime
curl_easy_getinfo(xfer->handle, CURLINFO_FILETIME_T, ×.modtime);
- if (times.modtime) {
+ if (times.modtime > 0) {
r = utime(xfer->path, ×);
if (r)
CTX_ERROR(xfer->ctx, "Could not set mtime of %s: %m\n", xfer->path);
return pakfire_progress_update(xfer->progress, xfer->xferred);
}
-
static int pakfire_xfer_prepare_progress(struct pakfire_xfer* xfer,
struct pakfire_progress* parent, int flags) {
const char* title = NULL;
return 0;
}
-
-static int pakfire_xfer_prepare_tmpfile(struct pakfire_xfer* xfer) {
- char path[PATH_MAX] = PAKFIRE_TMP_DIR "/pakfire-download.XXXXXX";
- FILE* f = NULL;
- int r;
-
- // Allocate a temporary file
- f = pakfire_mktemp(path, 0600);
- if (!f)
- return -errno;
-
- // Set this as output
- r = pakfire_xfer_set_output(xfer, f);
- if (r)
- return r;
-
- // Store the path to the temporary file
- return pakfire_string_set(xfer->tempfile, path);
-}
-
static int pakfire_xfer_prepare_url(struct pakfire_xfer* xfer) {
int r;
}
}
- // If we do not have an output file, we will create a temporary file
- if (!xfer->fout && !xfer->fin) {
- r = pakfire_xfer_prepare_tmpfile(xfer);
- if (r) {
- CTX_ERROR(xfer->ctx, "Could not open a temporary file: %s\n", strerror(-r));
- return r;
- }
- }
-
// Authentication
if (xfer->auth) {
// Request SPNEGO