summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-01-25 14:34:13 +0200
committerSergey Poznyakoff <gray@gnu.org>2019-01-25 14:34:13 +0200
commitbc4d023a3810a7da6ede2cc522cdc34fa3129378 (patch)
treef8c79ba0ab5440a13ab59fbb7862c1f119a41ea6
parent2d47b2e12416e8c48673fd5fb60717ef3963abf7 (diff)
downloadmailutils-bc4d023a3810a7da6ede2cc522cdc34fa3129378.tar.gz
mailutils-bc4d023a3810a7da6ede2cc522cdc34fa3129378.tar.bz2
Improve error checking in stream writing functions.
* libmailutils/stream/stream.c (mu_stream_write): Return EIO on short writes if pnwritten is NULL. * libmailutils/stream/streamcpy.c (mu_stream_copy): Likewise (if source stream size is known.
-rw-r--r--libmailutils/stream/stream.c5
-rw-r--r--libmailutils/stream/streamcpy.c43
2 files changed, 27 insertions, 21 deletions
diff --git a/libmailutils/stream/stream.c b/libmailutils/stream/stream.c
index de995aa57..8c9cbb6e0 100644
--- a/libmailutils/stream/stream.c
+++ b/libmailutils/stream/stream.c
@@ -1027,12 +1027,17 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
bufp += n;
size -= n;
_stream_setflag (stream, _MU_STR_DIRTY);
}
if (pnwritten)
*pnwritten = nbytes;
+ else if (nbytes < size)
+ {
+ rc = EIO;
+ mu_stream_seterr (stream, rc, 1);
+ }
}
return rc;
}
int
mu_stream_writeline (mu_stream_t stream, const char *buf, size_t size)
diff --git a/libmailutils/stream/streamcpy.c b/libmailutils/stream/streamcpy.c
index 3270ee9fb..aaf0e7273 100644
--- a/libmailutils/stream/streamcpy.c
+++ b/libmailutils/stream/streamcpy.c
@@ -35,13 +35,13 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
mu_off_t *pcsz)
{
int status;
size_t bufsize, n;
char *buf;
mu_off_t total = 0;
-
+
if (pcsz)
*pcsz = 0;
if (size == 0)
{
status = mu_stream_size (src, &size);
switch (status)
@@ -53,25 +53,25 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
size = 0;
break;
default:
return status;
}
-
+
if (size)
{
mu_off_t pos;
status = mu_stream_seek (src, 0, MU_SEEK_CUR, &pos);
switch (status)
{
case 0:
if (pos > size)
return ESPIPE;
size -= pos;
break;
-
+
case EACCES:
mu_stream_clearerr (src);
case ENOSYS:
size = 0;
break;
@@ -87,27 +87,32 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
for (; (buf = malloc (bufsize)) == NULL; bufsize >>= 1)
if (bufsize < STREAMCPY_MIN_BUF_SIZE)
return ENOMEM;
if (size)
- while (size)
- {
- size_t rdsize = bufsize < size ? bufsize : size;
+ {
+ while (size)
+ {
+ size_t rdsize = bufsize < size ? bufsize : size;
- status = mu_stream_read (src, buf, rdsize, &n);
- if (status)
- break;
- if (n == 0)
- break;
- status = mu_stream_write (dst, buf, n, NULL);
- if (status)
- break;
- size -= n;
- total += n;
- }
+ status = mu_stream_read (src, buf, rdsize, &n);
+ if (status)
+ break;
+ if (n == 0)
+ break;
+ status = mu_stream_write (dst, buf, n, NULL);
+ if (status)
+ break;
+ size -= n;
+ total += n;
+ }
+
+ if (!pcsz && 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)
@@ -121,10 +126,6 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
else if (total == 0)
status = EOF;
*/
free (buf);
return status;
}
-
-
-
-

Return to:

Send suggestions and report system problems to the System administrator.