1570af302Sopenharmony_ci#include "stdio_impl.h"
2570af302Sopenharmony_ci#include <sys/uio.h>
3570af302Sopenharmony_ci#include <string.h>
4570af302Sopenharmony_ci
5570af302Sopenharmony_cissize_t __flush_buffer(FILE *f)
6570af302Sopenharmony_ci{
7570af302Sopenharmony_ci	ssize_t cnt = 0;
8570af302Sopenharmony_ci	char *wbase = (char *)f->wbase;
9570af302Sopenharmony_ci	size_t rem = f->wpos - f->wbase;
10570af302Sopenharmony_ci	while (rem > 0) {
11570af302Sopenharmony_ci		cnt = syscall(SYS_write, f->fd, wbase, rem);
12570af302Sopenharmony_ci		if (cnt < 0) {
13570af302Sopenharmony_ci			f->wpos = f->wbase = f->wend = 0;
14570af302Sopenharmony_ci			f->flags |= F_ERR;
15570af302Sopenharmony_ci			return cnt;
16570af302Sopenharmony_ci		}
17570af302Sopenharmony_ci		wbase += cnt;
18570af302Sopenharmony_ci		rem -= cnt;
19570af302Sopenharmony_ci	}
20570af302Sopenharmony_ci
21570af302Sopenharmony_ci	/* reset file buffer */
22570af302Sopenharmony_ci	f->wend = f->buf + f->buf_size;
23570af302Sopenharmony_ci	f->wpos = f->wbase = f->buf;
24570af302Sopenharmony_ci	return cnt;
25570af302Sopenharmony_ci}
26570af302Sopenharmony_ci
27570af302Sopenharmony_cisize_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
28570af302Sopenharmony_ci{
29570af302Sopenharmony_ci	size_t rem = len;
30570af302Sopenharmony_ci	unsigned char *wbuf = (unsigned char *)buf;
31570af302Sopenharmony_ci
32570af302Sopenharmony_ci	/* flush buffer first */
33570af302Sopenharmony_ci	ssize_t cnt = __flush_buffer(f);
34570af302Sopenharmony_ci	if (cnt < 0) {
35570af302Sopenharmony_ci		return 0;
36570af302Sopenharmony_ci	}
37570af302Sopenharmony_ci
38570af302Sopenharmony_ci	for (;;) {
39570af302Sopenharmony_ci		if (f->lbf < 0 && rem <= f->wend - f->wpos) {
40570af302Sopenharmony_ci			memcpy(f->wpos, wbuf, rem);
41570af302Sopenharmony_ci			f->wpos += rem;
42570af302Sopenharmony_ci			return len;
43570af302Sopenharmony_ci		}
44570af302Sopenharmony_ci
45570af302Sopenharmony_ci		/* write directly if
46570af302Sopenharmony_ci		 * 1. file buffer < rem
47570af302Sopenharmony_ci		 * 2. line buffer mode
48570af302Sopenharmony_ci		 */
49570af302Sopenharmony_ci		cnt = syscall(SYS_write, f->fd, wbuf, rem);
50570af302Sopenharmony_ci		if (cnt < 0) {
51570af302Sopenharmony_ci			f->wpos = f->wbase = f->wend = 0;
52570af302Sopenharmony_ci			f->flags |= F_ERR;
53570af302Sopenharmony_ci			return len - rem;
54570af302Sopenharmony_ci		}
55570af302Sopenharmony_ci
56570af302Sopenharmony_ci		rem -= cnt;
57570af302Sopenharmony_ci		wbuf += cnt;
58570af302Sopenharmony_ci		if (rem == 0) {
59570af302Sopenharmony_ci			break;
60570af302Sopenharmony_ci		}
61570af302Sopenharmony_ci	}
62570af302Sopenharmony_ci
63570af302Sopenharmony_ci	return len;
64570af302Sopenharmony_ci}
65