62 lines
1.3 KiB
C
62 lines
1.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "fileutil.h"
|
|
|
|
size_t fwrite(void const *data, size_t membsize, size_t nmemb, FILE *fp)
|
|
{
|
|
if(!fp->writable) {
|
|
fp->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
size_t size;
|
|
if(__builtin_umul_overflow(membsize, nmemb, &size)) {
|
|
fp->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
if(fp->append && fseek(fp, 0, SEEK_END) == EOF) {
|
|
fp->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
if(!fp->buf) {
|
|
ssize_t rc = __fp_write(fp, data, size);
|
|
return (rc == EOF) ? 0 : rc;
|
|
}
|
|
|
|
__fp_buffer_mode_write(fp);
|
|
|
|
size_t size_written = 0;
|
|
|
|
while(size_written < size) {
|
|
size_t size_frag = fp->bufsize - fp->bufpos;
|
|
void const *last_line = NULL;
|
|
|
|
if(size_frag >= size - size_written) {
|
|
size_frag = size - size_written;
|
|
|
|
/* In the last run, if line buffering is enabled and
|
|
there is a newline, stop at that newline and flush
|
|
before the last write to buffer */
|
|
if(fp->bufmode == _IOLBF) last_line = memrchr(
|
|
data + size_written, '\n', size_frag);
|
|
}
|
|
if(last_line)
|
|
size_frag = (last_line + 1) - (data + size_written);
|
|
|
|
memcpy(fp->buf + fp->bufpos, data + size_written, size_frag);
|
|
size_written += size_frag;
|
|
fp->bufpos += size_frag;
|
|
|
|
if(fp->bufpos >= fp->bufsize || last_line) {
|
|
ssize_t rc = __fp_write(fp, fp->buf, fp->bufpos);
|
|
if(rc <= 0) /* error */
|
|
break;
|
|
fp->bufpos = 0;
|
|
}
|
|
}
|
|
|
|
return size_written;
|
|
}
|