From: Fredrik Tolf Date: Sun, 2 Mar 2014 09:17:48 +0000 (+0100) Subject: lib: Introduced a portable abstraction layer for custom stdio streams. X-Git-Url: http://www.dolda2000.com/gitweb/?p=ashd.git;a=commitdiff_plain;h=2b8eb6dfb02dc93372c5e0a4efa6dff73a8ba004 lib: Introduced a portable abstraction layer for custom stdio streams. --- diff --git a/lib/mtio.c b/lib/mtio.c index 70a0949..1f4a579 100644 --- a/lib/mtio.c +++ b/lib/mtio.c @@ -38,7 +38,7 @@ struct stdiofd { int timeout; }; -static ssize_t mtread(void *cookie, char *buf, size_t len) +static ssize_t mtread(void *cookie, void *buf, size_t len) { struct stdiofd *d = cookie; int ev; @@ -63,7 +63,7 @@ static ssize_t mtread(void *cookie, char *buf, size_t len) } } -static ssize_t mtwrite(void *cookie, const char *buf, size_t len) +static ssize_t mtwrite(void *cookie, const void *buf, size_t len) { struct stdiofd *d = cookie; int ev; @@ -107,40 +107,6 @@ static int mtclose(void *cookie) return(0); } -#if defined(HAVE_GLIBC_STDIO) -static cookie_io_functions_t iofuns = { - .read = mtread, - .write = mtwrite, - .close = mtclose, -}; - -FILE *mtstdopen(int fd, int issock, int timeout, char *mode) -{ - struct stdiofd *d; - FILE *ret; - - omalloc(d); - d->fd = fd; - d->sock = issock; - d->timeout = timeout; - ret = fopencookie(d, mode, iofuns); - if(!ret) - free(d); - else - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - return(ret); -} -#elif defined(HAVE_BSD_STDIO) -static int bsd2mtread(void *cookie, char *buf, int len) -{ - return(mtread(cookie, buf, len)); -} - -static int bsd2mtwrite(void *cookie, const char *buf, int len) -{ - return(mtwrite(cookie, buf, len)); -} - FILE *mtstdopen(int fd, int issock, int timeout, char *mode) { struct stdiofd *d; @@ -160,13 +126,10 @@ FILE *mtstdopen(int fd, int issock, int timeout, char *mode) d->fd = fd; d->sock = issock; d->timeout = timeout; - ret = funopen(d, r?bsd2mtread:NULL, w?bsd2mtwrite:NULL, NULL, mtclose); + ret = funstdio(d, r?mtread:NULL, w?mtwrite:NULL, NULL, mtclose); if(!ret) free(d); else fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); return(ret); } -#else -#error "No stdio implementation for this system" -#endif diff --git a/lib/utils.c b/lib/utils.c index 459afed..ed22b42 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -16,14 +16,15 @@ along with this program. If not, see . */ +#ifdef HAVE_CONFIG_H +#include +#endif #include #include #include #include +#include -#ifdef HAVE_CONFIG_H -#include -#endif #include static char *base64set = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -474,3 +475,127 @@ void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *)) return(tree->d); } } + +struct stdif { + ssize_t (*read)(void *pdata, void *buf, size_t len); + ssize_t (*write)(void *pdata, const void *buf, size_t len); + off_t (*seek)(void *pdata, off_t offset, int whence); + int (*close)(void *pdata); + void *pdata; +}; + +#if defined(HAVE_GLIBC_STDIO) +static ssize_t wrapread(void *pdata, char *buf, size_t len) +{ + struct stdif *nf = pdata; + + return(nf->read(nf->pdata, buf, len)); +} + +static ssize_t wrapwrite(void *pdata, const char *buf, size_t len) +{ + struct stdif *nf = pdata; + + return(nf->write(nf->pdata, buf, len)); +} + +static int wrapseek(void *pdata, off_t *pos, int whence) +{ + struct stdif *nf = pdata; + off_t ret; + + ret = nf->seek(nf->pdata, *pos, whence); + if(ret < 0) + return(-1); + *pos = ret; + return(0); +} + +static int wrapclose(void *pdata) +{ + struct stdif *nf = pdata; + int ret; + + if(nf->close != NULL) + ret = nf->close(nf->pdata); + free(nf); + return(ret); +} + +FILE *funstdio(void *pdata, + ssize_t (*read)(void *pdata, void *buf, size_t len), + ssize_t (*write)(void *pdata, const void *buf, size_t len), + off_t (*seek)(void *pdata, off_t offset, int whence), + int (*close)(void *pdata)) +{ + struct stdif *nf; + cookie_io_functions_t io; + char *mode; + + if(read && write) { + mode = "r+"; + } else if(read) { + mode = "r"; + } else if(write) { + mode = "w"; + } else { + errno = EINVAL; + return(NULL); + } + omalloc(nf); + *nf = (struct stdif){.read = read, .write = write, .seek = seek, .close = close, .pdata = pdata}; + io = (cookie_io_functions_t) { + .read = read?wrapread:NULL, + .write = write?wrapwrite:NULL, + .seek = seek?wrapseek:NULL, + .close = wrapclose, + }; + return(fopencookie(nf, mode, io)); +} +#elif defined(HAVE_BSD_STDIO) +static int wrapread(void *pdata, char *buf, int len) +{ + struct stdif *nf = pdata; + + return(nf->read(nf->pdata, buf, len)); +} + +static int wrapwrite(void *pdata, const char *buf, int len) +{ + struct stdif *nf = pdata; + + return(nf->write(nf->pdata, buf, len)); +} + +static fpos_t wrapseek(void *pdata, fpos_t pos, int whence) +{ + struct stdif *nf = pdata; + + return(nf->seek(nf->pdata, pos, whence)); +} + +static int wrapclose(void *pdata) +{ + struct stdif *nf = pdata; + int ret; + + if(nf->close != NULL) + ret = nf->close(nf->pdata); + free(nf); + return(ret); +} + +FILE *funstdio(void *pdata, + ssize_t (*read)(void *pdata, void *buf, size_t len), + ssize_t (*write)(void *pdata, const void *buf, size_t len), + off_t (*seek)(void *pdata, off_t offset, int whence), + int (*close)(void *pdata)) +{ + struct stdif *nf; + + omalloc(nf); + return(funopen(pdata, read?wrapread:NULL, write:wrapwrite:NULL, seek:wrapseek:NULL, wrapclose)); +} +#else +#error "No stdio implementation for this system" +#endif diff --git a/lib/utils.h b/lib/utils.h index 080864b..4fdde3c 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -1,6 +1,7 @@ #ifndef _UTILS_H #define _UTILS_H +#include #include #include @@ -86,5 +87,10 @@ int bbtreedel(struct btree **tree, void *item, int (*cmp)(void *, void *)); void freebtree(struct btree **tree, void (*ffunc)(void *)); int bbtreeput(struct btree **tree, void *item, int (*cmp)(void *, void *)); void *btreeget(struct btree *tree, void *key, int (*cmp)(void *, void *)); +FILE *funstdio(void *pdata, + ssize_t (*read)(void *pdata, void *buf, size_t len), + ssize_t (*write)(void *pdata, const void *buf, size_t len), + off_t (*seek)(void *pdata, off_t offset, int whence), + int (*close)(void *pdata)); #endif