]> git.ipfire.org Git - pakfire.git/commitdiff
xfer: Implement another version for tmpfiles
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Nov 2023 20:09:22 +0000 (20:09 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 1 Nov 2023 20:09:22 +0000 (20:09 +0000)
O_TMPFILE requires filesystem support which is sadly not available for
NFS.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/xfer.c

index c6822b90cb9f84bdf70ddbcfe6ac8af7c3a222da..c532a0d90d34ae4eaa283c019c03c5c0cee24a7d 100644 (file)
@@ -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;