/* This file is in the public domain. */ #include #include #include #include #include extern const char *__progname; #include "panic.h" #include "dequal.h" #include "writev.h" typedef struct wv WV; struct wv { int type; #define WVT_CB 1 union { void (*cb)(struct iovec *, int); } ; int n; int a; struct iovec *v; int fn; int fa; char **fv; } ; static int maxiov = 0; static void get_max(void) { int mib[2]; size_t l; if (maxiov > 0) return; mib[0] = CTL_KERN; mib[1] = KERN_IOV_MAX; l = sizeof(maxiov); if (sysctl(&mib[0],2,&maxiov,&l,0,0) < 0) { fprintf(stderr,"%s: can't get kern.iov_max: %s\n",__progname,strerror(errno)); exit(1); } if (maxiov < 1) panic("kern.iov_max (%d) < 1",maxiov); if (maxiov > 1024) maxiov = 1024; } static void flush(WV *w) { switch (w->type) { default: panic("flushing invalid WV type %d",w->type); break; case WVT_CB: if (w->n) (*w->cb)(w->v,w->n); w->n = 0; break; } } static void flushfree(WV *w) { int i; for (i=w->fn-1;i>=0;i--) free(w->fv[i]); w->fn = 0; } void *writev_open_cb(void (*cb)(struct iovec *, int)) { WV *w; get_max(); w = malloc(sizeof(WV)); w->type = WVT_CB; w->cb = cb; w->n = 0; w->a = 0; w->v = 0; w->fn = 0; w->fa = 0; w->fv = 0; return(w); } void writev_copy(void *wvv, const void *data, int len) { char *b; b = malloc(len); bcopy(data,b,len); writev_free(wvv,b,len); } void writev_point(void *wvv, const void *data, int len) { WV *w; w = wvv; if (w->n >= maxiov) { flush(w); flushfree(w); } if (w->n >= w->a) w->v = realloc(w->v,(w->a=w->n+8)*sizeof(*w->v)); w->v[w->n++] = (struct iovec) { .iov_base=dequal(data), .iov_len=len }; } void writev_free(void *wvv, void *data, int len) { WV *w; w = wvv; writev_point(wvv,data,len); if (w->fn >= w->fa) w->fv = realloc(w->fv,(w->fa=w->fn+8)*sizeof(*w->fv)); w->fv[w->fn++] = data; } void writev_close(void *wvv) { WV *w; w = wvv; flush(w); flushfree(w); free(w->fv); free(w->v); free(w); }