]> pd.if.org Git - pdclib/blob - platform/example/functions/stdio/tmpfile.c
Test drivers for fgetpos, fsetpos, and perror. Cannot really test closeall().
[pdclib] / platform / example / 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
17 #include <_PDCLIB_glue.h>
18
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23
24 extern struct _PDCLIB_file_t * _PDCLIB_filelist;
25
26 /* This is an example implementation of tmpfile() fit for use with POSIX
27    kernels.
28 */
29 struct _PDCLIB_file_t * tmpfile( void )
30 {
31     FILE * rc;
32     /* This is the chosen way to get high-quality randomness. Replace as
33        appropriate.
34     */
35     FILE * randomsource = fopen( "/proc/sys/kernel/random/uuid", "rb" );
36     char filename[ L_tmpnam ];
37     _PDCLIB_fd_t fd;
38     if ( randomsource == NULL )
39     {
40         return NULL;
41     }
42     for ( ;; )
43     {
44         /* Get a filename candidate. What constitutes a valid filename and
45            where temporary files are usually located is platform-dependent,
46            which is one reason why this function is located in the platform
47            overlay. The other reason is that a *good* implementation should
48            use high-quality randomness instead of a pseudo-random sequence to
49            generate the filename candidate, which is *also* platform-dependent.
50         */
51         unsigned int random;
52         fscanf( randomsource, "%u", &random ); 
53         sprintf( filename, "/tmp/%u.tmp", random );
54         /* Check if file of this name exists. Note that fopen() is a very weak
55            check, which does not take e.g. access permissions into account
56            (file might exist but not readable). Replace with something more
57            appropriate.
58         */
59         fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR );
60         if ( fd != -1 )
61         {
62             break;
63         }
64         close( fd );
65     }
66     fclose( randomsource );
67     /* See fopen(). */
68     if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL )
69     {
70         /* No memory to set up FILE structure */
71         close( fd );
72         return NULL;
73     }
74     rc->status = _PDCLIB_filemode( "wb+" ) | _IOLBF | _PDCLIB_DELONCLOSE;
75     rc->handle = fd;
76     rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t );
77     rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE;
78     rc->buffer   = rc->filename + L_tmpnam;
79     strcpy( rc->filename, filename );
80     rc->bufsize = BUFSIZ;
81     rc->bufidx = 0;
82     rc->ungetidx = 0;
83     rc->next = _PDCLIB_filelist;
84     _PDCLIB_filelist = rc;
85     return rc;
86 }
87
88 #endif
89
90 #ifdef TEST
91 #include <_PDCLIB_test.h>
92 #include <string.h>
93
94 int main()
95 {
96     FILE * fh;
97     char filename[ L_tmpnam ];
98     FILE * fhtest;
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