/**************************************************************/ /* tpax: a topological pax implementation */ /* Copyright (C) 2020--2021 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ /**************************************************************/ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #define PPRIX64 "%"PRIx64 /* 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; void * addr; char tmplate[128]; /* 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 */ addr = tmplate; memset(tmplate,0,sizeof(tmplate)); snprintf(tmplate,sizeof(tmplate), "/tmp/" ".tpax.tmpfile" ".time."PPRIX64 ".salt.%p" ".pid.%d" ".XXXXXXXXXXXX", time(0), addr, getpid()); return tpax_mkostemp(tmplate); }