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