]> pd.if.org Git - pdclib/commitdiff
Added fclose().
authorsolar <unknown>
Wed, 7 Jun 2006 18:10:53 +0000 (18:10 +0000)
committersolar <unknown>
Wed, 7 Jun 2006 18:10:53 +0000 (18:10 +0000)
functions/stdio/fclose.c [new file with mode: 0644]
functions/stdio/fopen.c
internals/_PDCLIB_int.h

diff --git a/functions/stdio/fclose.c b/functions/stdio/fclose.c
new file mode 100644 (file)
index 0000000..ff01058
--- /dev/null
@@ -0,0 +1,73 @@
+/* $Id$ */
+
+/* fclose( FILE * )
+
+   This file is part of the Public Domain C Library (PDCLib).
+   Permission is granted to use, modify, and / or redistribute at will.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef REGTEST
+#include <_PDCLIB_glue.h>
+
+extern struct _PDCLIB_file_t * _PDCLIB_filelist;
+
+/* FIXME: Last file not removed from list. */
+int fclose( struct _PDCLIB_file_t * stream )
+{
+    struct _PDCLIB_file_t * current = _PDCLIB_filelist;
+    struct _PDCLIB_file_t * previous = NULL;
+    /* Checking that the FILE handle is actually one we had opened before. */
+    while ( current != NULL )
+    {
+        if ( stream == current )
+        {
+            if ( stream->status & _PDCLIB_WROTELAST ) fflush( stream );
+            if ( stream->status & _PDCLIB_LIBBUFFER ) free( stream->buffer );
+            _PDCLIB_close( stream->handle );
+            if ( previous != NULL )
+            {
+                previous = current->next;
+            }
+            else
+            {
+                _PDCLIB_filelist = current->next;
+            }
+            return 0;
+        }
+        previous = current;
+        current = current->next;
+    }
+    return -1;
+}
+
+#endif
+
+#ifdef TEST
+#include <_PDCLIB_test.h>
+
+int main( void )
+{
+    /* FIXME: This is basically fopen() checking. Flushing and buffer-freeing is not checked. */
+    struct _PDCLIB_file_t * file1;
+    struct _PDCLIB_file_t * file2;
+    TESTCASE( _PDCLIB_filelist == NULL );
+    TESTCASE( ( file1 = fopen( "testfile1", "w" ) ) != NULL );
+    TESTCASE( _PDCLIB_filelist == file1 );
+    TESTCASE( ( file2 = fopen( "testfile2", "w" ) ) != NULL );
+    TESTCASE( _PDCLIB_filelist == file2 );
+    TESTCASE( fclose( file2 ) == 0 );
+    TESTCASE( _PDCLIB_filelist == file1 );
+    TESTCASE( ( file2 = fopen( "testfile1", "w" ) ) != NULL );
+    TESTCASE( _PDCLIB_filelist == file2 );
+    TESTCASE( fclose( file1 ) == 0 );
+    TESTCASE( _PDCLIB_filelist == file2 );
+    TESTCASE( fclose( file2 ) == 0 );
+    TESTCASE( _PDCLIB_filelist == NULL );
+    system( "rm testfile1 testfile2" );
+    return TEST_RESULTS;
+}
+
+#endif
index ad8d8765716a69752b27c15a911a08d0e9aca4d9..2abb66407bb9bb7e80eb53dcecd0740148a2697e 100644 (file)
 #ifndef REGTEST
 #include <_PDCLIB_glue.h>
 
-static FILE * _PDCLIB_filelist = NULL;
+/* FIXME: This approach is a possible attack vector. */
+struct _PDCLIB_file_t * _PDCLIB_filelist = NULL;
 
 /* Helper function that parses the C-style mode string passed to fopen() into
-   the PDCLib flags.FREAD, FWRITE, FAPPEND, FRW (read-write) and FBIN (
+   the PDCLib flags FREAD, FWRITE, FAPPEND, FRW (read-write) and FBIN (binary
    mode).
 */
 static unsigned int filemode( char const * const mode )
