aboutsummaryrefslogtreecommitdiffstats
path: root/src/estream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/estream.c')
-rw-r--r--src/estream.c111
1 files changed, 108 insertions, 3 deletions
diff --git a/src/estream.c b/src/estream.c
index 46be363..2537141 100644
--- a/src/estream.c
+++ b/src/estream.c
@@ -625,6 +625,9 @@ es_func_mem_read (void *cookie, void *buffer, size_t size)
estream_cookie_mem_t mem_cookie = cookie;
gpgrt_ssize_t ret;
+ if (!size) /* Just the pending data check. */
+ return (mem_cookie->data_len - mem_cookie->offset)? 0 : -1;
+
if (size > mem_cookie->data_len - mem_cookie->offset)
size = mem_cookie->data_len - mem_cookie->offset;
@@ -898,7 +901,9 @@ es_func_fd_read (void *cookie, void *buffer, size_t size)
estream_cookie_fd_t file_cookie = cookie;
gpgrt_ssize_t bytes_read;
- if (IS_INVALID_FD (file_cookie->fd))
+ if (!size)
+ bytes_read = -1; /* We don't know whether anything is pending. */
+ else if (IS_INVALID_FD (file_cookie->fd))
{
_gpgrt_yield ();
bytes_read = 0;
@@ -1057,7 +1062,9 @@ es_func_w32_read (void *cookie, void *buffer, size_t size)
estream_cookie_w32_t w32_cookie = cookie;
gpgrt_ssize_t bytes_read;
- if (w32_cookie->hd == INVALID_HANDLE_VALUE)
+ if (!size)
+ bytes_to_read = -1; /* We don't know whether anything is pending. */
+ else if (w32_cookie->hd == INVALID_HANDLE_VALUE)
{
_gpgrt_yield ();
bytes_read = 0;
@@ -1273,6 +1280,9 @@ es_func_fp_read (void *cookie, void *buffer, size_t size)
estream_cookie_fp_t file_cookie = cookie;
gpgrt_ssize_t bytes_read;
+ if (!size)
+ return -1; /* We don't know whether anything is pending. */
+
if (file_cookie->fp)
{
if (pre_syscall_func)
@@ -1602,6 +1612,8 @@ es_fill (estream_t stream)
_set_errno (EOPNOTSUPP);
err = -1;
}
+ else if (!stream->buffer_size)
+ err = 0;
else
{
gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
@@ -1937,6 +1949,18 @@ es_read_nbf (estream_t _GPGRT__RESTRICT stream,
return err;
}
+static int
+check_pending_nbf (estream_t _GPGRT__RESTRICT stream)
+{
+ gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
+ char buffer[1];
+
+ if (!(*func_read) (stream->intern->cookie, buffer, 0))
+ return 1; /* Pending bytes. */
+ return 0; /* No pending bytes or error. */
+}
+
+
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in
fully-buffered-mode, storing the amount of bytes read in
*BYTES_READ. */
@@ -1987,6 +2011,26 @@ es_read_fbf (estream_t _GPGRT__RESTRICT stream,
return err;
}
+
+static int
+check_pending_fbf (estream_t _GPGRT__RESTRICT stream)
+{
+ gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
+ char buffer[1];
+
+ if (stream->data_offset == stream->data_len)
+ {
+ /* Nothing more to read in current container, check whetehr it
+ would be possible to fill the container with new data. */
+ if (!(*func_read) (stream->intern->cookie, buffer, 0))
+ return 1; /* Pending bytes. */
+ }
+ else
+ return 1;
+ return 0;
+}
+
+
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER in
line-buffered-mode, storing the amount of bytes read in
*BYTES_READ. */
@@ -2003,7 +2047,7 @@ es_read_lbf (estream_t _GPGRT__RESTRICT stream,
}
/* Try to read BYTES_TO_READ bytes FROM STREAM into BUFFER, storing
- *the amount of bytes read in BYTES_READ. */
+ the amount of bytes read in BYTES_READ. */
static int
es_readn (estream_t _GPGRT__RESTRICT stream,
void *_GPGRT__RESTRICT buffer_arg,
@@ -2062,6 +2106,39 @@ es_readn (estream_t _GPGRT__RESTRICT stream,
return err;
}
+
+/* Return true if at least one byte is pending for read. This is a
+ best effort check and it it possible that bytes are still pending
+ even if false is returned. If the stream is in writing mode it is
+ switched to read mode. */
+static int
+check_pending (estream_t _GPGRT__RESTRICT stream)
+{
+ if (stream->flags.writing)
+ {
+ /* Switching to reading mode -> flush output. */
+ if (es_flush (stream))
+ return 0; /* Better return 0 on error. */
+ stream->flags.writing = 0;
+ }
+
+ /* Check unread data first. */
+ if (stream->unread_data_len)
+ return 1;
+
+ switch (stream->intern->strategy)
+ {
+ case _IONBF:
+ return check_pending_nbf (stream);
+ case _IOLBF:
+ case _IOFBF:
+ return check_pending_fbf (stream);
+ }
+
+ return 0;
+}
+
+
/* Try to unread DATA_N bytes from DATA into STREAM, storing the
amount of bytes successfully unread in *BYTES_UNREAD. */
static void
@@ -3394,6 +3471,34 @@ _gpgrt_syshd (estream_t stream, es_syshd_t *syshd)
int
+_gpgrt_pending_unlocked (estream_t stream)
+{
+ return check_pending (stream);
+}
+
+
+/* Return true if there is at least one byte pending for read on
+ STREAM. This does only work if the backend supports checking for
+ pending bytes and is thus mostly useful with cookie based backends.
+
+ Note that if this function is used with cookie based functions, the
+ read cookie may be called with 0 for the SIZE argument. If bytes
+ are pending the function is expected to return -1 in this case and
+ thus deviates from the standard behavior of read(2). */
+int
+_gpgrt_pending (estream_t stream)
+{
+ int ret;
+
+ lock_stream (stream);
+ ret = _gpgrt_pending_unlocked (stream);
+ unlock_stream (stream);
+
+ return ret;
+}
+
+
+int
_gpgrt_feof_unlocked (estream_t stream)
{
return es_get_indicator (stream, 0, 1);