3 /* fopen( const char *, const char * )
5 This file is part of the Public Domain C Library (PDCLib).
6 Permission is granted to use, modify, and / or redistribute at will.
13 #include <_PDCLIB_glue.h>
15 /* FIXME: This approach is a possible attack vector. */
16 struct _PDCLIB_file_t * _PDCLIB_filelist = NULL;
18 /* Helper function that parses the C-style mode string passed to fopen() into
19 the PDCLib flags FREAD, FWRITE, FAPPEND, FRW (read-write) and FBIN (binary
22 static unsigned int filemode( char const * const mode )
34 rc |= _PDCLIB_FAPPEND;
37 /* Other than read, write, or append - invalid */
40 for ( size_t i = 1; i < 4; ++i )
45 if ( rc & _PDCLIB_FRW ) return 0; /* Duplicates are invalid */
49 if ( rc & _PDCLIB_FBIN ) return 0; /* Duplicates are invalid */
56 /* Other than read/write or binary - invalid. */
60 /* Longer than three chars - invalid. */
64 struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
66 struct _PDCLIB_file_t * rc;
67 if ( mode == NULL || filename == NULL || filename[0] == '\0' )
69 /* Mode or filename invalid */
72 if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) ) ) == NULL )
74 /* no memory for another FILE */
77 if ( ( rc->status = filemode( mode ) ) == 0 ) goto fail; /* invalid mode */
78 rc->handle = _PDCLIB_open( filename, rc->status );
79 if ( rc->handle == _PDCLIB_NOHANDLE ) goto fail; /* OS open() failed */
80 /* Adding to list of open files */
81 rc->next = _PDCLIB_filelist;
82 _PDCLIB_filelist = rc;
83 /* Setting buffer, and mark as internal. TODO: Check for unbuffered */
84 if ( ( rc->buffer = malloc( BUFSIZ ) ) == NULL ) goto fail;
87 rc->status |= ( _PDCLIB_LIBBUFFER | _PDCLIB_VIRGINSTR );
88 /* TODO: Setting mbstate */
98 #include <_PDCLIB_test.h>
103 TESTCASE( filemode( "r" ) == _PDCLIB_FREAD );
104 TESTCASE( filemode( "w" ) == _PDCLIB_FWRITE );
105 TESTCASE( filemode( "a" ) == _PDCLIB_FAPPEND );
106 TESTCASE( filemode( "r+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW ) );
107 TESTCASE( filemode( "w+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW ) );
108 TESTCASE( filemode( "a+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW ) );
109 TESTCASE( filemode( "rb" ) == ( _PDCLIB_FREAD | _PDCLIB_FBIN ) );
110 TESTCASE( filemode( "wb" ) == ( _PDCLIB_FWRITE | _PDCLIB_FBIN ) );
111 TESTCASE( filemode( "ab" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FBIN ) );
112 TESTCASE( filemode( "r+b" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
113 TESTCASE( filemode( "w+b" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
114 TESTCASE( filemode( "a+b" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW | _PDCLIB_FBIN ) );
115 TESTCASE( filemode( "rb+" ) == ( _PDCLIB_FREAD | _PDCLIB_FRW | _PDCLIB_FBIN ) );
116 TESTCASE( filemode( "wb+" ) == ( _PDCLIB_FWRITE | _PDCLIB_FRW | _PDCLIB_FBIN ) );
117 TESTCASE( filemode( "ab+" ) == ( _PDCLIB_FAPPEND | _PDCLIB_FRW | _PDCLIB_FBIN ) );
118 TESTCASE( fopen( NULL, NULL ) == NULL );
119 TESTCASE( fopen( NULL, "w" ) == NULL );
120 TESTCASE( fopen( "", NULL ) == NULL );
121 TESTCASE( fopen( "", "w" ) == NULL );
122 TESTCASE( fopen( "foo", "" ) == NULL );
123 TESTCASE( fopen( "testfile", "wq" ) == NULL ); /* Illegal mode */
124 TESTCASE( fopen( "testfile", "wr" ) == NULL ); /* Illegal mode */
125 TESTCASE( fopen( "testfile", "w" ) != NULL );
126 system( "rm testfile" );
128 puts( " NOTEST fopen() test driver is PDCLib-specific." );