]> pd.if.org Git - pdclib/blob - functions/stdio/setvbuf.c
Intermediate stdio work.
[pdclib] / functions / stdio / setvbuf.c
1 /* $Id$ */
2
3 /* setvbuf( FILE *, char *, int, size_t )
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
14 int setvbuf( struct _PDCLIB_file_t * _PDCLIB_restrict stream, char * _PDCLIB_restrict buf, int mode, size_t size )
15 {
16     /* TODO: Honor user-provided buffer / buffer size. (Not actually required
17        by the standard...) */
18     stream->status &= ~( _IOFBF | _IOLBF | _IONBF );
19     stream->status |= mode; /* TODO: Unchecked use of mode -> vulnerable. */
20     return 0;
21
22 #if 0
23     /* Only allowed on "virgin" streams (i.e., before first I/O occurs), a
24        valid value for mode, and only once per stream (i.e., the buffer
25        attached to the stream should always be the one allocated by fopen().
26     */
27     if ( ( ! stream->status & _PDCLIB_VIRGINSTR ) ||
28          ( ( mode != _IOFBF ) && ( mode != _IOLBF ) && ( mode != _IONBF ) ) ||
29          ! ( stream->status & _PDCLIB_LIBBUFFER ) )
30     {
31         return -1;
32     }
33     if ( mode == _IONBF )
34     {
35         /* When unbuffered I/O is requested, we don't need a buffer. */
36         buf = NULL;
37         size = 0;
38     }
39     else
40     {
41         /* The standard does not really require this - only BUFSIZ is required
42            to be no smaller than 256 - but it makes sense not to make buffers
43            too small anyway.
44         */
45         if ( size < 256 )
46         {
47             buf = NULL; /* do not use too-small user buffer */
48             size = 256;
49         }
50     }
51     /* If a suitable buffer is provided by user... */
52     if ( buf != NULL )
53     {
54         /* ...do not free it in library functions like fclose(), freopen(). */
55         stream->status &= ~_PDCLIB_LIBBUFFER;
56     }
57     /* If we cannot allocate enough memory, that is not a reason for failure -
58        the standard does not actually *require* that setvbuf() honors user-
59        supplied buffer and buffer size, so we can quietly ignore this.
60     */
61     /* FIXME: Logic stops here. Handle _IONBF, new buf value etc. correctly. */
62     puts("foo");
63     if ( ( ( buf = malloc( size ) ) != NULL ) || ( mode == _IONBF ) )
64     {
65         free( stream->buffer );
66     }
67     puts("bar");
68     /* Applying new settings to stream. */
69     stream->status &= ~( _IOFBF | _IOLBF | _IONBF );
70     stream->status |= mode;
71     stream->bufsize = size;
72     stream->status &= ~_PDCLIB_VIRGINSTR;
73     return 0;
74 #endif
75 }
76
77 #endif
78
79 #ifdef TEST
80 #include <_PDCLIB_test.h>
81
82 #define BUFFERSIZE 500
83
84 int main( void )
85 {
86 #ifndef REGTEST
87     char const * const filename = "testfile";
88     char buffer[ BUFFERSIZE ];
89     struct _PDCLIB_file_t * fh;
90     /* full buffered, user-supplied buffer */
91     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
92     TESTCASE( fh->status & _PDCLIB_LIBBUFFER );
93     TESTCASE( fh->bufsize == BUFSIZ );
94     TESTCASE( setvbuf( fh, buffer, _IOFBF, BUFFERSIZE ) == 0 );
95 #if 0
96     TESTCASE( fh->buffer == buffer );
97     TESTCASE( fh->bufsize == BUFFERSIZE );
98 #endif
99     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOFBF );
100     TESTCASE( fclose( fh ) == 0 );
101     /* line buffered, lib-supplied buffer */
102     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
103     TESTCASE( setvbuf( fh, NULL, _IOLBF, BUFFERSIZE ) == 0 );
104 #if 0
105     TESTCASE( fh->buffer != buffer );
106     TESTCASE( fh->buffer != NULL );
107     TESTCASE( fh->bufsize == BUFFERSIZE );
108 #endif
109     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IOLBF );
110     TESTCASE( fclose( fh ) == 0 );
111     /* not buffered, user-supplied buffer */
112     TESTCASE( ( fh = fopen( filename, "w" ) ) != NULL );
113     TESTCASE( setvbuf( fh, buffer, _IONBF, BUFFERSIZE ) == 0 );
114 #if 0
115     TESTCASE( fh->buffer == NULL );
116     TESTCASE( fh->bufsize == 0 );
117 #endif
118     TESTCASE( ( fh->status & ( _IOFBF | _IONBF | _IOLBF ) ) == _IONBF );
119     TESTCASE( fclose( fh ) == 0 );
120 #else
121     puts( " NOTEST setvbuf() test driver is PDCLib-specific." );
122 #endif
123     return TEST_RESULTS;
124 }
125
126 #endif