52 lines
1.0 KiB
C
52 lines
1.0 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 size;
|
|
if(__builtin_umul_overflow(membsize, nmemb, &size)) {
|
|
fp->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
if(!fp->buf) {
|
|
ssize_t rc = __fp_read(fp, data, size);
|
|
return (rc == EOF) ? 0 : rc;
|
|
}
|
|
|
|
__fp_buffer_mode_read(fp);
|
|
|
|
size_t size_read = 0;
|
|
while(size_read < size) {
|
|
/* Take what's available in the buffer (may be 0, but only
|
|
during the first iteration) */
|
|
size_t size_frag = fp->bufread - fp->bufpos;
|
|
if(size_frag > size - size_read)
|
|
size_frag = size - size_read;
|
|
memcpy(data + size_read, fp->buf + fp->bufpos, size_frag);
|
|
size_read += size_frag;
|
|
fp->bufpos += size_frag;
|
|
|
|
if(fp->bufpos >= fp->bufread) {
|
|
fp->bufread = 0;
|
|
fp->bufpos = 0;
|
|
}
|
|
if(size_read >= size)
|
|
break;
|
|
|
|
/* Get more data */
|
|
ssize_t rc = __fp_read(fp, fp->buf, fp->bufsize);
|
|
if(rc <= 0) /* EOF or error */
|
|
break;
|
|
fp->bufread = rc;
|
|
}
|
|
|
|
return size_read;
|
|
}
|