1 #include "stdio_impl.h"
2 #include <string.h>
3 #include "param_check.h"
4 
5 #define MIN(a,b) ((a)<(b) ? (a) : (b))
6 
__fill_buffer(FILE *f)7 int __fill_buffer(FILE *f)
8 {
9 	int r = __toread(f);
10 	if (r != 0) {
11 		return r;
12 	}
13 
14 	int k = f->readx(f, f->buf, f->buf_size);
15 	if (k <= 0) {
16 		f->flags |= (k == 0) ? F_EOF : F_ERR;
17 		f->rpos = f->rend;
18 		return k;
19 	}
20 
21 	f->rpos = f->buf;
22 	f->rend = f->rpos + k;
23 
24 	return 0;
25 }
26 
fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)27 size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
28 {
29 	unsigned char *dest = destv;
30 	size_t len = size * nmemb, l = len, k;
31 	PARAM_CHECK(f);
32 	if (!size) {
33 		nmemb = 0;
34 	}
35 
36 	FLOCK(f);
37 
38 	/* allocate file buffer if needed */
39 	if (__falloc_buf(f) < 0) {
40 		f->flags |= F_ERR;
41 		goto exit;
42 	}
43 
44 	f->mode |= f->mode-1;
45 
46 	while (l > 0) {
47 		if (f->rpos != f->rend) {
48 			/* First exhaust the buffer. */
49 			k = MIN(f->rend - f->rpos, l);
50 			memcpy(dest, f->rpos, k);
51 			f->rpos += k;
52 			dest += k;
53 			l -= k;
54 		}
55 		/* done */
56 		if (l == 0) {
57 			goto exit;
58 		}
59 		/* if user buffer is longer than file buffer,
60 		 * maybe buffer size is 0, non-buffer mode,
61 		 * read directly */
62 		if (l > f->buf_size) {
63 			break;
64 		}
65 
66 		if (__fill_buffer(f)) {
67 			goto exit;
68 		}
69 	}
70 
71 	/* Read the remainder directly */
72 	for (; l; l-=k, dest+=k) {
73 		k = f->readx(f, dest, l);
74 		if (!k) {
75 			break;
76 		}
77 	}
78 
79 exit:
80 	FUNLOCK(f);
81 	return (len - l) / size;
82 }
83 
84 weak_alias(fread, fread_unlocked);
85