#include #include #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; }