summaryrefslogtreecommitdiff
path: root/libmailutils/stream/streamcpy.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/stream/streamcpy.c')
-rw-r--r--libmailutils/stream/streamcpy.c81
1 files changed, 68 insertions, 13 deletions
diff --git a/libmailutils/stream/streamcpy.c b/libmailutils/stream/streamcpy.c
index aaf0e7273..e04512859 100644
--- a/libmailutils/stream/streamcpy.c
+++ b/libmailutils/stream/streamcpy.c
@@ -1,5 +1,5 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 2009-2019 Free Software Foundation, Inc.
+ Copyright (C) 2009-2024 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -29,10 +29,16 @@
#define STREAMCPY_MAX_BUF_SIZE 16384
/* Copy SIZE bytes from SRC to DST. If SIZE is 0, copy everything up to
- EOF. */
+ EOF.
+ If the callback function CBF is not NULL, it will be called for
+ each buffer-full of data read with the following arguments: pointer to
+ the buffer, length of the data portion in buffer, pointer to the user-
+ supplied callback data (CBD).
+*/
int
-mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
- mu_off_t *pcsz)
+mu_stream_copy_wcb (mu_stream_t dst, mu_stream_t src, mu_off_t size,
+ void (*cbf) (char *, size_t, void *), void *cbd,
+ mu_off_t *pcsz)
{
int status;
size_t bufsize, n;
@@ -49,7 +55,11 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
case 0:
break;
+ case EAGAIN:
+ case EINTR:
case ENOSYS:
+ case EINPROGRESS:
+ case MU_ERR_INFO_UNAVAILABLE:
size = 0;
break;
@@ -100,6 +110,8 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
break;
if (n == 0)
break;
+ if (cbf)
+ cbf (buf, n, cbd);
status = mu_stream_write (dst, buf, n, NULL);
if (status)
break;
@@ -111,15 +123,19 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
status = EIO;
}
else
- while ((status = mu_stream_read (src, buf, bufsize, &n)) == 0
- && n > 0)
- {
- status = mu_stream_write (dst, buf, n, NULL);
- if (status)
- break;
- total += n;
- }
-
+ {
+ while ((status = mu_stream_read (src, buf, bufsize, &n)) == 0
+ && n > 0)
+ {
+ if (cbf)
+ cbf (buf, n, cbd);
+ status = mu_stream_write (dst, buf, n, NULL);
+ if (status)
+ break;
+ total += n;
+ }
+ }
+
if (pcsz)
*pcsz = total;
/* FIXME: When EOF error code is implemented:
@@ -129,3 +145,42 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
free (buf);
return status;
}
+
+/* Copy SIZE bytes from SRC to DST. If SIZE is 0, copy everything up to
+ EOF. */
+int
+mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
+ mu_off_t *pcsz)
+{
+ return mu_stream_copy_wcb (dst, src, size, NULL, NULL, pcsz);
+}
+
+static void
+capture_last_char (char *buf, size_t size, void *data)
+{
+ int *n = data;
+ *n = (buf[size-1] == '\n');
+}
+
+/*
+ * Copies data from SRC to DST, appending an empty line (single newline) at
+ * the end. If data in SRC does not end in a newline character, an additional
+ * newline is appended.
+ */
+int
+mu_stream_copy_nl (mu_stream_t dst, mu_stream_t src, mu_off_t size,
+ mu_off_t *pcsz)
+{
+ int lc = 0;
+ int status = mu_stream_copy_wcb (dst, src, size, capture_last_char, &lc,
+ pcsz);
+ if (status == 0)
+ {
+ status = mu_stream_write (dst, "\n\n", 2 - lc, NULL);
+ if (status == 0 && pcsz)
+ *pcsz += 2 - lc;
+ }
+ return status;
+}
+
+

Return to:

Send suggestions and report system problems to the System administrator.