From 8024ab6eb8c841b330458354788d7f3a86bee7dd Mon Sep 17 00:00:00 2001 From: solar Date: Sun, 16 May 2010 10:36:32 +0000 Subject: [PATCH] Almost done on tmpfile / tmpnam. --- Makefile | 2 +- functions/stdio/fclose.c | 5 -- functions/stdio/fopen.c | 39 +++++++----- includes/inttypes.h | 2 + internals/_PDCLIB_int.h | 1 + platform/example/functions/stdio/tmpfile.c | 74 +++++++++++++++++++++- platform/example/functions/stdio/tmpnam.c | 20 ++++-- 7 files changed, 114 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 9c5b977..afd9eb5 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ SRCFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.c") # All header files of the project HDRFILES := $(shell find $(PROJDIRS) -mindepth 1 -maxdepth 3 -name "*.h") # All .c files in functions/_PDCLIB that do not have a regression test driver -INTFILES := _Exit atomax digits open print scan remove rename seed stdinit strtox_main strtox_prelim filemode eol errno seek prepread prepwrite allocpages +INTFILES := _Exit atomax digits open print scan remove rename seed stdinit strtox_main strtox_prelim filemode eol errno seek prepread prepwrite allocpages tmpfilename # All object files in the library OBJFILES := $(patsubst %.c,%.o,$(SRCFILES)) # All test drivers (.t) diff --git a/functions/stdio/fclose.c b/functions/stdio/fclose.c index 8a9301a..dc27fe2 100644 --- a/functions/stdio/fclose.c +++ b/functions/stdio/fclose.c @@ -32,11 +32,6 @@ int fclose( struct _PDCLIB_file_t * stream ) return EOF; } } - /* Free buffer */ - if ( stream->status & _PDCLIB_LIBBUFFER ) - { - free( stream->buffer ); - } /* Close handle */ _PDCLIB_close( stream->handle ); /* Remove stream from list */ diff --git a/functions/stdio/fopen.c b/functions/stdio/fopen.c index 48c07d2..1c47c17 100644 --- a/functions/stdio/fopen.c +++ b/functions/stdio/fopen.c @@ -11,20 +11,30 @@ #ifndef REGTEST #include <_PDCLIB_glue.h> +#include extern struct _PDCLIB_file_t * _PDCLIB_filelist; struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode ) { struct _PDCLIB_file_t * rc; + size_t filename_len; if ( mode == NULL || filename == NULL || filename[0] == '\0' ) { /* Mode or filename invalid */ return NULL; } - if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) ) ) == NULL ) + /* To reduce the number of malloc calls, all data fields are concatenated: + * the FILE structure itself, + * ungetc buffer, + * filename buffer, + * data buffer. + Data buffer comes last because it might change in size ( setvbuf() ). + */ + filename_len = strlen( filename ) + 1; + if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) + _PDCLIB_UNGETCBUFSIZE + filename_len + BUFSIZ ) ) == NULL ) { - /* no memory for another FILE */ + /* no memory */ return NULL; } if ( ( rc->status = _PDCLIB_filemode( mode ) ) == 0 ) @@ -40,21 +50,13 @@ struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const cha free( rc ); return NULL; } - /* Adding to list of open files */ - rc->next = _PDCLIB_filelist; - _PDCLIB_filelist = rc; - /* Setting buffer, and mark as internal. TODO: Check for unbuffered */ - if ( ( rc->buffer = malloc( BUFSIZ ) ) == NULL ) - { - free( rc ); - return NULL; - } - if ( ( rc->ungetbuf = malloc( _PDCLIB_UNGETCBUFSIZE ) ) == NULL ) - { - free( rc->buffer ); - free( rc ); - return NULL; - } + /* Setting pointers into the memory block allocated above */ + rc->ungetbuf = (unsigned char *)rc + sizeof( struct _PDCLIB_file_t ); + rc->filename = (char *)rc->ungetbuf + _PDCLIB_UNGETCBUFSIZE; + rc->buffer = rc->filename + filename_len; + /* Copying filename to FILE structure */ + strcpy( rc->filename, filename ); + /* Initializing the rest of the structure */ rc->bufsize = BUFSIZ; rc->bufidx = 0; rc->ungetidx = 0; @@ -64,6 +66,9 @@ struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const cha */ rc->status |= _PDCLIB_LIBBUFFER | _IOLBF; /* TODO: Setting mbstate */ + /* Adding to list of open files */ + rc->next = _PDCLIB_filelist; + _PDCLIB_filelist = rc; return rc; } diff --git a/includes/inttypes.h b/includes/inttypes.h index 5b86807..a0b0f35 100755 --- a/includes/inttypes.h +++ b/includes/inttypes.h @@ -13,6 +13,8 @@ typedef struct _PDCLIB_imaxdiv_t imaxdiv_t; +#define SCNu32 "u" +#define PRNu32 "u" /* TODO: Print / Scan Macros */ /* PRId8 PRIdLEAST8 PRIdFAST8 PRIdMAX diff --git a/internals/_PDCLIB_int.h b/internals/_PDCLIB_int.h index c6283b9..20a1682 100644 --- a/internals/_PDCLIB_int.h +++ b/internals/_PDCLIB_int.h @@ -263,6 +263,7 @@ typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t; #define _PDCLIB_EOFFLAG 2048u #define _PDCLIB_WIDESTREAM 4096u #define _PDCLIB_BYTESTREAM 8192u +#define _PDCLIB_DELONCLOSE 16384u /* Position / status structure for getpos() / fsetpos(). */ struct _PDCLIB_fpos_t 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 + diff --git a/platform/example/functions/stdio/tmpnam.c b/platform/example/functions/stdio/tmpnam.c index c4a0a4d..a9f5385 100644 --- a/platform/example/functions/stdio/tmpnam.c +++ b/platform/example/functions/stdio/tmpnam.c @@ -7,14 +7,23 @@ */ #include -#include #ifndef REGTEST +#include +#include <_PDCLIB_glue.h> + char * tmpnam( char * s ) { - /* TODO: Implement. */ - return NULL; + static char filename[ L_tmpnam ]; + FILE * file = tmpfile(); + if ( s == NULL ) + { + s = filename; + } + strcpy( s, file->filename ); + fclose( file ); + return s; } #endif @@ -22,10 +31,13 @@ char * tmpnam( char * s ) #ifdef TEST #include <_PDCLIB_test.h> +#include + int main( void ) { - TESTCASE( NO_TESTDRIVER ); + TESTCASE( strlen( tmpnam( NULL ) ) < L_tmpnam ); return TEST_RESULTS; } #endif + -- 2.40.0