char url[PATH_MAX];
char title[NAME_MAX];
char path[PATH_MAX];
+ char tmpfile[PATH_MAX];
int tries;
// POST MIME Object
};
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);
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;
// 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
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;