X-Git-Url: https://pd.if.org/git/?p=pdclib;a=blobdiff_plain;f=platform%2Fexample%2Ffunctions%2Fstdio%2Ftmpfile.c;h=4c55e5d3542a4c4db4f16f14fcd7d8425b6050ec;hp=255a35eb75721d58d352cd1279a1dd7f3fdda622;hb=8024ab6eb8c841b330458354788d7f3a86bee7dd;hpb=4116251e9bb6c386580d71d8c4afd2d0d08c6096 diff --git a/platform/example/functions/stdio/tmpfile.c b/platform/example/functions/stdio/tmpfile.c index 255a35e..4c55e5d 100644 --- a/platform/example/functions/stdio/tmpfile.c +++ b/platform/example/functions/stdio/tmpfile.c @@ -10,10 +10,79 @@ #ifndef REGTEST +#include +#include +#include + +#include <_PDCLIB_glue.h> + +#include +#include +#include +#include + +extern struct _PDCLIB_file_t * _PDCLIB_filelist; + +/* This is an example implementation of tmpfile() fit for use with POSIX + POSIX kernels. +*/ struct _PDCLIB_file_t * tmpfile( void ) { - /* TODO: Implement */ - return NULL; + FILE * rc; + /* This is the chosen way to get high-quality randomness. Replace as + appropriate. + */ + FILE * randomsource = fopen( "/dev/urandom", "rb" ); + char filename[ L_tmpnam ]; + _PDCLIB_fd_t fd; + if ( randomsource == NULL ) + { + return NULL; + } + for ( ;; ) + { + /* Get a filename candidate. What constitutes a valid filename and + where temporary files are usually located is platform-dependent, + which is one reason why this function is located in the platform + overlay. The other reason is that a *good* implementation should + use high-quality randomness instead of a pseudo-random sequence to + generate the filename candidate, which is *also* platform-dependent. + */ + uint32_t random; + fscanf( randomsource, "%" SCNu32, &random ); + sprintf( filename, "/tmp/%010" PRNu32 ".tmp", random ); + /* Check if file of this name exists. Note that fopen() is a very weak + check, which does not take e.g. access permissions into account + (file might exist but not readable). Replace with something more + appropriate. + */ + fd = open( filename, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR ); + if ( fd != -1 ) + { + break; + } + close( fd ); + } + fclose( randomsource ); + /* See fopen(). */ + if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + L_tmpnam + BUFSIZ ) ) == NULL ) + { + /* No memory to set up FILE structure */ + close( fd ); + return NULL; + } + rc->status = _PDCLIB_filemode( "wb+" ) | _PDCLIB_LIBBUFFER | _IOLBF | _PDCLIB_DELONCLOSE; + rc->handle = fd; + rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); + rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; + rc->buffer = rc->filename + L_tmpnam; + strcpy( rc->filename, filename ); + rc->bufsize = BUFSIZ; + rc->bufidx = 0; + rc->ungetidx = 0; + rc->next = _PDCLIB_filelist; + _PDCLIB_filelist = rc; + return rc; } #endif @@ -28,3 +97,4 @@ int main() } #endif +