From: Michael Tremer Date: Wed, 1 Nov 2023 20:09:22 +0000 (+0000) Subject: xfer: Implement another version for tmpfiles X-Git-Tag: 0.9.30~1319 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8afe94b5dd93ad00f67c425466f94ac01dfa3aee;p=pakfire.git xfer: Implement another version for tmpfiles O_TMPFILE requires filesystem support which is sadly not available for NFS. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/xfer.c b/src/libpakfire/xfer.c index c6822b90c..c532a0d90 100644 --- a/src/libpakfire/xfer.c +++ b/src/libpakfire/xfer.c @@ -60,6 +60,7 @@ struct pakfire_xfer { char url[PATH_MAX]; char title[NAME_MAX]; char path[PATH_MAX]; + char tmpfile[PATH_MAX]; int tries; // POST MIME Object @@ -103,6 +104,10 @@ struct pakfire_xfer { }; static void pakfire_xfer_free(struct pakfire_xfer* xfer) { + // Unlink + if (*xfer->tmpfile) + unlink(xfer->tmpfile); + // Close any streams if (xfer->fin) fclose(xfer->fin); @@ -601,6 +606,27 @@ int pakfire_xfer_set_input(struct pakfire_xfer* xfer, FILE* f) { return 0; } +static int pakfire_xfer_allocate_tmpfile_legacy(struct pakfire_xfer* xfer, const char* path) { + FILE* f = NULL; + int r; + + // Compose the path + r = pakfire_string_format(xfer->tmpfile, "%s.XXXXXX", path); + if (r) + return r; + + // Create a temporary file + f = pakfire_mktemp(xfer->tmpfile, 0600); + if (!f) { + CTX_ERROR(xfer->ctx, "Could not open temporary file for %s: %s\n", + path, strerror(errno)); + return -errno; + } + + // Set the handle as output + return pakfire_xfer_set_output(xfer, f); +} + static int pakfire_xfer_allocate_tmpfile(struct pakfire_xfer* xfer, const char* path) { char dirname[PATH_MAX]; FILE* f = NULL; @@ -620,9 +646,16 @@ static int pakfire_xfer_allocate_tmpfile(struct pakfire_xfer* xfer, const char* // 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; + switch (errno) { + // Fall back to another way for filesystems that don't support O_TMPFILE + case ENOTSUP: + return pakfire_xfer_allocate_tmpfile_legacy(xfer, path); + + default: + 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 @@ -729,10 +762,18 @@ static int pakfire_xfer_save(struct pakfire_xfer* xfer) { unlink(xfer->path); // Move the temporary file to its destination - 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); - return r; + if (*xfer->tmpfile) { + r = link(xfer->tmpfile, xfer->path); + if (r) { + CTX_ERROR(xfer->ctx, "Could not link destination file %s: %m\n", xfer->path); + return r; + } + } else { + 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); + return r; + } } return 0;