diff --git a/include/igloo/io.h b/include/igloo/io.h index e815fb9..d6916e2 100644 --- a/include/igloo/io.h +++ b/include/igloo/io.h @@ -105,17 +105,18 @@ typedef enum { typedef struct { igloo_interface_base_ifdesc_t __base; - ssize_t (*read)(igloo_INTERFACE_BASIC_ARGS, void *buffer, size_t len); - ssize_t (*write)(igloo_INTERFACE_BASIC_ARGS, const void *buffer, size_t len); - int (*flush)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags); - int (*sync)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags); - int (*set_blockingmode)(igloo_INTERFACE_BASIC_ARGS, libigloo_io_blockingmode_t mode); - libigloo_io_blockingmode_t (*get_blockingmode)(igloo_INTERFACE_BASIC_ARGS); - int (*get_fd_for_systemcall)(igloo_INTERFACE_BASIC_ARGS); + ssize_t (*read)(igloo_INTERFACE_BASIC_ARGS, void *buffer, size_t len, igloo_error_t *error); + ssize_t (*peek)(igloo_INTERFACE_BASIC_ARGS, void *buffer, size_t len, igloo_error_t *error); + ssize_t (*write)(igloo_INTERFACE_BASIC_ARGS, const void *buffer, size_t len, igloo_error_t *error); + igloo_error_t (*flush)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags); + igloo_error_t (*sync)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags); + igloo_error_t (*set_blockingmode)(igloo_INTERFACE_BASIC_ARGS, libigloo_io_blockingmode_t mode); + igloo_error_t (*get_blockingmode)(igloo_INTERFACE_BASIC_ARGS, libigloo_io_blockingmode_t *mode); + igloo_error_t (*get_fd_for_systemcall)(igloo_INTERFACE_BASIC_ARGS, int *fd); #ifdef IGLOO_CTC_STDC_HEADERS - int (*control)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags, igloo_io_control_t control, va_list ap); + igloo_error_t (*control)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags, igloo_io_control_t control, va_list ap); #else - int (*control)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags, igloo_io_control_t control, ...); + igloo_error_t (*control)(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags, igloo_io_control_t control, ...); #endif } igloo_io_ifdesc_t; @@ -143,7 +144,14 @@ igloo_io_t * igloo_io_new(const igloo_io_ifdesc_t *ifdesc, igloo_ro_t backend_ob * Returns: * The actual amount of bytes read. */ -ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len); +ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len, igloo_error_t *error); + +/* Peeks on the input side of the handle. + * + * This does the same as igloo_io_read() expect that the data is not removed from the read queue. + * This is likely not to be supported by some backends. + */ +ssize_t igloo_io_peek(igloo_io_t *io, void *buffer, size_t len, igloo_error_t *error); /* Write data to a IO handle. * Parameters: * io @@ -155,7 +163,7 @@ ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len); * Returns: * The actual amount of bytes written. */ -ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len); +ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len, igloo_error_t *error); /* Flush internal buffers to the underlying object. * This does not guarantee that all data has been written to the physical level @@ -166,7 +174,7 @@ ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len); * flags * Flags for this operation. */ -int igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags); +igloo_error_t igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags); /* Sync object with physical state. This is used to get the object into a state * that allows passing the underlying object to other software. * This may also flush internal buffers. @@ -176,7 +184,7 @@ int igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags); * flags * Flags for this operation. */ -int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags); +igloo_error_t igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags); /* Set and get the blocking state of the object. * Parameters: @@ -185,8 +193,8 @@ int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags); * mode * The new blocking mode. */ -int igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode); -libigloo_io_blockingmode_t igloo_io_get_blockingmode(igloo_io_t *io); +igloo_error_t igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode); +igloo_error_t igloo_io_get_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t *mode); #ifdef IGLOO_CTC_HAVE_SYS_SELECT_H /* Those functions act as igloo's replacement for FD_SET(), FD_CLR(), and FD_SET() and @@ -208,8 +216,8 @@ libigloo_io_blockingmode_t igloo_io_get_blockingmode(igloo_io_t *io); * to avoid this, as finding the correct parameters for igloo_io_sync() might be tricky. * The object MUST NOT be touched between select() and igloo_io_select_isset(). */ -int igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag_t flags); -int igloo_io_select_clear(igloo_io_t *io, fd_set *set); +igloo_error_t igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag_t flags); +igloo_error_t igloo_io_select_clear(igloo_io_t *io, fd_set *set); int igloo_io_select_isset(igloo_io_t *io, fd_set *set); #endif @@ -230,20 +238,9 @@ int igloo_io_select_isset(igloo_io_t *io, fd_set *set); * poll() the user MUST call igloo_io_sync() with the correct flags. It is RECOMMENDED * to avoid this, as finding the correct parameters for igloo_io_sync() might be tricky. */ -int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events); +igloo_error_t igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events); #endif -/* On a listen socket accept a new connection. - * Parameters: - * io - * The IO handle to operate on. - * Returns: - * The new connection or igloo_RO_NULL. - */ -/* TODO: Allow accept to accept()'s and accept4()'s additional parameters. -igloo_io_t *igloo_io_accept(igloo_io_t *io); -*/ - /* Advanced control interface. * Parameters: * io @@ -259,7 +256,7 @@ igloo_io_t *igloo_io_accept(igloo_io_t *io); * Additional parameters if any. * Values are always passed as pointers. */ -int igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t control, ...); +igloo_error_t igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t control, ...); #ifdef __cplusplus } diff --git a/src/io.c b/src/io.c index b65aa35..a734202 100644 --- a/src/io.c +++ b/src/io.c @@ -15,6 +15,7 @@ #include #include +#include #include "private.h" struct igloo_io_tag { @@ -57,13 +58,51 @@ igloo_io_t * igloo_io_new(const igloo_io_ifdesc_t *ifdesc, igloo_ro_t backend_ob return io; } +#define __read_fun(x) \ +ssize_t igloo_io_ ## x (igloo_io_t *io, void *buffer, size_t len, igloo_error_t *error) \ +{ \ + ssize_t ret = -1; \ + igloo_error_t error_store; \ +\ + if (!error) \ + error = &error_store; \ +\ + if (!io || !buffer) {\ + *error = igloo_ERROR_FAULT; \ + return -1; \ + } \ +\ + if (!len) \ + return 0; \ +\ + igloo_thread_mutex_lock(&(io->lock)); \ + io->touched = 1; \ +\ + if (io->ifdesc->x) {\ + ret = io->ifdesc->x(igloo_INTERFACE_BASIC_CALL(io), buffer, len, error); \ + } else { \ + *error = igloo_ERROR_GENERIC; \ + } \ + igloo_thread_mutex_unlock(&(io->lock)); \ +\ + return ret; \ +} -ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len) +__read_fun(read) +__read_fun(peek) + +ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len, igloo_error_t *error) { ssize_t ret = -1; + igloo_error_t error_store; - if (!io || !buffer) + if (!error) + error = &error_store; + + if (!io || !buffer) { + *error = igloo_ERROR_FAULT; return -1; + } if (!len) return 0; @@ -71,39 +110,22 @@ ssize_t igloo_io_read(igloo_io_t *io, void *buffer, size_t len) igloo_thread_mutex_lock(&(io->lock)); io->touched = 1; - if (io->ifdesc->read) - ret = io->ifdesc->read(igloo_INTERFACE_BASIC_CALL(io), buffer, len); + if (io->ifdesc->write) { + ret = io->ifdesc->write(igloo_INTERFACE_BASIC_CALL(io), buffer, len, error); + } else { + *error = igloo_ERROR_GENERIC; + } igloo_thread_mutex_unlock(&(io->lock)); return ret; } -ssize_t igloo_io_write(igloo_io_t *io, const void *buffer, size_t len) +igloo_error_t igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags) { - ssize_t ret = -1; - - if (!io || !buffer) - return -1; - - if (!len) - return 0; - - igloo_thread_mutex_lock(&(io->lock)); - io->touched = 1; - - if (io->ifdesc->write) - ret = io->ifdesc->write(igloo_INTERFACE_BASIC_CALL(io), buffer, len); - igloo_thread_mutex_unlock(&(io->lock)); - - return ret; -} - -int igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags) -{ - int ret = -1; + igloo_error_t ret = igloo_ERROR_GENERIC; if (!io) - return -1; + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); io->touched = 1; @@ -115,12 +137,12 @@ int igloo_io_flush(igloo_io_t *io, igloo_io_opflag_t flags) return ret; } -int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags) +igloo_error_t igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags) { - int ret; + igloo_error_t ret; if (!io) - return -1; + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); if (io->ifdesc->flush) @@ -128,7 +150,7 @@ int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags) if (io->ifdesc->sync) { ret = io->ifdesc->sync(igloo_INTERFACE_BASIC_CALL(io), flags); - if (ret != 0) { + if (ret != igloo_ERROR_NONE) { igloo_thread_mutex_unlock(&(io->lock)); return ret; } @@ -140,18 +162,18 @@ int igloo_io_sync(igloo_io_t *io, igloo_io_opflag_t flags) } igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } -int igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode) +igloo_error_t igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode) { - int ret = -1; + igloo_error_t ret = igloo_ERROR_GENERIC; if (!io) - return -1; + return igloo_ERROR_FAULT; if (mode != igloo_IO_BLOCKINGMODE_NONE && mode != igloo_IO_BLOCKINGMODE_FULL) - return -1; + return igloo_ERROR_INVAL; igloo_thread_mutex_lock(&(io->lock)); io->touched = 1; @@ -162,52 +184,60 @@ int igloo_io_set_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t mode) return ret; } -libigloo_io_blockingmode_t igloo_io_get_blockingmode(igloo_io_t *io) +igloo_error_t igloo_io_get_blockingmode(igloo_io_t *io, libigloo_io_blockingmode_t *mode) { libigloo_io_blockingmode_t ret = igloo_IO_BLOCKINGMODE_ERROR; + igloo_error_t error = igloo_ERROR_GENERIC; - if (!io) - return igloo_IO_BLOCKINGMODE_ERROR; + if (!io || !mode) + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); if (io->ifdesc->get_blockingmode) - ret = io->ifdesc->get_blockingmode(igloo_INTERFACE_BASIC_CALL(io)); + error = io->ifdesc->get_blockingmode(igloo_INTERFACE_BASIC_CALL(io), &ret); igloo_thread_mutex_unlock(&(io->lock)); - return ret; + if (error != igloo_ERROR_NONE) + return error; + + *mode = ret; + + return igloo_ERROR_NONE; } #ifdef IGLOO_CTC_HAVE_SYS_SELECT_H -int igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag_t flags) +igloo_error_t igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag_t flags) { - int ret; + igloo_error_t ret; if (!io || !set || !maxfd) - return -1; + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); if (!io->ifdesc->get_fd_for_systemcall) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } if (io->touched || !(flags & igloo_IO_OPFLAG_NOWRITE)) { igloo_thread_mutex_unlock(&(io->lock)); ret = igloo_io_sync(io, igloo_IO_OPFLAG_DEFAULTS|(flags & igloo_IO_OPFLAG_NOWRITE)); - if (ret != 0) + if (ret != igloo_ERROR_NONE) return ret; igloo_thread_mutex_lock(&(io->lock)); if (io->touched) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } } - io->fd = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io)); + ret = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io), &(io->fd)); + if (ret != igloo_ERROR_NONE) + return ret; if (io->fd < 0) - return -1; + return igloo_ERROR_GENERIC; FD_SET(io->fd, set); if (*maxfd < io->fd) @@ -215,24 +245,24 @@ int igloo_io_select_set(igloo_io_t *io, fd_set *set, int *maxfd, igloo_io_opflag igloo_thread_mutex_unlock(&(io->lock)); - return 0; + return igloo_ERROR_NONE; } -int igloo_io_select_clear(igloo_io_t *io, fd_set *set) +igloo_error_t igloo_io_select_clear(igloo_io_t *io, fd_set *set) { if (!io || !set) - return -1; + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); if (io->touched || io->fd < 0) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } FD_CLR(io->fd, set); igloo_thread_mutex_unlock(&(io->lock)); - return 0; + return igloo_ERROR_GENERIC; } int igloo_io_select_isset(igloo_io_t *io, fd_set *set) @@ -252,7 +282,7 @@ int igloo_io_select_isset(igloo_io_t *io, fd_set *set) #endif #ifdef IGLOO_CTC_HAVE_POLL -int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events) +igloo_error_t igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events) { static const short safe_events = POLLIN|POLLPRI #ifdef POLLRDHUP @@ -266,14 +296,14 @@ int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events) int ret; if (!io || !fd) - return -1; + return igloo_ERROR_FAULT; is_safe = !((events|safe_events) - safe_events); igloo_thread_mutex_lock(&(io->lock)); if (!io->ifdesc->get_fd_for_systemcall) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } if (io->touched || !is_safe) { @@ -286,14 +316,17 @@ int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events) igloo_thread_mutex_lock(&(io->lock)); if (io->touched) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } } - io->fd = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io)); + ret = io->ifdesc->get_fd_for_systemcall(igloo_INTERFACE_BASIC_CALL(io), &(io->fd)); if (io->fd < 0) { + ret = igloo_ERROR_GENERIC; + } + if (ret != igloo_ERROR_NONE) { igloo_thread_mutex_unlock(&(io->lock)); - return -1; + return igloo_ERROR_GENERIC; } memset(fd, 0, sizeof(*fd)); @@ -306,14 +339,14 @@ int igloo_io_poll_fill(igloo_io_t *io, struct pollfd *fd, short events) } #endif -int igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t control, ...) +igloo_error_t igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t control, ...) { #ifdef IGLOO_CTC_STDC_HEADERS - int ret = -1; + igloo_error_t ret = igloo_ERROR_GENERIC; va_list ap; if (!io) - return -1; + return igloo_ERROR_FAULT; igloo_thread_mutex_lock(&(io->lock)); if (io->ifdesc->control) { @@ -325,6 +358,6 @@ int igloo_io_control(igloo_io_t *io, igloo_io_opflag_t flags, igloo_io_control_t return ret; #else - return -1; + return igloo_ERROR_GENERIC; #endif } diff --git a/src/logmsg.c b/src/logmsg.c index 9588071..2ae6669 100644 --- a/src/logmsg.c +++ b/src/logmsg.c @@ -227,7 +227,7 @@ static igloo_filter_result_t __handle(igloo_INTERFACE_BASIC_ARGS, igloo_ro_t obj break; } - igloo_io_write(igloo_RO_TO_TYPE(*backend_object, igloo_io_t), pre, strlen(pre)); + igloo_io_write(igloo_RO_TO_TYPE(*backend_object, igloo_io_t), pre, strlen(pre), NULL); return igloo_FILTER_RESULT_PASS; } @@ -239,7 +239,7 @@ static int __flush(igloo_INTERFACE_BASIC_ARGS) if (!io) return 0; - return igloo_io_flush(io, igloo_IO_OPFLAG_DEFAULTS|igloo_IO_OPFLAG_FULL); + return igloo_io_flush(io, igloo_IO_OPFLAG_DEFAULTS|igloo_IO_OPFLAG_FULL) == igloo_ERROR_NONE ? 0 : -1; } static int __set_backend(igloo_INTERFACE_BASIC_ARGS, igloo_ro_t backend) diff --git a/src/stdio.c b/src/stdio.c index c62fc0a..5e9ab9f 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -13,6 +13,7 @@ #include #include +#include static int __free(igloo_INTERFACE_BASIC_ARGS) { @@ -22,30 +23,48 @@ static int __free(igloo_INTERFACE_BASIC_ARGS) } -static ssize_t __read(igloo_INTERFACE_BASIC_ARGS, void *buffer, size_t len) +static ssize_t __read(igloo_INTERFACE_BASIC_ARGS, void *buffer, size_t len, igloo_error_t *error) { - return fread(buffer, 1, len, *backend_userdata); + ssize_t ret = fread(buffer, 1, len, *backend_userdata); + + if (ret < 0) { + *error = igloo_ERROR_IO; + } else { + *error = igloo_ERROR_NONE; + } + + return ret; } -static ssize_t __write(igloo_INTERFACE_BASIC_ARGS, const void *buffer, size_t len) +static ssize_t __write(igloo_INTERFACE_BASIC_ARGS, const void *buffer, size_t len, igloo_error_t *error) { - return fwrite(buffer, 1, len, *backend_userdata); + ssize_t ret = fwrite(buffer, 1, len, *backend_userdata); + + if (ret < 0) { + *error = igloo_ERROR_IO; + } else { + *error = igloo_ERROR_NONE; + } + + return ret; } -static int __flush(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags) +static igloo_error_t __flush(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags) { - return fflush(*backend_userdata) == 0 ? 0 : -1; + return fflush(*backend_userdata) == 0 ? igloo_ERROR_NONE : igloo_ERROR_GENERIC; } -static int __sync(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags) +static igloo_error_t __sync(igloo_INTERFACE_BASIC_ARGS, igloo_io_opflag_t flags) { - return 0; + return igloo_ERROR_NONE; } -static libigloo_io_blockingmode_t __get_blockingmode(igloo_INTERFACE_BASIC_ARGS) +static igloo_error_t __get_blockingmode(igloo_INTERFACE_BASIC_ARGS, libigloo_io_blockingmode_t *mode) { - return igloo_IO_BLOCKINGMODE_FULL; + *mode = igloo_IO_BLOCKINGMODE_FULL; + return igloo_ERROR_NONE; } -static int __get_fd_for_systemcall(igloo_INTERFACE_BASIC_ARGS) +static igloo_error_t __get_fd_for_systemcall(igloo_INTERFACE_BASIC_ARGS, int *fd) { - return fileno(*backend_userdata); + *fd = fileno(*backend_userdata); + return igloo_ERROR_NONE; } static const igloo_io_ifdesc_t igloo_stdio_ifdesc = {