summaryrefslogtreecommitdiff
path: root/src/stdio/setvbuf.c
blob: 2edfdaea973a66eac09027ac33f41993146db1e2 (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
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "_stdio.h"

/** specify file stream buffering options **/

int setvbuf(FILE *stream, char *buf, int mode, size_t size)
{
	flockfile(stream);

	if (!f_is_open(stream)) {
		#ifdef EBADF
		errno = EBADF;
		#endif

		return -1;
	}

	if (mode != _IOFBF && mode != _IOLBF && mode != _IONBF) {
		#ifdef EINVAL
		errno = EINVAL;
		#endif

		funlockfile(stream);
		return -1;
	}

	if (mode == _IONBF) {
		stream->bmode = mode;
		funlockfile(stream);
		return 0;
	}

	if (buf != NULL) {
		stream->buf = buf;
	} else if (size > stream->bsize) {
		char *tmp = stream->buf;
		if (tmp == stream->ibuf) {
			tmp = NULL;
		}

		stream->buf = realloc(tmp, size);
		if (stream->buf == NULL) {
			stream->buf = tmp ? tmp : stream->ibuf;
			funlockfile(stream);
			return -1;
		}

		stream->ibuf[0] = 'a';
	}

	stream->bmode = mode;
	stream->bsize = size;
	
	return 0;
}

/***
function sets the type of buffering for a file stream, along
with the size and location of the buffer. It must be called before any other
operations are performed.

The type of buffering is specified by ARGUMENT(mode):
FLAG(CONSTANT(_IOFBF), fully buffered)
FLAG(CONSTANT(_IOLBF), line buffered)
FLAG(CONSTANT(_IONBF), unbuffered)

If ARGUMENT(buf) is CONSTANT(NULL), THIS() will automatically allocate an
appropriate buffer. If ARGUMENT(buf) is not CONSTANT(NULL), it must point to
an array of at least ARGUMENT(size) characters.

The ARGUMENT(size) argument specifies the size of the buffer.
***/

/*
STDC(1)
*/