@@ -38,7 +39,7 @@ static unsigned int filemode( char const * const mode )
     }
     for ( size_t i = 1; i < 4; ++i )
     {
-        switch ( mode[1] )
+        switch ( mode[i] )
         {
             case '+':
                 if ( rc & _PDCLIB_FRW ) return 0; /* Duplicates are invalid */
@@ -60,15 +61,15 @@ static unsigned int filemode( char const * const mode )
     return 0;
 }
 
-FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
+struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
 {
-    FILE * rc;
+    struct _PDCLIB_file_t * rc;
     if ( mode == NULL || filename == NULL || filename[0] == '\0' )
     {
         /* Mode or filename invalid */
         return NULL;
     }
-    if ( ( rc = calloc( 1, sizeof( FILE ) ) ) == NULL )
+    if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) ) ) == NULL )
     {
         /* no memory for another FILE */
         return NULL;
@@ -80,8 +81,9 @@ FILE * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restr
     /* Adding to list of open files */
     rc->next = _PDCLIB_filelist;
     _PDCLIB_filelist = rc;
-    /* Setting buffer. TODO: Check for unbuffered? */
+    /* Setting buffer, and mark as internal. TODO: Check for unbuffered? */
     if ( ( rc->buffer = malloc( BUFSIZ ) ) == NULL ) goto fail;
+    rc->status |= _PDCLIB_LIBBUFFER;
     /* TODO: Setting mbstate */
     return rc;
 fail:
@@ -96,7 +98,30 @@ fail:
 
 int main( void )
 {
-    TESTCASE( NO_TESTDRIVER );
+    TESTCASE( filemode( "r" ) == _PDCLIB_FREAD );
+    TESTCASE( filemode( "w" ) == _PDCLIB_FWRITE );
+    TESTCASE( filemode( "a" ) == _PDCLIB_FAPPEND );
+    TESTCASE( filemode( "r+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW ) );
+    TESTCASE( filemode( "w+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW ) );
+    TESTCASE( filemode( "a+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW ) );
+    TESTCASE( filemode( "rb" ) == ( _PDCLIB_FREAD | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "wb" ) == ( _PDCLIB_FWRITE | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "ab" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "r+b" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "w+b" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "a+b" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "rb+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "wb+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( filemode( "ab+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW | _PDCLIB_FBIN ) );
+    TESTCASE( fopen( NULL, NULL ) == NULL );
+    TESTCASE( fopen( NULL, "w" ) == NULL );
+    TESTCASE( fopen( "", NULL ) == NULL );
+    TESTCASE( fopen( "", "w" ) == NULL );
+    TESTCASE( fopen( "foo", "" ) == NULL );
+    TESTCASE( fopen( "testfile", "wq" ) == NULL ); /* Illegal mode */
+    TESTCASE( fopen( "testfile", "wr" ) == NULL ); /* Illegal mode */
+    TESTCASE( fopen( "testfile", "w" ) != NULL );
+    system( "rm testfile" );
     return TEST_RESULTS;
 }
 
index 1cc8c018c834ad9ade5702a48856b6256082c60a..a0a63704f889bc033c2b8aee4b2d8ce672f1ac0c 100644 (file)
@@ -257,10 +257,14 @@ typedef unsigned _PDCLIB_intmax _PDCLIB_uintmax_t;
 /* Flags for representing mode (see fopen()). */
 #define _PDCLIB_FREAD    1u
 #define _PDCLIB_FWRITE   2u
-#define _PDCLIB_FAPPEND  4u
+#define _PDCLIB_FAPPEND  4u 
 #define _PDCLIB_FRW      8u
 #define _PDCLIB_FBIN    16u
 
+/* Internal flags, made to fit the same status field as the flags above. */
+#define _PDCLIB_WROTELAST 32u
+#define _PDCLIB_LIBBUFFER 64u
+
 struct _PDCLIB_file_t
 {
     _PDCLIB_fd_t            handle;   /* OS-specific file descriptor */