• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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