]> pd.if.org Git - pdclib/blob - functions/stdio/fopen.c
d181cc1f876ded1362cc297e8c2fad923e67ae64
[pdclib] / functions / stdio / fopen.c
1 /* $Id$ */
2
3 /* fopen( const char *, const char * )
4
5    This file is part of the Public Domain C Library (PDCLib).
6    Permission is granted to use, modify, and / or redistribute at will.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #ifndef REGTEST
13 #include <_PDCLIB_glue.h>
14
15 /* FIXME: This approach is a possible attack vector. */
16 struct _PDCLIB_file_t * _PDCLIB_filelist = NULL;
17
18 struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
19 {
20     struct _PDCLIB_file_t * rc;
21     if ( mode == NULL || filename == NULL || filename[0] == '\0' )
22     {
23         /* Mode or filename invalid */
24         return NULL;
25     }
26     if ( ( rc = calloc( 1, sizeof( struct _PDCLIB_file_t ) ) ) == NULL )
27     {
28         /* no memory for another FILE */
29         return NULL;
30     }
31     if ( ( rc->status = _PDCLIB_filemode( mode ) ) == 0 ) goto fail; /* invalid mode */
32     rc->handle = _PDCLIB_open( filename, rc->status );
33     if ( rc->handle == _PDCLIB_NOHANDLE ) goto fail; /* OS open() failed */
34     /* Adding to list of open files */
35     rc->next = _PDCLIB_filelist;
36     _PDCLIB_filelist = rc;
37     /* Setting buffer, and mark as internal. TODO: Check for unbuffered */
38     if ( ( rc->buffer = malloc( BUFSIZ ) ) == NULL ) goto fail;
39     rc->bufsize = BUFSIZ;
40     rc->bufidx = 0;
41     /* Setting buffer to _IOLBF because "when opened, a stream is fully
42        buffered if and only if it can be determined not to refer to an
43        interactive device."
44     */
45     rc->status |= ( _PDCLIB_LIBBUFFER | _PDCLIB_VIRGINSTR /* | _IOLBF */ ); /* FIXME: Uncommenting the _IOLBF here breaks output. */
46     /* TODO: Setting mbstate */
47     return rc;
48 fail:
49     free( rc );
50     return NULL;
51 }
52
53 #endif
54
55 #ifdef TEST
56 #include <_PDCLIB_test.h>
57
58 int main( void )
59 {
60     /* Some of the tests are not executed for regression tests, as the libc on
61        my system is at once less forgiving (segfaults on mode NULL) and more
62        forgiving (accepts undefined modes).
63     */
64 #ifndef REGTEST
65     TESTCASE( fopen( NULL, NULL ) == NULL );
66 #endif
67     TESTCASE( fopen( NULL, "w" ) == NULL );
68 #ifndef REGTEST
69     TESTCASE( fopen( "", NULL ) == NULL );
70 #endif
71     TESTCASE( fopen( "", "w" ) == NULL );
72     TESTCASE( fopen( "foo", "" ) == NULL );
73 #ifndef REGTEST
74     TESTCASE( fopen( "testfile", "wq" ) == NULL ); /* Undefined mode */
75     TESTCASE( fopen( "testfile", "wr" ) == NULL ); /* Undefined mode */
76 #endif
77     TESTCASE( fopen( "testfile", "w" ) != NULL );
78     system( "rm testfile" );
79     return TEST_RESULTS;
80 }
81
82 #endif