]> pd.if.org Git - pdclib/commitdiff
Almost done on tmpfile / tmpnam.
authorsolar <unknown>
Sun, 16 May 2010 10:36:32 +0000 (10:36 +0000)
committersolar <unknown>
Sun, 16 May 2010 10:36:32 +0000 (10:36 +0000)
Makefile
functions/stdio/fclose.c
functions/stdio/fopen.c
includes/inttypes.h
internals/_PDCLIB_int.h
platform/example/functions/stdio/tmpfile.c
platform/example/functions/stdio/tmpnam.c

index 9c5b977b500dae2f1d4bd49cb10b04fd5744c26f..afd9eb58648a37f686372a3d791a9f4b343c681e 100644 (file)
--- 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)
index 8a9301ae8c71cd91b206f67b4e0a17201d523707..dc27fe2eb1555a5e36bd7ceb513390d675baf415 100644 (file)
@@ -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 */
index 48c07d2b3ff41d6c2244461bc417832546063161..1c47c17a974636e3acdb3af3fbe8ec28ac17cdfb 100644 (file)
 
 #ifndef REGTEST
 #include <_PDCLIB_glue.h>
+#include <string.h>
 
 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;
 }
 
index 5b868071144317bf646463ad90d31eeb314fb2ec..a0b0f359d8faeddbc7e1081a2f4bb2a696e2139a 100755 (executable)
@@ -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
index c6283b9aee74acba2d350d749495e7ed58075d3c..20a1682303f0b8424be974f41a532af31743ddd7 100644 (file)
@@ -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
index 255a35eb75721d58d352cd1279a1dd7f3fdda622..4c55e5d3542a4c4db4f16f14fcd7d8425b6050ec 100644 (file)
 
 #ifndef REGTEST
 
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <_PDCLIB_glue.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+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
+
index c4a0a4d968402848ae28bdde0e48d809caecb028..a9f5385c1e0723e45eba248a1e44091a14a3553c 100644 (file)
@@ -7,14 +7,23 @@
 */
 
 #include <stdio.h>
-#include <stdarg.h>
 
 #ifndef REGTEST
 
+#include <string.h>
+#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 <string.h>
+
 int main( void )
 {
-    TESTCASE( NO_TESTDRIVER );
+    TESTCASE( strlen( tmpnam( NULL ) ) < L_tmpnam );
     return TEST_RESULTS;
 }
 
 #endif
+