Blame src/internal/treebnf_tmpfile_impl.c

02e59c
/**************************************************************/
02e59c
/*  treebnf: a tree oriented bnf library                      */
02e59c
/*  Copyright (C) 2024  SysDeer Technologies, LLC             */
02e59c
/*  Released under GPLv2 and GPLv3; see COPYING.TREEBNF.      */
02e59c
/**************************************************************/
02e59c
02e59c
#define _GNU_SOURCE
02e59c
#include <time.h>
02e59c
#include <fcntl.h>
02e59c
#include <limits.h>
02e59c
#include <stdlib.h>
02e59c
#include <unistd.h>
02e59c
#include <string.h>
02e59c
#include <stdio.h>
02e59c
#include <inttypes.h>
02e59c
02e59c
#include "treebnf_visibility_impl.h"
02e59c
02e59c
#define PPRIX64 "%"PRIx64
02e59c
02e59c
/* mkostemp might be guarded by non-standard macros */
02e59c
/* unless HAVE_NO_MKOSTEMP, assume it is available */
02e59c
extern int mkstemp(char *);
02e59c
extern int mkostemp(char *, int);
02e59c
02e59c
/* __fs_tmpfile() atomically provides a private tmpfile */
02e59c
static int tbnf_tmpfile_by_framework(void)
02e59c
{
02e59c
#ifdef _MIDIPIX_ABI
02e59c
	extern int __fs_tmpfile(int);
02e59c
	return __fs_tmpfile(O_CLOEXEC);
02e59c
#else
02e59c
	return (-1);
02e59c
#endif
02e59c
}
02e59c
02e59c
/* O_TMPFILE atomically provides a private tmpfile */
02e59c
static int tbnf_tmpfile_by_kernel(void)
02e59c
{
02e59c
#ifdef O_TMPFILE
02e59c
	return openat(AT_FDCWD,"/tmp",O_RDWR|O_TMPFILE|O_CLOEXEC,0);
02e59c
#else
02e59c
	return (-1);
02e59c
#endif
02e59c
}
02e59c
02e59c
/* mk{o}stemp() provides a non-private tmpfile */
02e59c
static int tbnf_mkostemp(char * tmplate)
02e59c
{
02e59c
	int fd;
02e59c
#ifdef HAVE_NO_MKOSTEMP
02e59c
	if ((fd = mkstemp(tmplate)) >= 0)
02e59c
		fcntl(fd,F_SETFD,FD_CLOEXEC);
02e59c
#else
02e59c
	fd = mkostemp(tmplate,O_CLOEXEC);
02e59c
#endif
02e59c
	return fd;
02e59c
}
02e59c
02e59c
tbnf_hidden int tbnf_tmpfile(void)
02e59c
{
02e59c
	int             fd;
02e59c
	void *          addr;
02e59c
	char            tmplate[128];
02e59c
02e59c
	/* try with __fs_tmpfile() */
02e59c
	if ((fd = tbnf_tmpfile_by_framework()) >= 0)
02e59c
		return fd;
02e59c
02e59c
	/* try with O_TMPFILE */
02e59c
	if ((fd = tbnf_tmpfile_by_kernel()) >= 0)
02e59c
		return fd;
02e59c
02e59c
	/* fallback to mk{o}stemp */
02e59c
	addr = tmplate;
02e59c
	memset(tmplate,0,sizeof(tmplate));
02e59c
	snprintf(tmplate,sizeof(tmplate),
02e59c
		"/tmp/"
02e59c
		".treebnf.tmpfile"
02e59c
		".time."PPRIX64
02e59c
		".salt.%p"
02e59c
		".pid.%d"
02e59c
		".XXXXXXXXXXXX",
02e59c
		time(0),
02e59c
		addr,
02e59c
		getpid());
02e59c
02e59c
	return tbnf_mkostemp(tmplate);
02e59c
}