diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/tpax_tmpfile_impl.c | 74 | ||||
-rw-r--r-- | src/internal/tpax_tmpfile_impl.h | 6 |
2 files changed, 80 insertions, 0 deletions
diff --git a/src/internal/tpax_tmpfile_impl.c b/src/internal/tpax_tmpfile_impl.c new file mode 100644 index 0000000..0c0bcc1 --- /dev/null +++ b/src/internal/tpax_tmpfile_impl.c @@ -0,0 +1,74 @@ +/******************************************************/ +/* tpax: a topological pax implementation */ +/* Copyright (C) 2020 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.TPAX. */ +/******************************************************/ + +#define _GNU_SOURCE +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +/* 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 open("/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); +} diff --git a/src/internal/tpax_tmpfile_impl.h b/src/internal/tpax_tmpfile_impl.h new file mode 100644 index 0000000..f146326 --- /dev/null +++ b/src/internal/tpax_tmpfile_impl.h @@ -0,0 +1,6 @@ +#ifndef TPAX_TMPFILE_IMPL_H +#define TPAX_TMPFILE_IMPL_H + +int tpax_tmpfile(void); + +#endif |