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