fxlibc/src/libc/stdio/fread.c

53 lines
1.3 KiB
C

#include <stdio.h>
#include <string.h>
#include "fileutil.h"
size_t fread(void *data, size_t membsize, size_t nmemb, FILE *fp)
{
if(!fp->readable) {
fp->error = 1;
return 0;
}
size_t request_size;
if(__builtin_umul_overflow(membsize, nmemb, &request_size)) {
fp->error = 1;
return 0;
}
/* If the stream if unbuffered, we might have no buffer for the reads.
If it's buffered, we always have one. It's also possible that fp is
unbuffered (_IONBF) but has a buffer temporarily because ungetc()
has been used, in which case we have to transition from buffered
reads into direct reads midway. We use __fp_buffered_read() to
handle this. */
size_t read_size = 0;
__fp_buffer_mode_read(fp);
while(read_size < request_size) {
int remaining = request_size - read_size;
int chunk = __fp_buffered_read(fp, data+read_size, remaining);
/* Stream is not/no longer buffered, finish unbuffered */
if(chunk < 0) {
ssize_t rc = __fp_read(fp, data+read_size, remaining);
return read_size + (rc == EOF ? 0 : rc);
}
read_size += chunk;
if(read_size >= request_size)
break;
/* Get more data from the file descriptor into the buffer */
if(fp->buf) {
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
if(rc <= 0) /* EOF or error */
break;
fp->bufread = rc;
}
}
return read_size;
}