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