Blame src/internal/tpax_tmpfile_impl.c

4ebdc3
/******************************************************/
4ebdc3
/*  tpax: a topological pax implementation            */
4ebdc3
/*  Copyright (C) 2020  Z. Gilboa                     */
4ebdc3
/*  Released under GPLv2 and GPLv3; see COPYING.TPAX. */
4ebdc3
/******************************************************/
4ebdc3
4ebdc3
#define _GNU_SOURCE
4ebdc3
#include <fcntl.h>
559cff
#include <limits.h>
4ebdc3
#include <stdlib.h>
4ebdc3
#include <unistd.h>
4ebdc3
#include <string.h>
4ebdc3
#include <stdio.h>
4ebdc3
4ebdc3
/* mkostemp might be guarded by non-standard macros */
4ebdc3
/* unless HAVE_NO_MKOSTEMP, assume it is available */
4ebdc3
extern int mkstemp(char *);
4ebdc3
extern int mkostemp(char *, int);
4ebdc3
4ebdc3
/* __fs_tmpfile() atomically provides a private tmpfile */
4ebdc3
static int tpax_tmpfile_by_framework(void)
4ebdc3
{
4ebdc3
#ifdef _MIDIPIX_ABI
4ebdc3
	extern int __fs_tmpfile(int);
4ebdc3
	return __fs_tmpfile(O_CLOEXEC);
4ebdc3
#else
4ebdc3
	return (-1);
4ebdc3
#endif
4ebdc3
}
4ebdc3
4ebdc3
/* O_TMPFILE atomically provides a private tmpfile */
4ebdc3
static int tpax_tmpfile_by_kernel(void)
4ebdc3
{
4ebdc3
#ifdef O_TMPFILE
4ebdc3
	return open("/tmp",O_RDWR|O_TMPFILE|O_CLOEXEC,0);
4ebdc3
#else
4ebdc3
	return (-1);
4ebdc3
#endif
4ebdc3
}
4ebdc3
4ebdc3
/* mk{o}stemp() provides a non-private tmpfile */
4ebdc3
static int tpax_mkostemp(char * tmplate)
4ebdc3
{
4ebdc3
	int fd;
4ebdc3
#ifdef HAVE_NO_MKOSTEMP
4ebdc3
	if ((fd = mkstemp(tmplate)) >= 0)
4ebdc3
		fcntl(fd,F_SETFD,FD_CLOEXEC);
4ebdc3
#else
4ebdc3
	fd = mkostemp(tmplate,O_CLOEXEC);
4ebdc3
#endif
4ebdc3
	return fd;
4ebdc3
}
4ebdc3
4ebdc3
int tpax_tmpfile(void)
4ebdc3
{
4ebdc3
	int             fd;
4ebdc3
	unsigned        seed;
4ebdc3
	char            tmplate[64];
4ebdc3
4ebdc3
	/* try with __fs_tmpfile() */
4ebdc3
	if ((fd = tpax_tmpfile_by_framework()) >= 0)
4ebdc3
		return fd;
4ebdc3
4ebdc3
	/* try with O_TMPFILE */
4ebdc3
	if ((fd = tpax_tmpfile_by_kernel()) >= 0)
4ebdc3
		return fd;
4ebdc3
4ebdc3
	/* fallback to mk{o}stemp */
4ebdc3
	seed = getpid();
4ebdc3
	memset(tmplate,0,sizeof(tmplate));
4ebdc3
	snprintf(tmplate,sizeof(tmplate),"/tmp/tpax_%d_%d_%d_XXXXXXXXXXXX",
4ebdc3
		getppid(),getpid(),rand_r(&seed));
4ebdc3
4ebdc3
	return tpax_mkostemp(tmplate);
4ebdc3
}