#include #include #include #include #include #include #include "fatal.h" #include "writev.h" struct writev { int fd; const char *fname; int err; struct iovec *v; int n; } ; static int iov_max = -1; static void *dequal(volatile const void *v) { return((((volatile const char *)v)-(volatile const char *)0)+(char *)0); } static void writev_flush(WRITEV *wv) { int rv; if (wv->n > 0) { rv = writev(wv->fd,wv->v,wv->n); if (rv < 0) wv->err = errno; wv->n = 0; } } WRITEV *writev_init(int fd, const char *name) { WRITEV *wv; if (iov_max < 0) { int mib[2]; size_t oldlen; mib[0] = CTL_KERN; mib[1] = KERN_IOV_MAX; oldlen = sizeof(iov_max); if (sysctl(&mib[0],2,&iov_max,&oldlen,0,0) < 0) { fatal("can't get kern.iov_max: %s",strerror(errno)); exit(1); } if (iov_max > 256) iov_max = 256; if (iov_max < 1) iov_max = 1; } wv = malloc(sizeof(WRITEV)); wv->fd = fd; wv->fname = name; wv->err = 0; wv->v = malloc(iov_max*sizeof(struct iovec)); wv->n = 0; return(wv); } void writev_append(WRITEV *wv, const void *data, int len) { if (wv->err) return; if (wv->n > 0) { struct iovec *io; io = &wv->v[wv->n-1]; if (data == io->iov_len+(char *)io->iov_base) { wv->v[wv->n-1].iov_len += len; return; } } if (wv->n >= iov_max) writev_flush(wv); wv->v[wv->n++] = (struct iovec) { .iov_base = dequal(data), .iov_len = len }; } int writev_finish(WRITEV *wv) { int err; if (! wv->err) writev_flush(wv); err = wv->err; free(wv->v); free(wv); if (err) { errno = err; return(-1); } else { return(0); } }