OSDN Git Service

f8bea5a500dbdb684f89ae4e726500014abb8a21
[uclinux-h8/uclibc-ng.git] / libc / stdio / fread.c
1 /* Copyright (C) 2004       Manuel Novoa III    <mjn3@codepoet.org>
2  *
3  * GNU Library General Public License (LGPL) version 2 or later.
4  *
5  * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details.
6  */
7
8 #include "_stdio.h"
9
10
11 #ifdef __DO_UNLOCKED
12
13
14 size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb,
15                                                 FILE * __restrict stream)
16 {
17         __STDIO_STREAM_VALIDATE(stream);
18         assert(stream->__filedes >= -1);
19
20         /* Note: If nmbem * size > SIZE_MAX then there is an application
21          * bug since no array can be larger than SIZE_MAX in size. */
22
23         if ((__STDIO_STREAM_IS_NARROW_READING(stream)
24                  || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW))
25                 && size && nmemb
26                 ) {
27
28                 if (nmemb <= (SIZE_MAX / size)) {
29                         unsigned char *buffer = (unsigned char *) ptr;
30                         size_t todo, bytes, avail;
31
32                         todo = bytes = size * nmemb;
33
34                         /* Check for ungots... */
35                         while (stream->__modeflags & __FLAG_UNGOT) {
36                                 *buffer++ = stream->__ungot[(stream->__modeflags--) & 1];
37                                 stream->__ungot[1] = 0;
38                                 if (!--todo) {
39                                         goto DONE;
40                                 }
41                         }
42
43 #ifdef __STDIO_BUFFERS
44                         /* Next check for available buffered... */
45                         if ((avail = stream->__bufread - stream->__bufpos) > 0) {
46                                 if (avail > todo) {
47                                         avail = todo;
48                                 }
49                                 memcpy(buffer, stream->__bufpos, avail);
50                                 buffer += avail;
51                                 stream->__bufpos += avail;
52                                 if (!(todo -= avail)) {
53                                         goto DONE;
54                                 }
55                         }
56
57                         /* We need to read from the host environment, so we must
58                          * flush all line buffered streams if the stream is not
59                          * fully buffered. */
60                         if (!__STDIO_STREAM_IS_FBF(stream)) {
61                                 __STDIO_FLUSH_LBF_STREAMS;
62                         }
63 #endif
64                         while ((avail = __stdio_READ(stream, buffer, todo)) > 0) {
65                                 buffer += avail;
66                                 if (!(todo -= avail)) {
67                                         break;
68                                 }
69                         }
70
71                 DONE:
72                         __STDIO_STREAM_VALIDATE(stream);
73                         return (bytes - todo) / size;
74                 }
75
76                 __STDIO_STREAM_SET_ERROR(stream);
77                 __set_errno(EINVAL);
78         }
79
80         __STDIO_STREAM_VALIDATE(stream);
81         return 0;
82 }
83 libc_hidden_def(fread_unlocked)
84
85 #ifndef __UCLIBC_HAS_THREADS__
86 strong_alias(fread_unlocked,fread)
87 libc_hidden_def(fread)
88 #endif
89
90 #elif defined __UCLIBC_HAS_THREADS__
91
92 size_t fread(void * __restrict ptr, size_t size, size_t nmemb,
93                          register FILE * __restrict stream)
94 {
95         size_t retval;
96         __STDIO_AUTO_THREADLOCK_VAR;
97
98         __STDIO_AUTO_THREADLOCK(stream);
99
100         retval = fread_unlocked(ptr, size, nmemb, stream);
101
102         __STDIO_AUTO_THREADUNLOCK(stream);
103
104         return retval;
105 }
106 libc_hidden_def(fread)
107
108 #endif