This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Implement tmpfile with O_TMPFILE (bug 21530)
- From: Andreas Schwab <schwab at suse dot de>
- To: libc-alpha at sourceware dot org
- Date: Mon, 26 Jun 2017 13:47:38 +0200
- Subject: [PATCH] Implement tmpfile with O_TMPFILE (bug 21530)
- Authentication-results: sourceware.org; auth=none
If the kernel or the file system does not support O_TMPFILE fall back to
creating a temporary file based on tmpnam.
[BZ #21530]
* stdio-common/tmpfile.c (tmpfile) [O_TMPFILE]: Try opening an
unnamed file first.
---
stdio-common/tmpfile.c | 51 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 37 insertions(+), 14 deletions(-)
diff --git a/stdio-common/tmpfile.c b/stdio-common/tmpfile.c
index e6030be0af..5505d6f571 100644
--- a/stdio-common/tmpfile.c
+++ b/stdio-common/tmpfile.c
@@ -18,6 +18,8 @@
#include <fcntl.h>
#include <stdio.h>
+#include <string.h>
+#include <errno.h>
#include <unistd.h>
#include <iolibio.h>
@@ -27,30 +29,51 @@
#endif
-/* This returns a new stream opened on a temporary file (generated
- by tmpnam). The file is opened with mode "w+b" (binary read/write).
- If we couldn't generate a unique filename or the file couldn't
- be opened, NULL is returned. */
+/* This returns a new stream opened on an unnamed file (if supported) or a
+ temporary file (generated by tmpnam). The file is opened with mode
+ "w+b" (binary read/write). If we couldn't generate a unique filename
+ or the file couldn't be opened, NULL is returned. */
FILE *
tmpfile (void)
{
- char buf[FILENAME_MAX];
- int fd;
+ int fd = -1;
FILE *f;
-
- if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
- return NULL;
int flags = 0;
#ifdef FLAGS
flags = FLAGS;
#endif
- fd = __gen_tempname (buf, 0, flags, __GT_FILE);
+
+#ifdef O_TMPFILE
+ fd = __open (P_tmpdir, O_RDWR | O_TMPFILE | O_EXCL | flags,
+ S_IRUSR | S_IWUSR);
+ if (fd < 0 && errno == ENOENT && strcmp (P_tmpdir, "/tmp") != 0)
+ fd = __open ("/tmp", O_RDWR | O_TMPFILE | O_EXCL | flags,
+ S_IRUSR | S_IWUSR);
if (fd < 0)
- return NULL;
+ {
+ if (errno != EISDIR && errno != EOPNOTSUPP)
+ return NULL;
- /* Note that this relies on the Unix semantics that
- a file is not really removed until it is closed. */
- (void) __unlink (buf);
+ /* Either O_TMPFILE is unknown to the kernel, or the file system
+ does not support it. */
+ }
+#endif
+ if (fd < 0)
+ {
+ char buf[FILENAME_MAX];
+
+ if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
+ return NULL;
+ fd = __gen_tempname (buf, 0, flags, __GT_FILE);
+
+ if (fd >= 0)
+ /* Note that this relies on the Unix semantics that
+ a file is not really removed until it is closed. */
+ (void) __unlink (buf);
+ }
+
+ if (fd < 0)
+ return NULL;
if ((f = __fdopen (fd, "w+b")) == NULL)
__close (fd);
--
2.13.2
--
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."