blob: 709e4840d07a8a80145920aa4f65a0668af5a272 [file] [log] [blame]
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Copyright (C) 2025 Intel Corporation.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <shared/macro.h>
#include <shared/missing.h>
#include <shared/tmpfile-util.h>
#include <shared/util.h>
FILE *tmpfile_openat(int dirfd, mode_t mode, struct tmpfile *file)
{
const char *tmpname_tmpl = "/tmpfileXXXXXX";
const char *tmpname;
char tmpfile_path[PATH_MAX];
int fd, n;
FILE *fp;
n = fd_lookup_path(dirfd, tmpfile_path, sizeof(tmpfile_path));
if (n < 0)
goto create_fail;
if (n + strlen(tmpname_tmpl) + 1 > sizeof(tmpfile_path))
goto create_fail;
memcpy(tmpfile_path + n, tmpname_tmpl, strlen(tmpname_tmpl) + 1);
fd = mkstemp(tmpfile_path);
if (fd < 0)
goto create_fail;
if (fchmod(fd, mode) < 0)
goto checkout_fail;
fp = fdopen(fd, "wb");
if (fp == NULL)
goto checkout_fail;
tmpname = basename(tmpfile_path);
memcpy(file->tmpname, tmpname, strlen(tmpname) + 1);
file->dirfd = dirfd;
file->fd = fd;
return fp;
checkout_fail:
close(fd);
remove(tmpfile_path);
create_fail:
return NULL;
}
int tmpfile_publish(struct tmpfile *file, const char *targetname)
{
if (renameat(file->dirfd, file->tmpname, file->dirfd, targetname) != 0)
return -errno;
file->fd = -1;
file->dirfd = -1;
memset(file->tmpname, 0, sizeof(file->tmpname));
return 0;
}
void tmpfile_release(struct tmpfile *file)
{
unlinkat(file->dirfd, file->tmpname, 0);
file->fd = -1;
file->dirfd = -1;
file->tmpname[0] = '\0';
}