ssize_t fiob_write(void *cookie, const char *buf, size_t len) #endif { struct fiob *f = (struct fiob *)cookie; if (len == 0) return 0; if (!f->buf) return fiob_writef(f, buf, len); ssize_t bytes_left = len; ssize_t tocopy; if (f->bfill < f->bsize) { ssize_t available_buf_size = f->bsize - f->bfill; tocopy = available_buf_size > bytes_left ? bytes_left : available_buf_size; memcpy(f->buf + f->bfill, buf, tocopy); bytes_left -= tocopy; buf += tocopy; f->bfill += tocopy; } while (bytes_left > 0) { assert(f->bfill == f->bsize); ssize_t res = fiob_writef(f, f->buf, f->bsize); if (res < 0) return res; tocopy = f->bsize > bytes_left ? bytes_left : f->bsize; /* * We must memcpy because O_DIRECT requires * an aligned chunk. */ memcpy(f->buf, buf, tocopy); bytes_left -= tocopy; buf += tocopy; f->bfill = tocopy; } return len; }
static int fiob_flushb(struct fiob *f) { if (!f->bfill) return 0; size_t tlen = fiob_ceil(f->bfill); if (fiob_writef(f, f->buf, tlen) < 0) { return -1; } off_t size = lseek(f->fd, (off_t)(f->bfill) - tlen, SEEK_CUR); if (size == (off_t)-1) { return -1; } int res = ftruncate(f->fd, size); f->bfill = 0; return res; }