]> pd.if.org Git - pdclib/blob - platform/posix/functions/stdio/tmpfile.c
27c06ab1430d4c6526186854175c692eab138021
[pdclib] / platform / posix / functions / stdio / tmpfile.c
1 /* tmpfile( void )
2
3    This file is part of the Public Domain C Library (PDCLib).
4    Permission is granted to use, modify, and / or redistribute at will.
5 */
6
7 #include <stdio.h>
8
9 #ifndef REGTEST
10
11 #include <inttypes.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <_PDCLIB_glue.h>
15 #include <unistd.h>
16 #ifdef __linux__
17 /* get O_CLOEXEC without sys/types.h being awful */
18 #include <asm/fcntl.h>
19 int open(const char *fname, int flags, ...);
20 #else
21 #include <fcntl.h>
22 #endif
23
24 extern const _PDCLIB_fileops_t _PDCLIB_fileops;
25
26 FILE* _PDCLIB_nothrow tmpfile( void )
27 {
28
29     /* Good quality random source */
30     int urandom = open( "/dev/urandom", O_RDONLY | O_CLOEXEC );
31     if(urandom == -1)
32     {
33         // TODO: errno!
34         return NULL;
35     }
36
37     int fd;
38     char filename[ L_tmpnam ];
39     for ( ;; )
40     {
41         long long randnum;
42         if( read(urandom, &randnum, sizeof randnum ) != sizeof randnum )
43         {
44             // TODO: errno!
45             close( urandom );
46             return NULL;
47         }
48
49         sprintf( filename, "/tmp/%llx.tmp", randnum );
50         /* Check if file of this name exists. Note that fopen() is a very weak
51            check, which does not take e.g. access permissions into account
52            (file might exist but not readable). Replace with something more
53            appropriate.
54         */
55         fd = open( filename, O_CREAT | O_EXCL | O_RDWR, 0600 );
56         if ( fd != -1 )
57         {
58             break;
59         }
60     }
61     close( urandom );
62
63     FILE* rc = _PDCLIB_fvopen(((_PDCLIB_fd_t){ .sval = fd}), &_PDCLIB_fileops,
64                                 _PDCLIB_FWRITE | _PDCLIB_FRW |
65                                 _PDCLIB_DELONCLOSE, filename);
66     if( rc == NULL )
67     {
68         close( fd );
69         return NULL;
70     }
71
72     return rc;
73 }
74
75 #endif
76
77 #ifdef TEST
78 #include <_PDCLIB_test.h>
79 #include <string.h>
80
81 int main( void )
82 {
83     FILE * fh;
84 #ifndef REGTEST
85     char filename[ L_tmpnam ];
86     FILE * fhtest;
87 #endif
88     TESTCASE( ( fh = tmpfile() ) != NULL );
89     TESTCASE( fputc( 'x', fh ) == 'x' );
90     /* Checking that file is actually there */
91     TESTCASE_NOREG( strcpy( filename, fh->filename ) == filename );
92     TESTCASE_NOREG( ( fhtest = fopen( filename, "r" ) ) != NULL );
93     TESTCASE_NOREG( fclose( fhtest ) == 0 );
94     /* Closing tmpfile */
95     TESTCASE( fclose( fh ) == 0 );
96     /* Checking that file was deleted */
97     TESTCASE_NOREG( fopen( filename, "r" ) == NULL );
98     return TEST_RESULTS;
99 }
100
101 #endif
102