]> pd.if.org Git - pdclib/blob - platform/example/functions/stdio/tmpfile.c
Comment cleanups.
[pdclib] / platform / example / 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
15 #include <_PDCLIB_glue.h>
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21
22 extern struct _PDCLIB_file_t * _PDCLIB_filelist;
23
24 /* This is an example implementation of tmpfile() fit for use with POSIX
25    kernels.
26 */
27 struct _PDCLIB_file_t * tmpfile( void )
28 {
29     FILE * rc;
30     /* This is the chosen way to get high-quality randomness. Replace as
31        appropriate.
32     */
33     FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
34     char filename[ L_tmpnam ];
35     _PDCLIB_fd_t fd;
36     if ( randomsource == NULL )
37     {
38         return NULL;
39     }
40     for ( ;; )
41     {
42         /* Get a filename candidate. What constitutes a valid filename and
43            where temporary files are usually located is platform-dependent,
44            which is one reason why this function is located in the platform
45            overlay. The other reason is that a *good* implementation should
46            use high-quality randomness instead of a pseudo-random sequence to
47            generate the filename candidate, which is *also* platform-dependent.
48         */
49         unsigned int random;
50         fscanf( randomsource, "%u", &random ); 
51         sprintf( filename, "/tmp/%u.tmp", random );
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, S_IRUSR | S_IWUSR );
58         if ( fd != -1 )
59         {
60             break;
61         }
62         close( fd );
63     }
64     fclose( randomsource );
65     /* See fopen(). */
66     if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL )
67     {
68         /* No memory to set up FILE structure */
69         close( fd );
70         return NULL;
71     }
72     rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE;
73     rc->handle = fd;
74     rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
75     rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
76     rc->buffer   = rc->filename + L_tmpnam;
77     strcpy( rc->filename, filename );
78     rc->bufsize = BUFSIZ;
79     rc->bufidx = 0;
80     rc->ungetidx = 0;
81     rc->next = _PDCLIB_filelist;
82     _PDCLIB_filelist = rc;
83     return rc;
84 }
85
86 #endif
87
88 #ifdef TEST
89 #include <_PDCLIB_test.h>
90 #include <string.h>
91
92 int main( void )
93 {
94     FILE * fh;
95 #ifndef REGTEST
96     char filename[ L_tmpnam ];
97     FILE * fhtest;
98 #endif
99     TESTCASE( ( fh = tmpfile() ) != NULL );
100     TESTCASE( fputc( 'x', fh ) == 'x' );
101     /* Checking that file is actually there */
102     TESTCASE_NOREG( strcpy( filename, fh->filename ) == filename );
103     TESTCASE_NOREG( ( fhtest = fopen( filename, "r" ) ) != NULL );
104     TESTCASE_NOREG( fclose( fhtest ) == 0 );
105     /* Closing tmpfile */
106     TESTCASE( fclose( fh ) == 0 );
107     /* Checking that file was deleted */
108     TESTCASE_NOREG( fopen( filename, "r" ) == NULL );
109     return TEST_RESULTS;
110 }
111
112 #endif
113