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