blob: 0b0ea0dde97d3181ce847d6e39074577fa77c39c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
/* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
*
* GNU Library General Public License (LGPL) version 2 or later.
*
* Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
*/
#include "_stdio.h"
#if (_IOFBF != 0) || (_IOLBF != 1) || (_IONBF != 2)
#error Assumption violated -- values of _IOFBF, _IOLBF, _IONBF
#endif
#if (__FLAG_FBF != 0) || (__FLAG_NBF != (2*__FLAG_LBF))
#error Assumption violated for buffering mode flags
#endif
int setvbuf(register FILE * __restrict stream, register char * __restrict buf,
int mode, size_t size)
{
#ifdef __STDIO_BUFFERS
int retval = EOF;
int alloc_flag = 0;
__STDIO_AUTO_THREADLOCK_VAR;
__STDIO_AUTO_THREADLOCK(stream);
__STDIO_STREAM_VALIDATE(stream);
if (((unsigned int) mode) > 2) {
__set_errno(EINVAL);
goto ERROR;
}
/* C99 states that setvbuf may only be used between a successful
* open of the stream and before any other operation other than
* an unsuccessful call to setvbuf. */
#ifdef __STDIO_FLEXIBLE_SETVBUF
/* If we aren't currently reading (including ungots) or writing,
* then allow the request to proceed. */
if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) {
goto ERROR;
}
#else
/* The following test isn't quite as strict as C99, as it will
* not detect file positioning operations. */
if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING
|__FLAG_NARROW|__FLAG_WIDE
|__FLAG_ERROR|__FLAG_EOF)
) {
goto ERROR;
}
#endif
stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */
stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */
if ((mode == _IONBF) || !size) {
size = 0;
buf = NULL;
} else if (!buf) {
if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */
|| !(buf = malloc(size)) /* malloc failed, so don't change. */
) {
goto DONE;
}
alloc_flag = __FLAG_FREEBUF;
}
if (stream->__modeflags & __FLAG_FREEBUF) {
stream->__modeflags &= ~(__FLAG_FREEBUF);
free(stream->__bufstart);
}
stream->__modeflags |= alloc_flag;
stream->__bufstart = (unsigned char *) buf;
stream->__bufend = (unsigned char *) buf + size;
__STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream);
__STDIO_STREAM_DISABLE_GETC(stream);
__STDIO_STREAM_DISABLE_PUTC(stream);
DONE:
retval = 0;
ERROR:
__STDIO_STREAM_VALIDATE(stream);
__STDIO_AUTO_THREADUNLOCK(stream);
return retval;
#else /* __STDIO_BUFFERS */
if (mode == _IONBF) {
return 0;
}
if (((unsigned int) mode) > 2) {
__set_errno(EINVAL);
}
return EOF;
#endif
}
libc_hidden_def(setvbuf)
|