diff options
Diffstat (limited to 'libmailutils/stream/streamcpy.c')
-rw-r--r-- | libmailutils/stream/streamcpy.c | 81 |
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; +} + + |