diff options
Diffstat (limited to 'src/internal')
-rw-r--r-- | src/internal/slibtool_tmpfile_impl.c | 89 | ||||
-rw-r--r-- | src/internal/slibtool_tmpfile_impl.h | 6 |
2 files changed, 95 insertions, 0 deletions
diff --git a/src/internal/slibtool_tmpfile_impl.c b/src/internal/slibtool_tmpfile_impl.c new file mode 100644 index 0000000..52c7317 --- /dev/null +++ b/src/internal/slibtool_tmpfile_impl.c @@ -0,0 +1,89 @@ +/*******************************************************************/ +/* slibtool: a strong libtool implementation, written in C */ +/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */ +/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */ +/*******************************************************************/ + +#define _GNU_SOURCE +#include <time.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <inttypes.h> + +#include "slibtool_visibility_impl.h" + +#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 slbt_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 slbt_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 slbt_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; +} + +slbt_hidden int slbt_tmpfile(void) +{ + int fd; + void * addr; + char tmplate[128]; + + /* try with __fs_tmpfile() */ + if ((fd = slbt_tmpfile_by_framework()) >= 0) + return fd; + + /* try with O_TMPFILE */ + if ((fd = slbt_tmpfile_by_kernel()) >= 0) + return fd; + + /* fallback to mk{o}stemp */ + addr = tmplate; + memset(tmplate,0,sizeof(tmplate)); + snprintf(tmplate,sizeof(tmplate), + "/tmp/" + ".slibtool.tmpfile" + ".time."PPRIX64 + ".salt.%p" + ".pid.%d" + ".XXXXXXXXXXXX", + time(0), + addr, + getpid()); + + return slbt_mkostemp(tmplate); +} diff --git a/src/internal/slibtool_tmpfile_impl.h b/src/internal/slibtool_tmpfile_impl.h new file mode 100644 index 0000000..cd6a02b --- /dev/null +++ b/src/internal/slibtool_tmpfile_impl.h @@ -0,0 +1,6 @@ +#ifndef SLIBTOOL_TMPFILE_IMPL_H +#define SLIBTOOL_TMPFILE_IMPL_H + +int slbt_tmpfile(void); + +#endif |