Commit d976d8a1 d976d8a10c7930658054733e3173d4b45355f61e by Sergey Poznyakoff

Bugfixes.

* examples/sfrom.c (main): Check return from mu_mailbox_messages_count.
* include/mailutils/sys/stream.h (_MU_STR_WRT): New constant.
* libproto/mbox/mbox.c (_msg_stream_setup): Fix 3rd argument to
mu_streamref_create_abridged.
* libproto/mbox/mboxscan.c (mbox_scan_internal): Don't use mailbox->stream
directly, because its offsets may get shifted by observers. Use streamref
instead.
* mailbox/argcv.c (argcv_get): Do nothing if argc <= 0.
* mailbox/mapfile_stream.c (_mapfile_seek): Fill the *presult.
* mailbox/memory_stream.c (_memory_done): Remove leftover free.
* mailbox/stream.c: Reorder functions.
(_mu_stream_create): Increase reference count (i.e. set it to 1)
before returning.
(mu_stream_seek): Call _stream_flush_buffer instead of
mu_stream_flush.
(mu_stream_read_unbuffered): Return 0 on EOF.
(mu_stream_write_unbuffered): Set _MU_STR_WRT bit.
(mu_stream_readline, mu_stream_getdelim): Check the actual
number of bytes read.
(mu_stream_flush): Call flush method only if _MU_STR_WRT is set.
Clear it.
* mailbox/streamref.c (_streamref_seek): Optimization for off==0 and
whence == MU_SEEK_CUR.
(_streamref_seek): Return new offset in ppos.
(mu_streamref_create_abridged): Set MU_STREAM_NO_CLOSE.
* mailbox/memory_stream.c (_memory_seek) : Return new offset in presult.
* mailbox/message_stream.c (_message_seek): Likewise.
* mailbox/stdio_stream.c (stdio_seek): Fix prototype.
1 parent d7a596df
......@@ -53,7 +53,12 @@ main (int argc, const char **argv)
exit (EXIT_FAILURE);
}
mu_mailbox_messages_count (mbox, &total);
status = mu_mailbox_messages_count (mbox, &total);
if (status != 0)
{
mu_error ("mu_mailbox_messages_count: %s", mu_strerror (status));
exit (EXIT_FAILURE);
}
for (msgno = 1; msgno <= total; msgno++)
{
......
......@@ -18,8 +18,9 @@
#define _MAILUTILS_SYS_STREAM_H
#define _MU_STR_DIRTY 0x1000 /* Buffer dirty */
#define _MU_STR_ERR 0x2000 /* Permanent error state */
#define _MU_STR_EOF 0x4000 /* EOF encountered */
#define _MU_STR_WRT 0x2000 /* Unflushed write pending */
#define _MU_STR_ERR 0x4000 /* Permanent error state */
#define _MU_STR_EOF 0x8000 /* EOF encountered */
#define _MU_STR_INTERN_MASK 0xf000
......
......@@ -297,7 +297,7 @@ _msg_stream_setup (mu_message_t msg, mbox_message_t mum)
status = mu_streamref_create_abridged (&stream,
mum->mud->mailbox->stream,
mum->header_from_end,
mum->header_from_end + 1,
mum->body);
if (status == 0)
status = mu_message_set_stream (msg, stream, mum);
......
......@@ -302,7 +302,12 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum,
newline = 1;
errno = lines = inheader = inbody = 0;
stream = mailbox->stream;
status = mu_streamref_create (&stream, mailbox->stream);
if (status)
return status;
status = mu_stream_seek (stream, total, MU_SEEK_SET, NULL);
if (status)
return status;
while ((status = mu_stream_readline (stream, buf, sizeof (buf), &n)) == 0
&& n != 0)
{
......@@ -396,7 +401,8 @@ mbox_scan_internal (mu_mailbox_t mailbox, mbox_message_t mum,
DISPATCH_PROGRESS (mailbox, mud);
} /* while */
mu_stream_destroy (&stream);
if (mum)
{
mum->body_end = total - newline;
......
......@@ -447,6 +447,8 @@ argcv_get (const char *command, const char *delim, const char *cmnt,
void
argcv_free (int argc, char **argv)
{
if (argc <= 0)
return;
while (--argc >= 0)
if (argv[argc])
free (argv[argc]);
......
......@@ -334,6 +334,7 @@ _mapfile_seek (struct _mu_stream *str, mu_off_t off, int whence, mu_off_t *presu
if (off < 0 || off > mfs->size)
return EINVAL;
mfs->offset = off;
*presult = off;
return 0;
}
......
......@@ -38,7 +38,6 @@ _memory_done (mu_stream_t stream)
struct _mu_memory_stream *mfs = (struct _mu_memory_stream *) stream;
if (mfs && mfs->ptr != NULL)
free (mfs->ptr);
free (mfs);
}
static int
......@@ -189,7 +188,7 @@ _memory_seek (struct _mu_stream *stream, mu_off_t off, int whence,
if (off < 0 || off > mfs->size)
return EINVAL;
mfs->offset = off;
*presult = off;
return 0;
}
......
......@@ -303,8 +303,8 @@ _message_done (mu_stream_t stream)
}
static int
_message_seek (struct _mu_stream *stream, off_t off, int whence,
off_t *presult)
_message_seek (struct _mu_stream *stream, mu_off_t off, int whence,
mu_off_t *presult)
{
struct _mu_message_stream *s = (struct _mu_message_stream*) stream;
mu_off_t size;
......@@ -327,6 +327,7 @@ _message_seek (struct _mu_stream *stream, off_t off, int whence,
if (off < 0 || off >= size)
return s->stream.last_err = EINVAL;
s->offset = off;
*presult = off;
return 0;
}
......
......@@ -128,7 +128,7 @@ stdio_size (struct _mu_stream *str, off_t *psize)
}
static int
stdio_seek (struct _mu_stream *str, off_t off, int whence, off_t *presult)
stdio_seek (struct _mu_stream *str, mu_off_t off, int whence, mu_off_t *presult)
{
struct _mu_stdio_stream *fs = (struct _mu_stdio_stream *) str;
/* FIXME */
......@@ -150,8 +150,7 @@ stdio_seek (struct _mu_stream *str, off_t off, int whence, off_t *presult)
return EINVAL;
fs->offset = off;
if (presult)
*presult = fs->offset;
*presult = fs->offset;
return 0;
}
......
......@@ -50,6 +50,138 @@ _stream_seterror (struct _mu_stream *stream, int code, int perm)
return code;
}
#define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF)
#define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n)
#define _stream_buffer_offset(s) ((s)->cur - (s)->buffer)
#define _stream_orig_level(s) ((s)->level + _stream_buffer_offset(s))
static int
_stream_fill_buffer (struct _mu_stream *stream)
{
size_t n;
size_t rdn;
int rc = 0;
char c;
switch (stream->buftype)
{
case mu_buffer_none:
return 0;
case mu_buffer_full:
if (mu_stream_read_unbuffered (stream,
stream->buffer, stream->bufsize,
0,
&stream->level))
return 1;
break;
case mu_buffer_line:
for (n = 0;
n < stream->bufsize
&& (rc = mu_stream_read_unbuffered (stream,
&c, 1, 0, &rdn)) == 0
&& rdn; n++)
{
stream->buffer[n] = c;
if (c == '\n')
break;
}
stream->level = n;
break;
}
stream->cur = stream->buffer;
return rc;
}
#define BUFFER_FULL_P(s) \
((s)->cur + (s)->level == (s)->buffer + (s)->bufsize)
static int
_stream_buffer_full_p (struct _mu_stream *stream)
{
switch (stream->buftype)
{
case mu_buffer_none:
break;
case mu_buffer_line:
return BUFFER_FULL_P (stream)
|| memchr (stream->cur, '\n', stream->level) != NULL;
case mu_buffer_full:
return BUFFER_FULL_P (stream);
}
return 0;
}
static int
_stream_flush_buffer (struct _mu_stream *stream, int all)
{
int rc;
char *end;
if (stream->flags & _MU_STR_DIRTY)
{
if ((stream->flags & MU_STREAM_SEEK)
&& (rc = mu_stream_seek (stream,
- _stream_orig_level (stream),
MU_SEEK_CUR, NULL)))
return rc;
switch (stream->buftype)
{
case mu_buffer_none:
abort(); /* should not happen */
case mu_buffer_full:
if ((rc = mu_stream_write_unbuffered (stream, stream->cur,
stream->level, 1, NULL)))
return rc;
break;
case mu_buffer_line:
if (stream->level == 0)
break;
for (end = memchr (stream->cur, '\n', stream->level);
end;
end = memchr (stream->cur, '\n', stream->level))
{
size_t size = end - stream->cur + 1;
rc = mu_stream_write_unbuffered (stream,
stream->cur,
size, 1, NULL);
if (rc)
return rc;
_stream_advance_buffer (stream, size);
}
if ((all && stream->level) || BUFFER_FULL_P (stream))
{
rc = mu_stream_write_unbuffered (stream,
stream->cur,
stream->level,
1, NULL);
if (rc)
return rc;
_stream_advance_buffer (stream, stream->level);
}
}
}
if (stream->level)
{
if (stream->cur > stream->buffer)
memmove (stream->buffer, stream->cur, stream->level);
}
else
{
stream->flags &= ~_MU_STR_DIRTY;
stream->level = 0;
}
stream->cur = stream->buffer;
return 0;
}
mu_stream_t
_mu_stream_create (size_t size, int flags)
{
......@@ -58,6 +190,7 @@ _mu_stream_create (size_t size, int flags)
abort ();
str = mu_zalloc (size);
str->flags = flags;
mu_stream_ref (str);
return str;
}
......@@ -137,11 +270,6 @@ mu_stream_eof (mu_stream_t stream)
return stream->flags & _MU_STR_EOF;
}
#define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF)
#define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n)
#define _stream_buffer_offset(s) ((s)->cur - (s)->buffer)
#define _stream_orig_level(s) ((s)->level + _stream_buffer_offset(s))
int
mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
mu_off_t *pres)
......@@ -162,7 +290,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
break;
case MU_SEEK_CUR:
break;
break;
case MU_SEEK_END:
bpos = _stream_buffer_offset (stream);
......@@ -183,8 +311,8 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
return _stream_seterror (stream, EINVAL, 1);
}
if (mu_stream_flush (stream))
return -1;
if ((rc = _stream_flush_buffer (stream, 1)))
return rc;
rc = stream->seek (stream, offset, whence, &res);
if (rc)
return _stream_seterror (stream, rc, 1);
......@@ -247,15 +375,8 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
if ((stream->flags & _MU_STR_EOF) || size == 0)
{
if (pnread)
{
*pnread = 0;
return 0;
}
else
{
_stream_seterror (stream, EIO, 0);
return EIO;
}
*pnread = 0;
return 0;
}
if (full_read)
......@@ -277,8 +398,8 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
stream->bytes_in += rdbytes;
}
if (size)
rc = _stream_seterror (stream, EIO, 0);
if (size && rc)
rc = _stream_seterror (stream, rc, 0);
}
else
{
......@@ -349,136 +470,13 @@ mu_stream_write_unbuffered (mu_stream_t stream,
if (rc == 0)
stream->bytes_out += nwritten;
}
stream->flags |= _MU_STR_WRT;
if (pnwritten)
*pnwritten = nwritten;
_stream_seterror (stream, rc, rc != 0);
return rc;
}
static int
_stream_fill_buffer (struct _mu_stream *stream)
{
size_t n;
int rc = 0;
char c;
switch (stream->buftype)
{
case mu_buffer_none:
return 0;
case mu_buffer_full:
if (mu_stream_read_unbuffered (stream,
stream->buffer, stream->bufsize,
0,
&stream->level))
return 1;
break;
case mu_buffer_line:
for (n = 0;
n < stream->bufsize
&& (rc = mu_stream_read_unbuffered (stream,
&c, 1, 0, NULL)) == 0; n++)
{
stream->buffer[n] = c;
if (c == '\n')
break;
}
stream->level = n;
break;
}
stream->cur = stream->buffer;
return rc;
}
#define BUFFER_FULL_P(s) \
((s)->cur + (s)->level == (s)->buffer + (s)->bufsize)
static int
_stream_buffer_full_p (struct _mu_stream *stream)
{
switch (stream->buftype)
{
case mu_buffer_none:
break;
case mu_buffer_line:
return BUFFER_FULL_P (stream)
|| memchr (stream->cur, '\n', stream->level) != NULL;
case mu_buffer_full:
return BUFFER_FULL_P (stream);
}
return 0;
}
static int
_stream_flush_buffer (struct _mu_stream *stream, int all)
{
int rc;
char *end;
if (stream->flags & _MU_STR_DIRTY)
{
if ((stream->flags & MU_STREAM_SEEK)
&& (rc = mu_stream_seek (stream,
- _stream_orig_level (stream),
MU_SEEK_CUR, NULL)))
return rc;
switch (stream->buftype)
{
case mu_buffer_none:
abort(); /* should not happen */
case mu_buffer_full:
if ((rc = mu_stream_write_unbuffered (stream, stream->cur,
stream->level, 1, NULL)))
return rc;
break;
case mu_buffer_line:
if (stream->level == 0)
break;
for (end = memchr(stream->cur, '\n', stream->level);
end;
end = memchr(stream->cur, '\n', stream->level))
{
size_t size = end - stream->cur + 1;
rc = mu_stream_write_unbuffered (stream,
stream->cur,
size, 1, NULL);
if (rc)
return rc;
_stream_advance_buffer (stream, size);
}
if ((all && stream->level) || BUFFER_FULL_P (stream))
{
rc = mu_stream_write_unbuffered (stream,
stream->cur,
stream->level,
1, NULL);
if (rc)
return rc;
_stream_advance_buffer (stream, stream->level);
}
}
}
if (stream->level)
{
if (stream->cur > stream->buffer)
memmove (stream->buffer, stream->cur, stream->level);
}
else
{
stream->flags &= ~_MU_STR_DIRTY;
stream->level = 0;
}
stream->cur = stream->buffer;
return 0;
}
int
mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
{
......@@ -530,16 +528,17 @@ mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread)
{
int rc;
char c;
size_t n = 0;
size_t n = 0, rdn;
if (size == 0)
return EIO;
size--;
for (n = 0; n < size && (rc = mu_stream_read (stream, &c, 1, NULL)) == 0;
n++)
for (n = 0;
n < size && (rc = mu_stream_read (stream, &c, 1, &rdn)) == 0 && rdn;)
{
*buf++ = c;
n++;
if (c == '\n')
break;
}
......@@ -571,9 +570,10 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
for (;;)
{
char c;
size_t rdn;
rc = mu_stream_read (stream, &c, 1, NULL);
if (rc)
rc = mu_stream_read (stream, &c, 1, &rdn);
if (rc || rdn == 0)
break;
/* Make enough space for len+1 (for final NUL) bytes. */
......@@ -686,8 +686,9 @@ mu_stream_flush (mu_stream_t stream)
rc = _stream_flush_buffer (stream, 1);
if (rc)
return rc;
if (stream->flush)
if ((stream->flags & _MU_STR_WRT) && stream->flush)
return stream->flush (stream);
stream->flags &= ~_MU_STR_WRT;
return 0;
}
......
......@@ -129,6 +129,11 @@ _streamref_seek (struct _mu_stream *str, mu_off_t off, int whence,
break;
case MU_SEEK_CUR:
if (off == 0)
{
*ppos = sp->offset - sp->start;
return 0;
}
off += cur;
break;
......@@ -139,10 +144,12 @@ _streamref_seek (struct _mu_stream *str, mu_off_t off, int whence,
if (off < 0 || off >= size)
return sp->stream.last_err = EINVAL;
return streamref_return (sp,
mu_stream_seek (sp->transport,
sp->start + off, MU_SEEK_SET,
&sp->offset));
rc = mu_stream_seek (sp->transport, sp->start + off, MU_SEEK_SET,
&sp->offset);
if (rc)
return streamref_return (sp, rc);
*ppos = sp->offset - sp->start;
return 0;
}
static int
......@@ -223,7 +230,8 @@ mu_streamref_create_abridged (mu_stream_t *pref, mu_stream_t str,
if (rc)
return rc;
mu_stream_get_flags (str, &flags);
sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp), flags);
sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp),
flags | MU_STREAM_NO_CLOSE);
if (!sp)
return ENOMEM;
mu_stream_ref (str);
......