OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.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 libc_hidden_proto(fread_unlocked)
11
12 #ifdef __DO_UNLOCKED
13
14 libc_hidden_proto(memcpy)
15 libc_hidden_proto(fflush_unlocked)
16
17 size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb,
18                                                 FILE * __restrict stream)
19 {
20         __STDIO_STREAM_VALIDATE(stream);
21         assert(stream->__filedes >= -1);
22
23         /* Note: If nmbem * size > SIZE_MAX then there is an application
24          * bug since no array can be larger than SIZE_MAX in size. */
25
26         if ((__STDIO_STREAM_IS_NARROW_READING(stream)
27                  || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW))
28                 && size && nmemb
29                 ) {
30
31                 if (nmemb <= (SIZE_MAX / size)) {
32                         unsigned char *buffer = (unsigned char *) ptr;
33                         size_t todo, bytes, avail;
34
35                         todo = bytes = size * nmemb;
36
37                         /* Check for ungots... */
38                         while (stream->__modeflags & __FLAG_UNGOT) {
39                                 *buffer++ = stream->__ungot[(stream->__modeflags--) & 1];
40                                 stream->__ungot[1] = 0;
41                                 if (!--todo) {
42                                         goto DONE;
43                                 }
44                         }
45
46 #ifdef __STDIO_BUFFERS
47                         /* Next check for available buffered... */
48                         if ((avail = stream->__bufread - stream->__bufpos) > 0) {
49                                 if (avail > todo) {
50                                         avail = todo;
51                                 }
52                                 memcpy(buffer, stream->__bufpos, avail);
53                                 buffer += avail;
54                                 stream->__bufpos += avail;
55                                 if (!(todo -= avail)) {
56                                         goto DONE;
57                                 }
58                         }
59  
60                         /* We need to read from the host environment, so we must
61                          * flush all line buffered streams if the stream is not
62                          * fully buffered. */
63                         if (!__STDIO_STREAM_IS_FBF(stream)) {
64                                 __STDIO_FLUSH_LBF_STREAMS;
65                         }
66 #endif
67
68 #ifdef __UCLIBC_MJN3_ONLY__
69 #warning CONSIDER: should we refill and read from the buffer sometimes?
70 #endif
71                         while ((avail = __stdio_READ(stream, buffer, todo)) > 0) {
72                                 buffer += avail;
73                                 if (!(todo -= avail)) {
74                                         break;
75                                 }
76                         }
77
78                 DONE:
79                         __STDIO_STREAM_VALIDATE(stream);
80                         return (bytes - todo) / size;
81                 }
82
83                 __STDIO_STREAM_SET_ERROR(stream);
84                 __set_errno(EINVAL);
85         }
86
87         __STDIO_STREAM_VALIDATE(stream);
88         return 0;
89 }
90 libc_hidden_def(fread_unlocked)
91
92 #ifndef __UCLIBC_HAS_THREADS__
93 strong_alias(fread_unlocked,fread)
94 libc_hidden_proto(fread)
95 libc_hidden_def(fread)
96 #endif
97
98 #elif defined __UCLIBC_HAS_THREADS__
99
100 size_t fread(void * __restrict ptr, size_t size, size_t nmemb,
101                          register FILE * __restrict stream)
102 {
103         size_t retval;
104         __STDIO_AUTO_THREADLOCK_VAR;
105
106         __STDIO_AUTO_THREADLOCK(stream);
107
108         retval = fread_unlocked(ptr, size, nmemb, stream);
109
110         __STDIO_AUTO_THREADUNLOCK(stream);
111
112         return retval;
113 }
114 libc_hidden_proto(fread)
115 libc_hidden_def(fread)
116
117 #endif