Commit 6c977a77 6c977a773bc4884d9651b7ae4908a968242a555f by Alain Magloire

* mailbox2/include/mailutils/mbox.h: New prototypes.

	* mailbox2/include/mailutils/sys/mbox.h: New prototypes.
	* mailbox2/mbox/*.c: Finish implementation.
	* mailbox2/attribute.c: Add user flags.
	* mailbox2/dattribute.c: Add user flags.

	To be compatible with the old mailbox, all stream read
	and write take an offset. Removed stream_seek () and add
	stream_is_seekable() instead.
	* mailbox2/stream.c: Likewised.
	* mailbox2/bstream.c: Likewised.
	* mailbox2/fdstream.c: Likewised.
	* mailbox2/fstream.c: Likewised.
	* mailbox2/mapstream.c: Likewised.
	* mailbox2/memstream.c: Likewised.
	* mailbox2/tcpstream.c: Likewised.

	* mailbox2/include/mailutils/error.h: Add EBADFD.
1 parent b7a718c6
Showing 71 changed files with 1373 additions and 631 deletions
......@@ -81,6 +81,42 @@ attribute_clear_flags (attribute_t attribute)
return attribute->vtable->clear_flags (attribute);
}
int
attribute_get_userflags (attribute_t attribute, int *puserflags)
{
if (attribute == NULL || attribute->vtable == NULL
|| attribute->vtable->get_userflags == NULL)
return MU_ERROR_NOT_SUPPORTED;
return attribute->vtable->get_userflags (attribute, puserflags);
}
int
attribute_set_userflags (attribute_t attribute, int userflags)
{
if (attribute == NULL || attribute->vtable == NULL
|| attribute->vtable->set_userflags == NULL)
return MU_ERROR_NOT_SUPPORTED;
return attribute->vtable->set_userflags (attribute, userflags);
}
int
attribute_unset_userflags (attribute_t attribute, int userflags)
{
if (attribute == NULL || attribute->vtable == NULL
|| attribute->vtable->unset_userflags == NULL)
return MU_ERROR_NOT_SUPPORTED;
return attribute->vtable->unset_userflags (attribute, userflags);
}
int
attribute_clear_userflags (attribute_t attribute)
{
if (attribute == NULL || attribute->vtable == NULL
|| attribute->vtable->clear_userflags == NULL)
return MU_ERROR_NOT_SUPPORTED;
return attribute->vtable->clear_userflags (attribute);
}
/* Stub helpers for the wellknown flags. */
int
......@@ -149,6 +185,16 @@ attribute_set_modified (attribute_t attribute)
}
int
attribute_is_userflags (attribute_t attribute, int userflag)
{
int flags = 0;
if (attribute == NULL)
return 0;
attribute_get_userflags (attribute, &flags);
return flags & userflag;
}
int
attribute_is_seen (attribute_t attribute)
{
int flags = 0;
......
......@@ -44,19 +44,20 @@ _stream_buffer_cleanup (void *arg)
}
static int
refill (struct _stream_buffer *bs)
refill (struct _stream_buffer *bs, off_t offset)
{
int status;
if (bs->rbuffer.base == NULL)
{
bs->rbuffer.base = calloc (1, bs->rbuffer.bufsize);
if (bs->rbuffer.base == NULL)
return ENOMEM;
return MU_ERROR_NO_MEMORY;
}
bs->rbuffer.ptr = bs->rbuffer.base;
bs->rbuffer.count = 0;
bs->rbuffer.offset = offset;
status = stream_read (bs->stream, bs->rbuffer.ptr, bs->rbuffer.bufsize,
(size_t *)&(bs->rbuffer.count));
offset, (size_t *)&(bs->rbuffer.count));
return status;
}
......@@ -107,7 +108,8 @@ _stream_buffer_close (stream_t stream)
networking. Lots of code between POP and IMAP can be share this way.
The buffering is on the read only, the writes fall through. */
int
_stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
_stream_buffer_read (stream_t stream, void *buf, size_t count, off_t offset,
size_t *pnread)
{
int status = 0;
struct _stream_buffer *bs = (struct _stream_buffer *)stream;
......@@ -121,8 +123,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
else if (bs->rbuffer.bufsize == 0)
{
/* If rbuffer.bufsize == 0. It means they did not want the buffer
mechanism, then what are we doing here? */
status = stream_read (bs->stream, buf, count, pnread);
mechanism, ... what are we doing here? */
status = stream_read (bs->stream, buf, count, offset, pnread);
}
else
{
......@@ -139,14 +141,17 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
{
r = 0;
/* Drain our buffer first. */
if (bs->rbuffer.count > 0)
if (bs->rbuffer.count > 0 && offset == bs->rbuffer.offset)
{
memcpy(p, bs->rbuffer.ptr, bs->rbuffer.count);
bs->rbuffer.offset += bs->rbuffer.count;
residue -= bs->rbuffer.count;
p += bs->rbuffer.count;
offset += bs->rbuffer.count;
}
bs->rbuffer.count = 0; /* Signal we will need to refill. */
status = stream_read (bs->stream, p, residue, &r);
status = stream_read (bs->stream, p, residue, offset, &r);
bs->rbuffer.offset += r;
residue -= r;
if (pnread)
*pnread = count - residue;
......@@ -164,20 +169,22 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
{
(void)memcpy (p, bs->rbuffer.ptr, (size_t)r);
bs->rbuffer.ptr += r;
bs->rbuffer.offset += r;
/* bs->rbuffer.count = 0 ... done in refill */
p += r;
residue -= r;
status = refill (bs);
status = refill (bs, bs->rbuffer.offset);
/* Did we reach the end. */
if (status != 0 || bs->rbuffer.count == 0)
{
/* We have something in the buffer return the error on the
next call . */
next call. */
if (count != residue)
status = 0;
if (pnread)
*pnread = count - residue;
done = 1;
break;
}
}
if (!done)
......@@ -185,6 +192,7 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
memcpy(p, bs->rbuffer.ptr, residue);
bs->rbuffer.count -= residue;
bs->rbuffer.ptr += residue;
bs->rbuffer.offset += residue;
if (pnread)
*pnread = count;
}
......@@ -200,7 +208,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
* Stop when a newline has been read, or the count runs out.
*/
int
_stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnread)
_stream_buffer_readline (stream_t stream, char *buf, size_t count,
off_t offset, size_t *pnread)
{
int status = 0;
struct _stream_buffer *bs = (struct _stream_buffer *)stream;
......@@ -214,7 +223,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
else if (bs->rbuffer.bufsize == 0)
{
/* Use the provided readline. */
status = stream_readline (bs->stream, buf, count, pnread);
status = stream_readline (bs->stream, buf, count, offset, pnread);
}
else /* Buffered. */
{
......@@ -234,7 +243,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
len = bs->rbuffer.count;
if (len <= 0)
{
status = refill (bs);
status = refill (bs, offset);
if (status != 0 || bs->rbuffer.count == 0)
{
break;
......@@ -255,6 +264,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
len = ++nl - p;
bs->rbuffer.count -= len;
bs->rbuffer.ptr = nl;
bs->rbuffer.offset += len;
memcpy (s, p, len);
total += len;
s += len;
......@@ -262,6 +272,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
}
bs->rbuffer.count -= len;
bs->rbuffer.ptr += len;
bs->rbuffer.offset += len;
memcpy(s, p, len);
total += len;
s += len;
......@@ -279,10 +290,10 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
int
_stream_buffer_write (stream_t stream, const void *buf, size_t count,
size_t *pnwrite)
off_t offset, size_t *pnwrite)
{
struct _stream_buffer *bs = (struct _stream_buffer *)stream;
return stream_write (bs->stream, buf, count, pnwrite);
return stream_write (bs->stream, buf, count, offset, pnwrite);
}
int
......@@ -328,10 +339,10 @@ _stream_buffer_get_state (stream_t stream, enum stream_state *pstate)
}
int
_stream_buffer_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_buffer_is_seekable (stream_t stream)
{
struct _stream_buffer *bs = (struct _stream_buffer *)stream;
return stream_seek (bs->stream, off, whence);
return stream_is_seekable (bs->stream);
}
int
......@@ -390,7 +401,6 @@ static struct _stream_vtable _stream_buffer_vtable =
_stream_buffer_readline,
_stream_buffer_write,
_stream_buffer_seek,
_stream_buffer_tell,
_stream_buffer_get_size,
......@@ -401,6 +411,7 @@ static struct _stream_vtable _stream_buffer_vtable =
_stream_buffer_get_flags,
_stream_buffer_get_state,
_stream_buffer_is_seekable,
_stream_buffer_is_readready,
_stream_buffer_is_writeready,
_stream_buffer_is_exceptionpending,
......@@ -423,10 +434,14 @@ _stream_buffer_ctor (struct _stream_buffer *bs, stream_t stream,
}
void
_stream_buffer_dtor (struct _stream_buffer *bs)
_stream_buffer_dtor (stream_t stream)
{
struct _stream_buffer *bs = (struct _stream_buffer *)stream;
if (bs)
{
stream_destroy (&bs->stream);
mu_refcount_destroy (&bs->refcount);
}
}
int
......
......@@ -92,6 +92,50 @@ _attribute_default_clear_flags (attribute_t attribute)
return 0;
}
int
_attribute_default_get_userflags (attribute_t attribute, int *puserflags)
{
struct _attribute_default *da = (struct _attribute_default *)attribute;
mu_refcount_lock (da->refcount);
if (puserflags)
*puserflags = da->userflags;
mu_refcount_unlock (da->refcount);
return 0;
}
int
_attribute_default_set_userflags (attribute_t attribute, int userflags)
{
struct _attribute_default *da = (struct _attribute_default *)attribute;
mu_refcount_lock (da->refcount);
da->userflags |= (userflags | MU_ATTRIBUTE_MODIFIED);
mu_refcount_unlock (da->refcount);
return 0;
}
int
_attribute_default_unset_userflags (attribute_t attribute, int userflags)
{
struct _attribute_default *da = (struct _attribute_default *)attribute;
mu_refcount_lock (da->refcount);
da->userflags &= ~userflags;
/* If Modified was being unset do not reset it. */
if (!(userflags & MU_ATTRIBUTE_MODIFIED))
da->userflags |= MU_ATTRIBUTE_MODIFIED;
mu_refcount_unlock (da->refcount);
return 0;
}
int
_attribute_default_clear_userflags (attribute_t attribute)
{
struct _attribute_default *da = (struct _attribute_default *)attribute;
mu_refcount_lock (da->refcount);
da->userflags = 0;
mu_refcount_unlock (da->refcount);
return 0;
}
static struct _attribute_vtable _attribute_default_vtable =
{
_attribute_default_ref,
......@@ -100,7 +144,12 @@ static struct _attribute_vtable _attribute_default_vtable =
_attribute_default_get_flags,
_attribute_default_set_flags,
_attribute_default_unset_flags,
_attribute_default_clear_flags
_attribute_default_clear_flags,
_attribute_default_get_userflags,
_attribute_default_set_userflags,
_attribute_default_unset_userflags,
_attribute_default_clear_userflags
};
int
......@@ -115,8 +164,10 @@ _attribute_default_ctor (struct _attribute_default *da)
}
void
_attribute_default_dtor (struct _attribute_default *da)
_attribute_default_dtor (attribute_t attribute)
{
struct _attribute_default *da = (struct _attribute_default *)attribute;
if (da)
mu_refcount_destroy (&da->refcount);
}
......@@ -173,22 +224,36 @@ attribute_status_create (attribute_t *pattribute, const char *field)
{
switch (*field)
{
case 'r':
case 'R':
attribute_set_read (*pattribute);
break;
case 'O':
case 'o':
attribute_set_seen (*pattribute);
break;
case 'r':
case 'R':
attribute_set_read (*pattribute);
break;
case 'a':
case 'A':
attribute_set_answered (*pattribute);
break;
case 'd':
case 'D':
attribute_set_deleted (*pattribute);
break;
case 't':
case 'T':
attribute_set_draft (*pattribute);
break;
case 'f':
case 'F':
attribute_set_flagged (*pattribute);
break;
}
}
attribute_unset_modified (*pattribute);
......
......@@ -242,11 +242,15 @@ _lockfile_dotlock_ctor (struct _lockfile_dotlock *dotlock,
}
void
_lockfile_dotlock_dtor (struct _lockfile_dotlock *dotlock)
_lockfile_dotlock_dtor (lockfile_t lockfile)
{
struct _lockfile_dotlock *dotlock = (struct _lockfile_dotlock *)lockfile;
if (dotlock)
{
mu_refcount_destroy (&dotlock->refcount);
if (dotlock->fname)
free (dotlock->fname);
}
}
int
......
......@@ -93,7 +93,7 @@ _stream_fd_get_fd (stream_t stream, int *fd)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
if (fd == NULL || fds->fd == -1)
if (fd == NULL)
return MU_ERROR_INVALID_PARAMETER;
*fd = fds->fd;
......@@ -101,26 +101,44 @@ _stream_fd_get_fd (stream_t stream, int *fd)
}
int
_stream_fd_read (stream_t stream, void *buf, size_t buf_size, size_t *br)
_stream_fd_read (stream_t stream, void *buf, size_t buf_size, off_t offset,
size_t *br)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
int bytes = 0;
int status = 0;
if (fds->fd < 0)
{
if (br)
*br = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
fds->state = MU_STREAM_STATE_READ;
if (fds->offset != offset)
{
lseek (fds->fd, offset, SEEK_SET);
fds->offset = offset;
}
bytes = read (fds->fd, buf, buf_size);
if (bytes == -1)
{
bytes = 0;
status = errno;
}
else
fds->offset += bytes;
if (br)
*br = bytes;
return status;
}
int
_stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
_stream_fd_readline (stream_t stream, char *buf, size_t buflen,
off_t offset, size_t *br)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
int status = 0;
......@@ -128,9 +146,22 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
int nr = 0;
char c;
if (fds->fd < 0)
{
if (br)
*br = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
fds->state = MU_STREAM_STATE_READ;
if (fds->offset != offset)
{
lseek (fds->fd, offset, SEEK_SET);
fds->offset = offset;
}
/* Grossly inefficient hopefully they override this */
for (n = 1; n < buf_size; n++)
for (n = 1; n < buflen; n++)
{
nr = read (fds->fd, &c, 1);
if (nr == -1) /* Error. */
......@@ -151,20 +182,38 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
break; /* EOF, some data was read. */
}
}
if (buf)
*buf = '\0';
fds->offset = (n == buflen) ? n - 1: n;
if (br)
*br = (n == buf_size) ? n - 1: n;
*br = (n == buflen) ? n - 1: n;
return status;
}
int
_stream_fd_write (stream_t stream, const void *buf, size_t buf_size, size_t *bw)
_stream_fd_write (stream_t stream, const void *buf, size_t buf_size,
off_t offset, size_t *bw)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
int bytes = 0;
int status = 0;
if (fds->fd < 0)
{
if (bw)
*bw = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
fds->state = MU_STREAM_STATE_WRITE;
if (fds->offset != offset)
{
lseek (fds->fd, offset, SEEK_SET);
fds->offset = offset;
}
bytes = write (fds->fd, buf, buf_size);
if (bytes == -1)
{
......@@ -177,38 +226,24 @@ _stream_fd_write (stream_t stream, const void *buf, size_t buf_size, size_t *bw)
}
int
_stream_fd_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_fd_is_seekable (stream_t stream)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
int err = 0;
if (fds->fd)
{
if (whence == MU_STREAM_WHENCE_SET)
off = lseek (fds->fd, off, SEEK_SET);
else if (whence == MU_STREAM_WHENCE_CUR)
off = lseek (fds->fd, off, SEEK_CUR);
else if (whence == MU_STREAM_WHENCE_END)
off = lseek (fds->fd, off, SEEK_END);
else
err = MU_ERROR_INVALID_PARAMETER;
if (err == -1)
err = errno;
}
return err;
off_t off;
return _stream_fd_tell (stream, &off) == 0;
}
int
_stream_fd_tell (stream_t stream, off_t *off)
_stream_fd_tell (stream_t stream, off_t *poff)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
int err = 0;
if (off)
if (poff)
{
*off = lseek (fds->fd, 0, SEEK_CUR);
if (*off == -1)
*poff = lseek (fds->fd, 0, SEEK_CUR);
if (*poff == -1)
{
err = errno;
*off = 0;
*poff = 0;
}
}
return err;
......@@ -356,7 +391,6 @@ static struct _stream_vtable _stream_fd_vtable =
_stream_fd_readline,
_stream_fd_write,
_stream_fd_seek,
_stream_fd_tell,
_stream_fd_get_size,
......@@ -367,6 +401,7 @@ static struct _stream_vtable _stream_fd_vtable =
_stream_fd_get_flags,
_stream_fd_get_state,
_stream_fd_is_seekable,
_stream_fd_is_readready,
_stream_fd_is_writeready,
_stream_fd_is_exceptionpending,
......@@ -387,8 +422,10 @@ _stream_fd_ctor (struct _stream_fd *fds, int fd)
}
void
_stream_fd_dtor (struct _stream_fd *fds)
_stream_fd_dtor (stream_t stream)
{
struct _stream_fd *fds = (struct _stream_fd *)stream;
if (fds)
mu_refcount_destroy (&fds->refcount);
}
......
......@@ -53,21 +53,33 @@ _stream_stdio_destroy (stream_t *pstream)
}
int
_stream_stdio_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
_stream_stdio_read (stream_t stream, void *optr, size_t osize,
off_t offset,size_t *nbytes)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
size_t n = 0;
int err = 0;
if (fs->file)
if (!fs->file)
{
if (nbytes)
*nbytes = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
if (fs->offset != offset)
{
if (fseek (fs->file, offset, SEEK_SET) != 0)
return errno;
fs->offset = offset;
}
n = fread (optr, 1, osize, fs->file);
if (n == 0)
{
if (ferror(fs->file))
err = MU_ERROR_IO;
}
}
if (nbytes)
*nbytes = n;
......@@ -75,24 +87,41 @@ _stream_stdio_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
}
int
_stream_stdio_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes)
_stream_stdio_readline (stream_t stream, char *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
size_t n = 0;
int err = 0;
if (fs->file)
if (!fs->file)
{
if (nbytes)
*nbytes = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
if (fs->offset != offset)
{
if (fseek (fs->file, offset, SEEK_SET) != 0)
return errno;
fs->offset = offset;
}
if (fgets (optr, osize, fs->file) != NULL)
{
n = strlen (optr);
/* Oh My!! */
if (n == 0)
n++;
else
fs->offset += n;
}
else
{
if (ferror (fs->file))
err = MU_ERROR_IO;
}
}
if (nbytes)
*nbytes = n;
......@@ -100,14 +129,27 @@ _stream_stdio_readline (stream_t stream, char *optr, size_t osize, size_t *nbyte
}
int
_stream_stdio_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes)
_stream_stdio_write (stream_t stream, const void *iptr, size_t isize,
off_t offset, size_t *nbytes)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
size_t n = 0;
int err = 0;
if (fs->file)
if (!fs->file)
{
if (nbytes)
*nbytes = 0;
return MU_ERROR_BAD_FILE_DESCRIPTOR;
}
if (fs->offset != offset)
{
if (fseek (fs->file, offset, SEEK_SET) != 0)
return errno;
fs->offset = offset;
}
n = fwrite (iptr, 1, isize, fs->file);
if (n != isize)
{
......@@ -116,7 +158,8 @@ _stream_stdio_write (stream_t stream, const void *iptr, size_t isize, size_t *nb
clearerr(fs->file);
n = 0;
}
}
else
fs->offset += n;
if (nbytes)
*nbytes = n;
......@@ -168,40 +211,37 @@ _stream_stdio_get_fd (stream_t stream, int *pfd)
if (fs->file)
*pfd = fileno (fs->file);
else
status = MU_ERROR_INVALID_PARAMETER;
status = MU_ERROR_BAD_FILE_DESCRIPTOR;
}
return status;
}
int
_stream_stdio_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_stdio_is_seekable (stream_t stream)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
int err = 0;
if (fs->file)
{
if (whence == MU_STREAM_WHENCE_SET)
err = fseek (fs->file, off, SEEK_SET);
else if (whence == MU_STREAM_WHENCE_CUR)
err = fseek (fs->file, off, SEEK_CUR);
else if (whence == MU_STREAM_WHENCE_END)
err = fseek (fs->file, off, SEEK_END);
else
err = MU_ERROR_INVALID_PARAMETER;
if (err == -1)
err = errno;
}
return err;
off_t off;
return _stream_stdio_tell (stream, &off) == 0;
}
int
_stream_stdio_tell (stream_t stream, off_t *off)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
int status = 0;
if (off == NULL)
return MU_ERROR_INVALID_PARAMETER;
*off = (fs->file) ? ftell (fs->file) : 0;
return 0;
if (fs->file)
{
*off = ftell (fs->file);
if (*off == -1)
{
*off = 0;
status = errno;
}
}
else
status = MU_ERROR_BAD_FILE_DESCRIPTOR;
return status;
}
int
......@@ -380,7 +420,6 @@ static struct _stream_vtable _stream_stdio_vtable =
_stream_stdio_readline,
_stream_stdio_write,
_stream_stdio_seek,
_stream_stdio_tell,
_stream_stdio_get_size,
......@@ -391,6 +430,7 @@ static struct _stream_vtable _stream_stdio_vtable =
_stream_stdio_get_flags,
_stream_stdio_get_state,
_stream_stdio_is_seekable,
_stream_stdio_is_readready,
_stream_stdio_is_writeready,
_stream_stdio_is_exceptionpending,
......@@ -411,11 +451,15 @@ _stream_stdio_ctor (struct _stream_stdio *fs, FILE *fp)
}
void
_stream_stdio_dtor (struct _stream_stdio *fs)
_stream_stdio_dtor (stream_t stream)
{
struct _stream_stdio *fs = (struct _stream_stdio *)stream;
if (fs)
{
mu_refcount_destroy (&fs->refcount);
/* We may leak if they did not close the FILE * */
fs->file = NULL;
}
}
int
......
......@@ -33,14 +33,14 @@ extern "C" {
struct _attribute;
typedef struct _attribute * attribute_t;
#define MU_ATTRIBUTE_ANSWERED 0x00001
#define MU_ATTRIBUTE_FLAGGED 0x00002
#define MU_ATTRIBUTE_DELETED 0x00004
#define MU_ATTRIBUTE_DRAFT 0x00008
#define MU_ATTRIBUTE_SEEN 0x00010
#define MU_ATTRIBUTE_READ 0x00020
#define MU_ATTRIBUTE_MODIFIED 0x10000
#define MU_ATTRIBUTE_RECENT 0x00000
#define MU_ATTRIBUTE_ANSWERED 0x000001
#define MU_ATTRIBUTE_FLAGGED 0x000002
#define MU_ATTRIBUTE_DELETED 0x000004
#define MU_ATTRIBUTE_DRAFT 0x000008
#define MU_ATTRIBUTE_SEEN 0x000010
#define MU_ATTRIBUTE_READ 0x000020
#define MU_ATTRIBUTE_MODIFIED 0x100000
#define MU_ATTRIBUTE_RECENT 0x000000
extern int attribute_ref __P ((attribute_t));
extern void attribute_destroy __P ((attribute_t *));
......@@ -72,6 +72,12 @@ extern int attribute_unset_recent __P ((attribute_t));
extern int attribute_unset_read __P ((attribute_t));
extern int attribute_unset_modified __P ((attribute_t));
extern int attribute_is_userflags __P ((attribute_t, int));
extern int attribute_set_userflags __P ((attribute_t, int));
extern int attribute_unset_userflags __P ((attribute_t, int));
extern int attribute_get_userflags __P ((attribute_t, int *));
extern int attribute_clear_userflags __P ((attribute_t));
extern int attribute_get_flags __P ((attribute_t, int *));
extern int attribute_set_flags __P ((attribute_t, int));
......
......@@ -142,6 +142,11 @@ extern "C" {
# define MU_ERROR_NO_DIRECTORY (MU_ERROR_RANGE + 17)
#endif
#if defined (EBADFD)
# define MU_ERROR_BAD_FILE_DESCRIPTOR EBADFD
#else
# define MU_ERROR_BAD_FILE_DESCRIPTOR (MU_ERROR_RANGE + 18)
#endif
#ifdef __cplusplus
}
......
......@@ -20,6 +20,7 @@
#include <mailutils/stream.h>
#include <mailutils/attribute.h>
#include <mailutils/debug.h>
#ifdef __cplusplus
extern "C" {
......@@ -46,12 +47,6 @@ extern int mbox_get_uidnext __P ((mbox_t, unsigned long *));
extern int mbox_open __P ((mbox_t, const char *, int));
extern int mbox_close __P ((mbox_t));
extern int mbox_get_attribute __P ((mbox_t, unsigned int, attribute_t *));
extern int mbox_get_uid __P ((mbox_t, unsigned int, unsigned long *));
extern int mbox_get_separator __P ((mbox_t, unsigned int, char **));
extern int mbox_set_separator __P ((mbox_t, unsigned int, const char *));
extern int mbox_get_hstream __P ((mbox_t, unsigned int, stream_t *));
extern int mbox_set_hstream __P ((mbox_t, unsigned int, stream_t));
extern int mbox_get_hsize __P ((mbox_t, unsigned int, unsigned int *));
......@@ -62,44 +57,42 @@ extern int mbox_set_bstream __P ((mbox_t, unsigned int, stream_t));
extern int mbox_get_bsize __P ((mbox_t, unsigned int, unsigned int *));
extern int mbox_get_blines __P ((mbox_t, unsigned int, unsigned int *));
extern int mbox_get_attribute __P ((mbox_t, unsigned int, attribute_t *));
extern int mbox_get_uid __P ((mbox_t, unsigned int, unsigned long *));
extern int mbox_get_size __P ((mbox_t, off_t *));
extern int mbox_get_separator __P ((mbox_t, unsigned int, char **));
extern int mbox_set_separator __P ((mbox_t, unsigned int, const char *));
extern int mbox_save_attributes __P ((mbox_t));
extern int mbox_expunge __P ((mbox_t, int));
extern int mbox_has_newmail __P ((mbox_t));
extern int mbox_set_progress_cb
__P ((mbox_t, int (*) __P ((int, void *)), void *));
extern int mbox_set_newmsg_cb
__P ((mbox_t, int (*) __P ((int, void *)), void *));
extern int mbox_newmsg_cb __P ((mbox_t, int));
extern int mbox_progress_cb __P ((mbox_t, int));
extern int mbox_set_progress_cb __P ((mbox_t,
int (*) __P ((int, void *)), void *));
extern int mbox_set_newmsg_cb __P ((mbox_t,
int (*) __P ((int, void *)), void *));
extern int mbox_set_error_cb __P ((mbox_t,
int (*) __P ((int, void *)), void *));
extern int mbox_scan __P ((mbox_t, unsigned int, unsigned int *, int));
extern int mbox_messages_count __P ((mbox_t, unsigned int *));
extern int mbox_scan __P ((mbox_t, unsigned int,
unsigned int *, int));
extern int mbox_append __P ((mbox_t, const char *, attribute_t, stream_t));
extern int mbox_append_hb
__P ((mbox_t, const char *, attribute_t, stream_t, stream_t));
extern int mbox_append_hb0
__P ((mbox_t, const char *, attribute_t, int, stream_t, stream_t));
extern int mbox_append __P ((mbox_t, const char *, attribute_t,
stream_t));
extern int mbox_append_hb __P ((mbox_t, const char *, attribute_t,
stream_t, stream_t));
extern int mbox_get_carrier __P ((mbox_t, stream_t *));
extern int mbox_set_carrier __P ((mbox_t, stream_t));
extern int mbox_set_hcache __P ((mbox_t, const char **, size_t));
extern int mbox_set_hcache_default __P ((mbox_t));
extern void mbox_hcache_free __P ((mbox_t, unsigned int));
extern int mbox_hcache_append __P ((mbox_t, unsigned int, const char *,
const char *));
extern int mbox_add_hcache __P ((mbox_t, const char **, size_t));
extern int mbox_header_get_value __P ((mbox_t, unsigned int, const char *,
extern int mbox_value_hcache __P ((mbox_t, unsigned int, const char *,
char *, size_t, size_t *));
extern int stream_mbox_create __P ((stream_t *, mbox_t, unsigned int, int));
extern int attribute_mbox_create __P ((attribute_t *, mbox_t, unsigned int));
extern int mbox_attribute_to_status
__P ((attribute_t, char *, size_t, size_t *));
extern int mbox_get_debug __P ((mbox_t, mu_debug_t *));
extern int mbox_set_debug __P ((mbox_t, mu_debug_t));
#ifdef __cplusplus
}
......
......@@ -32,13 +32,6 @@ extern "C" {
#define MU_STREAM_CREAT 0x00000008
#define MU_STREAM_NONBLOCK 0x00000010
enum stream_whence
{
MU_STREAM_WHENCE_SET,
MU_STREAM_WHENCE_CUR,
MU_STREAM_WHENCE_END
};
enum stream_state
{
MU_STREAM_NO_STATE,
......@@ -57,11 +50,10 @@ extern void stream_destroy __P ((stream_t *));
extern int stream_open __P ((stream_t, const char *, int, int));
extern int stream_close __P ((stream_t));
extern int stream_read __P ((stream_t, void *, size_t, size_t *));
extern int stream_readline __P ((stream_t, char *, size_t, size_t *));
extern int stream_write __P ((stream_t, const void *, size_t, size_t*));
extern int stream_read __P ((stream_t, void *, size_t, off_t, size_t *));
extern int stream_readline __P ((stream_t, char *, size_t, off_t, size_t *));
extern int stream_write __P ((stream_t, const void *, size_t, off_t, size_t*));
extern int stream_seek __P ((stream_t, off_t, enum stream_whence));
extern int stream_tell __P ((stream_t, off_t *));
extern int stream_get_size __P ((stream_t, off_t *));
......@@ -72,6 +64,7 @@ extern int stream_get_fd __P ((stream_t , int *));
extern int stream_get_flags __P ((stream_t, int *));
extern int stream_get_state __P ((stream_t, enum stream_state *));
extern int stream_is_seekable __P ((stream_t));
extern int stream_is_readready __P ((stream_t, int));
extern int stream_is_writeready __P ((stream_t, int));
extern int stream_is_exceptionpending __P ((stream_t, int));
......
......@@ -45,6 +45,11 @@ struct _attribute_vtable
int (*set_flags) __P ((attribute_t, int));
int (*unset_flags) __P ((attribute_t, int));
int (*clear_flags) __P ((attribute_t));
int (*get_userflags) __P ((attribute_t, int *));
int (*set_userflags) __P ((attribute_t, int));
int (*unset_userflags) __P ((attribute_t, int));
int (*clear_userflags) __P ((attribute_t));
};
struct _attribute
......
......@@ -18,6 +18,10 @@
#ifndef MAILUTILS_SYS_BSTREAM_H
#define MAILUTILS_SYS_BSTREAM_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/sys/stream.h>
#include <mailutils/refcount.h>
......@@ -31,6 +35,7 @@ struct _rbuffer
char *base;
char *ptr;
int count;
off_t offset;
size_t bufsize;
};
......@@ -43,22 +48,22 @@ struct _stream_buffer
};
extern int _stream_buffer_ctor __P ((struct _stream_buffer *, stream_t, size_t));
extern void _stream_buffer_dtor __P ((struct _stream_buffer *));
extern void _stream_buffer_dtor __P ((stream_t));
extern int _stream_buffer_ref __P ((stream_t));
extern void _stream_buffer_destroy __P ((stream_t *));
extern int _stream_buffer_open __P ((stream_t, const char *, int, int));
extern int _stream_buffer_close __P ((stream_t));
extern int _stream_buffer_read __P ((stream_t, void *, size_t, size_t *));
extern int _stream_buffer_readline __P ((stream_t, char *, size_t, size_t *));
extern int _stream_buffer_write __P ((stream_t, const void *, size_t, size_t *));
extern int _stream_buffer_read __P ((stream_t, void *, size_t, off_t, size_t *));
extern int _stream_buffer_readline __P ((stream_t, char *, size_t, off_t, size_t *));
extern int _stream_buffer_write __P ((stream_t, const void *, size_t, off_t, size_t *));
extern int _stream_buffer_get_fd __P ((stream_t, int *));
extern int _stream_buffer_get_flags __P ((stream_t, int *));
extern int _stream_buffer_get_size __P ((stream_t, off_t *));
extern int _stream_buffer_truncate __P ((stream_t, off_t));
extern int _stream_buffer_flush __P ((stream_t));
extern int _stream_buffer_get_state __P ((stream_t, enum stream_state *));
extern int _stream_buffer_seek __P ((stream_t, off_t, enum stream_whence));
extern int _stream_buffer_tell __P ((stream_t, off_t *));
extern int _stream_buffer_is_seekable __P ((stream_t));
extern int _stream_buffer_is_readready __P ((stream_t, int ));
extern int _stream_buffer_is_writeready __P ((stream_t, int));
extern int _stream_buffer_is_exceptionpending __P ((stream_t, int));
......
......@@ -35,10 +35,11 @@ struct _attribute_default
struct _attribute base;
mu_refcount_t refcount;
int flags;
int userflags;
};
extern int _attribute_default_ctor __P ((struct _attribute_default *));
extern void _attribute_default_dtor __P ((struct _attribute_default *));
extern void _attribute_default_dtor __P ((attribute_t));
extern int _attribute_default_ref __P ((attribute_t));
extern void _attribute_default_destroy __P ((attribute_t *));
......@@ -47,6 +48,11 @@ extern int _attribute_default_set_flags __P ((attribute_t, int));
extern int _attribute_default_unset_flags __P ((attribute_t, int));
extern int _attribute_default_clear_flags __P ((attribute_t));
extern int _attribute_default_get_userflags __P ((attribute_t, int *));
extern int _attribute_default_set_userflags __P ((attribute_t, int));
extern int _attribute_default_unset_userflags __P ((attribute_t, int));
extern int _attribute_default_clear_userflags __P ((attribute_t));
#ifdef __cplusplus
}
#endif
......
......@@ -49,7 +49,7 @@ struct _lockfile_dotlock
};
extern int _lockfile_dotlock_ctor __P ((struct _lockfile_dotlock *, const char *));
extern void _lockfile_dotlock_dtor __P ((struct _lockfile_dotlock *));
extern void _lockfile_dotlock_dtor __P ((lockfile_t));
extern int _lockfile_dotlock_ref __P ((lockfile_t));
extern void _lockfile_dotlock_destroy __P ((lockfile_t *));
......
......@@ -18,6 +18,10 @@
#ifndef MAILUTILS_SYS_FDSTREAM_H
#define MAILUTILS_SYS_FDSTREAM_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/refcount.h>
#include <mailutils/sys/stream.h>
......@@ -32,27 +36,28 @@ struct _stream_fd
int fd;
int state;
int flags;
off_t offset;
};
int _stream_fd_ctor __P ((struct _stream_fd *, int));
void _stream_fd_dtor __P ((struct _stream_fd *));
void _stream_fd_dtor __P ((stream_t));
int _stream_fd_ref __P ((stream_t));
void _stream_fd_destroy __P ((stream_t *));
int _stream_fd_open __P ((stream_t, const char *, int, int));
int _stream_fd_close __P ((stream_t));
int _stream_fd_read __P ((stream_t, void *, size_t, size_t *));
int _stream_fd_readline __P ((stream_t, char *, size_t, size_t *));
int _stream_fd_write __P ((stream_t, const void *, size_t, size_t *));
int _stream_fd_read __P ((stream_t, void *, size_t, off_t, size_t *));
int _stream_fd_readline __P ((stream_t, char *, size_t, off_t, size_t *));
int _stream_fd_write __P ((stream_t, const void *, size_t, off_t, size_t *));
int _stream_fd_get_fd __P ((stream_t, int *));
int _stream_fd_get_flags __P ((stream_t, int *));
int _stream_fd_get_size __P ((stream_t, off_t *));
int _stream_fd_truncate __P ((stream_t, off_t));
int _stream_fd_flush __P ((stream_t));
int _stream_fd_get_state __P ((stream_t, enum stream_state *));
int _stream_fd_seek __P ((stream_t, off_t, enum stream_whence));
int _stream_fd_tell __P ((stream_t, off_t *));
int _stream_fd_is_readready __P ((stream_t, int ));
int _stream_fd_is_seekable __P ((stream_t));
int _stream_fd_is_readready __P ((stream_t, int));
int _stream_fd_is_writeready __P ((stream_t, int));
int _stream_fd_is_exceptionpending __P ((stream_t, int));
int _stream_fd_is_open __P ((stream_t));
......
......@@ -18,8 +18,11 @@
#ifndef _MAILUTILS_SYS_FOLDER_H
#define _MAILUTILS_SYS_FOLDER_H
#include <mailutils/folder.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/folder.h>
#ifdef __cplusplus
extern "C" {
......
......@@ -18,6 +18,10 @@
#ifndef MAILUTILS_SYS_FSTREAM_H
#define MAILUTILS_SYS_FSTREAM_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/sys/stream.h>
#include <mailutils/refcount.h>
......@@ -30,27 +34,28 @@ struct _stream_stdio
struct _stream base;
mu_refcount_t refcount;
int flags;
off_t offset;
FILE *file;
};
extern int _stream_stdio_ctor __P ((struct _stream_stdio *, FILE *));
extern void _stream_stdio_dtor __P ((struct _stream_stdio *));
extern void _stream_stdio_dtor __P ((stream_t));
extern int _stream_stdio_ref __P ((stream_t));
extern void _stream_stdio_destroy __P ((stream_t *));
extern int _stream_stdio_open __P ((stream_t, const char *, int, int));
extern int _stream_stdio_close __P ((stream_t));
extern int _stream_stdio_read __P ((stream_t, void *, size_t, size_t *));
extern int _stream_stdio_readline __P ((stream_t, char *, size_t, size_t *));
extern int _stream_stdio_write __P ((stream_t, const void *, size_t, size_t *));
extern int _stream_stdio_read __P ((stream_t, void *, size_t, off_t, size_t *));
extern int _stream_stdio_readline __P ((stream_t, char *, size_t, off_t, size_t *));
extern int _stream_stdio_write __P ((stream_t, const void *, size_t, off_t, size_t *));
extern int _stream_stdio_get_fd __P ((stream_t, int *));
extern int _stream_stdio_get_flags __P ((stream_t, int *));
extern int _stream_stdio_get_size __P ((stream_t, off_t *));
extern int _stream_stdio_truncate __P ((stream_t, off_t));
extern int _stream_stdio_flush __P ((stream_t));
extern int _stream_stdio_get_state __P ((stream_t, enum stream_state *));
extern int _stream_stdio_seek __P ((stream_t, off_t, enum stream_whence));
extern int _stream_stdio_tell __P ((stream_t, off_t *));
extern int _stream_stdio_is_readready __P ((stream_t, int ));
extern int _stream_stdio_is_seekable __P ((stream_t));
extern int _stream_stdio_is_readready __P ((stream_t, int));
extern int _stream_stdio_is_writeready __P ((stream_t, int));
extern int _stream_stdio_is_exceptionpending __P ((stream_t, int));
extern int _stream_stdio_is_open __P ((stream_t));
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_HEADER_H
#define _MAILUTILS_SYS_HEADER_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/header.h>
#ifndef __P
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_ITERATOR_H
#define _MAILUTILS_SYS_ITERATOR_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/iterator.h>
#ifdef __cplusplus
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_MAILBOX_H
#define _MAILUTILS_SYS_MAILBOX_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/mailbox.h>
#ifdef __cplusplus
......
......@@ -20,6 +20,10 @@
#include <unistd.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/sys/stream.h>
#include <mailutils/refcount.h>
......@@ -38,27 +42,26 @@ struct _stream_mmap
int mflags;
char *ptr;
size_t size;
off_t offset;
};
extern int _stream_mmap_ctor __P ((struct _stream_mmap *));
extern void _stream_mmap_dtor __P ((struct _stream_mmap *));
extern void _stream_mmap_dtor __P ((stream_t));
extern int _stream_mmap_ref __P ((stream_t));
extern void _stream_mmap_destroy __P ((stream_t *));
extern int _stream_mmap_open __P ((stream_t, const char *, int, int));
extern int _stream_mmap_close __P ((stream_t));
extern int _stream_mmap_read __P ((stream_t, void *, size_t, size_t *));
extern int _stream_mmap_readline __P ((stream_t, char *, size_t, size_t *));
extern int _stream_mmap_write __P ((stream_t, const void *, size_t, size_t *));
extern int _stream_mmap_read __P ((stream_t, void *, size_t, off_t, size_t *));
extern int _stream_mmap_readline __P ((stream_t, char *, size_t, off_t, size_t *));
extern int _stream_mmap_write __P ((stream_t, const void *, size_t, off_t, size_t *));
extern int _stream_mmap_get_fd __P ((stream_t, int *));
extern int _stream_mmap_get_flags __P ((stream_t, int *));
extern int _stream_mmap_get_size __P ((stream_t, off_t *));
extern int _stream_mmap_truncate __P ((stream_t, off_t));
extern int _stream_mmap_flush __P ((stream_t));
extern int _stream_mmap_get_state __P ((stream_t, enum stream_state *));
extern int _stream_mmap_seek __P ((stream_t, off_t, enum stream_whence));
extern int _stream_mmap_tell __P ((stream_t, off_t *));
extern int _stream_mmap_is_readready __P ((stream_t, int ));
extern int _stream_mmap_is_seekable __P ((stream_t));
extern int _stream_mmap_is_readready __P ((stream_t, int));
extern int _stream_mmap_is_writeready __P ((stream_t, int));
extern int _stream_mmap_is_exceptionpending __P ((stream_t, int));
extern int _stream_mmap_is_open __P ((stream_t));
......
......@@ -19,9 +19,18 @@
#define _MAILUTILS_SYS_MBOX_H
#include <time.h>
#include <stdarg.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/lockfile.h>
#include <mailutils/mbox.h>
#define MU_MBOX_HSTREAM_SET 0x010000
#define MU_MBOX_BSTREAM_SET 0x001000
#ifdef __cplusplus
extern "C" {
#endif
......@@ -49,6 +58,7 @@ struct _mbox
stream_t carrier; /* File stream. */
off_t size; /* Size of the mailbox. */
mu_debug_t debug;
unsigned long uidvalidity;
unsigned long uidnext;
char *filename;
......@@ -69,7 +79,10 @@ struct _mbox
{
int (*cb) __P ((int, void *));
void *arg;
} newmsg, progress, corrupt;
} newmsg, progress, error;
/* Hold the offset of the stream when appending. */
off_t roffset, woffset;
};
/* Keep the file positions of where the headers and bodies start and end.
......@@ -96,9 +109,40 @@ struct _mbox_message
/* UID i.e. see IMAP */
unsigned long uid;
unsigned int attr_flags;
unsigned int attr_userflags;
attribute_t attribute; /* The attr_flags contains the "Status:" attribute */
};
extern int mbox_newmsg_cb __P ((mbox_t, int));
extern int mbox_progress_cb __P ((mbox_t, int));
extern int mbox_error_cb __P ((mbox_t, int));
extern int mbox_append_hb0 __P ((mbox_t, const char *, attribute_t,
stream_t, stream_t, int, unsigned long));
extern void mbox_release_hcache __P ((mbox_t, unsigned int));
extern int mbox_append_hcache __P ((mbox_t, unsigned int, const char *,
const char *));
extern int mbox_set_default_hcache __P ((mbox_t));
extern int mbox_debug_print __P ((mbox_t, const char *, ...));
extern int stream_mbox_create __P ((stream_t *, mbox_t, unsigned int, int));
extern int stream_mbox_msgno __P ((stream_t, unsigned int));
extern void _stream_mbox_dtor __P ((stream_t));
extern int attribute_mbox_create __P ((attribute_t *, mbox_t, unsigned int));
extern int attribute_mbox_msgno __P ((attribute_t, unsigned int));
extern int mbox_attribute_to_status __P ((attribute_t, char *, size_t,
size_t *));
extern void _attribute_mbox_dtor __P ((attribute_t));
extern void mbox_release_separator __P ((mbox_t, unsigned int));
extern void mbox_release_attribute __P ((mbox_t, unsigned int));
extern void mbox_release_hstream __P ((mbox_t, unsigned int));
extern void mbox_release_bstream __P ((mbox_t, unsigned int));
extern void mbox_release_msg __P ((mbox_t, unsigned int));
#ifdef __cplusplus
}
#endif
......
......@@ -20,6 +20,10 @@
#include <sys/types.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/refcount.h>
#include <mailutils/sys/stream.h>
......@@ -38,27 +42,26 @@ struct _stream_memory
char *ptr;
size_t capacity;
size_t size;
off_t offset;
int flags;
};
extern int _stream_memory_ctor __P ((struct _stream_memory *, size_t));
extern void _stream_memory_dtor __P ((struct _stream_memory *));
extern void _stream_memory_dtor __P ((stream_t));
extern int _stream_memory_ref __P ((stream_t));
extern void _stream_memory_destroy __P ((stream_t *));
extern int _stream_memory_open __P ((stream_t, const char *, int, int));
extern int _stream_memory_close __P ((stream_t));
extern int _stream_memory_read __P ((stream_t, void *, size_t, size_t *));
extern int _stream_memory_readline __P ((stream_t, char *, size_t, size_t *));
extern int _stream_memory_write __P ((stream_t, const void *, size_t, size_t *));
extern int _stream_memory_read __P ((stream_t, void *, size_t, off_t, size_t *));
extern int _stream_memory_readline __P ((stream_t, char *, size_t, off_t, size_t *));
extern int _stream_memory_write __P ((stream_t, const void *, size_t, off_t, size_t *));
extern int _stream_memory_get_fd __P ((stream_t, int *));
extern int _stream_memory_get_flags __P ((stream_t, int *));
extern int _stream_memory_get_size __P ((stream_t, off_t *));
extern int _stream_memory_truncate __P ((stream_t, off_t));
extern int _stream_memory_flush __P ((stream_t));
extern int _stream_memory_get_state __P ((stream_t, enum stream_state *));
extern int _stream_memory_seek __P ((stream_t, off_t, enum stream_whence));
extern int _stream_memory_tell __P ((stream_t, off_t *));
extern int _stream_memory_is_seekable __P ((stream_t));
extern int _stream_memory_is_readready __P ((stream_t, int ));
extern int _stream_memory_is_writeready __P ((stream_t, int));
extern int _stream_memory_is_exceptionpending __P ((stream_t, int));
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_MESSAGE_H
#define _MAILUTILS_SYS_MESSAGE_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/message.h>
#ifndef __P
......
......@@ -102,6 +102,7 @@ struct _pop3
enum pop3_state state;
stream_t carrier; /* TCP Connection. */
off_t offset; /* To synchronise with the buffering. */
mu_debug_t debug; /* Send the debug info. */
};
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_PTICKET_H
#define _MAILUTILS_SYS_PTICKET_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/sys/ticket.h>
#ifdef __cplusplus
......@@ -31,7 +35,7 @@ struct _ticket_prompt
};
extern int _ticket_prompt_ctor __P ((struct _ticket_prompt *));
extern void _ticket_prompt_dtor __P ((struct _ticket_prompt *));
extern void _ticket_prompt_dtor __P ((ticket_t));
extern int _ticket_prompt_ref __P ((ticket_t));
extern void _ticket_prompt_destroy __P ((ticket_t *));
extern int _ticket_prompt_pop __P ((ticket_t, const char *, char **));
......
......@@ -34,12 +34,13 @@ struct _mu_debug_stream
struct _mu_debug base;
mu_refcount_t refcount;
int level;
off_t offset;
stream_t stream;
int close_on_destroy;
};
int _mu_debug_stream_ctor __P ((struct _mu_debug_stream *));
int _mu_debug_stream_dtor __P ((struct _mu_debug_stream *));
int _mu_debug_stream_dtor __P ((mu_debug_t));
int _mu_debug_stream_ref __P ((mu_debug_t));
void _mu_debug_stream_destroy __P ((mu_debug_t *));
int _mu_debug_stream_set_level __P ((mu_debug_t, size_t));
......
......@@ -18,6 +18,10 @@
#ifndef _MAILUTILS_SYS_STREAM_H
#define _MAILUTILS_SYS_STREAM_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/stream.h>
#ifdef __cplusplus
......@@ -32,11 +36,10 @@ struct _stream_vtable
int (*open) __P ((stream_t, const char *, int, int));
int (*close) __P ((stream_t));
int (*read) __P ((stream_t, void *, size_t, size_t *));
int (*readline) __P ((stream_t, char *, size_t, size_t *));
int (*write) __P ((stream_t, const void *, size_t, size_t *));
int (*read) __P ((stream_t, void *, size_t, off_t, size_t *));
int (*readline) __P ((stream_t, char *, size_t, off_t, size_t *));
int (*write) __P ((stream_t, const void *, size_t, off_t, size_t *));
int (*seek) __P ((stream_t, off_t, enum stream_whence));
int (*tell) __P ((stream_t, off_t *));
int (*get_size) __P ((stream_t, off_t *));
......@@ -47,6 +50,7 @@ struct _stream_vtable
int (*get_flags) __P ((stream_t, int *));
int (*get_state) __P ((stream_t, enum stream_state *));
int (*is_seekable) __P ((stream_t));
int (*is_readready) __P ((stream_t, int));
int (*is_writeready) __P ((stream_t, int));
int (*is_exceptionpending) __P ((stream_t, int));
......
......@@ -18,6 +18,10 @@
#ifndef MAILUTILS_SYS_TCP_H
#define MAILUTILS_SYS_TCP_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <mailutils/refcount.h>
#include <mailutils/sys/fdstream.h>
......
......@@ -171,7 +171,7 @@ mu_list_remove (mu_list_t list, void *item)
}
int
mu_list_get (mu_list_t list, size_t index, void **pitem)
mu_list_get (mu_list_t list, size_t indx, void **pitem)
{
struct mu_list_data *current;
size_t count;
......@@ -182,7 +182,7 @@ mu_list_get (mu_list_t list, size_t index, void **pitem)
for (current = list->head.next, count = 0; current != &(list->head);
current = current->next, count++)
{
if (count == index)
if (count == indx)
{
*pitem = current->item;
status = 0;
......
......@@ -59,7 +59,8 @@ _stream_mmap_destroy (stream_t *pstream)
}
int
_stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
_stream_mmap_read (stream_t stream, void *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
size_t n = 0;
......@@ -67,12 +68,10 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
mu_refcount_lock (ms->refcount);
if (ms->ptr != MAP_FAILED && ms->ptr)
{
if (ms->offset < (off_t)ms->size)
if (offset < (off_t)ms->size)
{
n = ((ms->offset + osize) > ms->size) ?
ms->size - ms->offset : osize;
memcpy (optr, ms->ptr + ms->offset, n);
ms->offset += n;
n = ((offset + osize) > ms->size) ? ms->size - offset : osize;
memcpy (optr, ms->ptr + offset, n);
}
}
mu_refcount_unlock (ms->refcount);
......@@ -83,7 +82,8 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
}
int
_stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes)
_stream_mmap_readline (stream_t stream, char *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
size_t n = 0;
......@@ -91,17 +91,17 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes
mu_refcount_lock (ms->refcount);
if (ms->ptr != MAP_FAILED && ms->ptr)
{
if (ms->offset < (off_t)ms->size)
if (offset < (off_t)ms->size)
{
/* Save space for the null byte. */
char *nl;
osize--;
nl = memchr (ms->ptr + ms->offset, '\n', ms->size - ms->offset);
n = (nl) ? nl - (ms->ptr + ms->offset) + 1 : ms->size - ms->offset;
nl = memchr (ms->ptr + offset, '\n', ms->size - offset);
n = (nl) ? (size_t)(nl - (ms->ptr + offset) + 1) : ms->size - offset;
n = (n > osize) ? osize : n;
memcpy (optr, ms->ptr + ms->offset, n);
memcpy (optr, ms->ptr + offset, n);
optr[n] = '\0';
ms->offset += n;
offset += n;
}
}
mu_refcount_unlock (ms->refcount);
......@@ -112,7 +112,8 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes
}
int
_stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes)
_stream_mmap_write (stream_t stream, const void *iptr, size_t isize,
off_t offset, size_t *nbytes)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
int err = 0;
......@@ -122,17 +123,17 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby
if (ms->mflags & PROT_WRITE)
{
/* Bigger we have to remmap. */
if (ms->size < (ms->offset + isize))
if (ms->size < (offset + isize))
{
if (ms->ptr != MAP_FAILED && munmap (ms->ptr, ms->size) == 0)
{
ms->ptr = MAP_FAILED;
if (ftruncate (ms->fd, ms->offset + isize) == 0)
if (ftruncate (ms->fd, offset + isize) == 0)
{
ms->ptr = mmap (0, ms->offset + isize, ms->mflags,
ms->ptr = mmap (0, offset + isize, ms->mflags,
MAP_SHARED, ms->fd, 0);
if (ms->ptr != MAP_FAILED)
ms->size = ms->offset + isize;
ms->size = offset + isize;
}
}
}
......@@ -140,8 +141,7 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby
if (ms->ptr != MAP_FAILED)
{
if (isize > 0)
memcpy (ms->ptr + ms->offset, iptr, isize);
ms->offset += isize;
memcpy (ms->ptr + offset, iptr, isize);
n = isize;
}
else
......@@ -274,38 +274,26 @@ _stream_mmap_get_state (stream_t stream, enum stream_state *state)
}
int
_stream_mmap_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_mmap_is_seekable (stream_t stream)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
off_t noff = ms->offset;
int err = 0;
if (whence == MU_STREAM_WHENCE_SET)
noff = off;
else if (whence == MU_STREAM_WHENCE_CUR)
noff += off;
else if (whence == MU_STREAM_WHENCE_END)
noff = ms->size + off;
else
noff = -1; /* error. */
if (noff >= 0)
{
if (noff > ms->offset)
_stream_mmap_truncate (stream, noff);
ms->offset = noff;
}
else
err = MU_ERROR_INVALID_PARAMETER;
return err;
off_t off;
return _stream_mmap_tell (stream, &off) == 0;
}
int
_stream_mmap_tell (stream_t stream, off_t *off)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
int status = 0;
if (off == NULL)
return MU_ERROR_INVALID_PARAMETER;
*off = ms->offset;
return 0;
*off = lseek (ms->fd, 0, SEEK_SET);
if (*off == -1)
{
status = errno;
*off = 0;
}
return status;
}
int
......@@ -451,7 +439,6 @@ static struct _stream_vtable _stream_mmap_vtable =
_stream_mmap_readline,
_stream_mmap_write,
_stream_mmap_seek,
_stream_mmap_tell,
_stream_mmap_get_size,
......@@ -462,6 +449,7 @@ static struct _stream_vtable _stream_mmap_vtable =
_stream_mmap_get_flags,
_stream_mmap_get_state,
_stream_mmap_is_seekable,
_stream_mmap_is_readready,
_stream_mmap_is_writeready,
_stream_mmap_is_exceptionpending,
......@@ -476,7 +464,6 @@ _stream_mmap_ctor (struct _stream_mmap *ms)
if (ms->refcount == NULL)
return MU_ERROR_NO_MEMORY;
ms->fd = -1;
ms->offset = -1;
ms->flags = 0;
ms->mflags = 0;
ms->base.vtable = &_stream_mmap_vtable;
......@@ -484,13 +471,16 @@ _stream_mmap_ctor (struct _stream_mmap *ms)
}
void
_stream_mmap_dtor (struct _stream_mmap *ms)
_stream_mmap_dtor (stream_t stream)
{
struct _stream_mmap *ms = (struct _stream_mmap *)stream;
if (ms)
{
mu_refcount_destroy (&ms->refcount);
ms->fd = -1;
ms->offset = -1;
ms->mflags = 0;
ms->ptr = MAP_FAILED;
}
}
#endif /* _POSIX_MAPPED_FILES */
......
......@@ -16,15 +16,16 @@ libmbox_la_SOURCES = \
mbox_bstream.c \
mbox_carrier.c \
mbox_cb.c \
mbox_newmail.c \
mbox_close.c \
mbox_create.c \
mbox_debug.c \
mbox_destroy.c \
mbox_expunge.c \
mbox_hcache.c \
mbox_hlines.c \
mbox_hsize.c \
mbox_hstream.c \
mbox_newmail.c \
mbox_open.c \
mbox_scan.c \
mbox_separator.c \
......
......@@ -94,7 +94,10 @@
- Refuse to append if the mailbox is change on disk.
*/
/* Assuming that the file is lock. */
/* Assuming that the file is lock:
Add the unix separtor the form is:
From user cdate_format\n
*/
static int
mbox_append_separator (mbox_t mbox, const char *sep)
{
......@@ -123,93 +126,102 @@ mbox_append_separator (mbox_t mbox, const char *sep)
len = strlen (sep);
/* Write the separator. */
status = stream_write (mbox->carrier, sep, len, NULL);
status = stream_write (mbox->carrier, sep, len, mbox->woffset, &len);
if (status != 0)
return status;
mbox->woffset += len;
/* Add the trailing newline. */
if (len && sep[len - 1] != '\n')
status = stream_write (mbox->carrier, &nl, 1, NULL);
{
status = stream_write (mbox->carrier, &nl, 1, mbox->woffset, &len);
if (status != 0)
return status;
mbox->woffset += len;
}
return status;
}
/* Assuming that the file is lock. */
/* Assuming that the file is lock.
Strip away Content-Length in the header add add the separating
newline between the header and the body.
*/
static int
mbox_append_header (mbox_t mbox, attribute_t attribute, int save_uidvalidity,
stream_t hstream)
mbox_append_header (mbox_t mbox, attribute_t attribute, stream_t hstream,
int save_uidvalidity, unsigned long uid)
{
char buffer[1024];
char buf[1024];
size_t n = 0;
size_t nread = 0;
int status = 0;
const char nl = '\n';
do
{
status = stream_readline (hstream, buffer, sizeof buffer, &nread);
status = stream_readline (hstream, buf, sizeof buf, mbox->roffset, &nread);
if (status != 0)
return status;
mbox->roffset += nread;
/* A newline means the start of the body. */
if (*buffer == '\n')
if (*buf == '\n')
break;
if (IS_X_IMAPBASE (buffer))
{
/* Skip the X-IMAPBase it has special meaning for us. */
/* Skip X-IMAPBase it has special meaning for us. */
/* Skip X-UID. A new one will be provided. */
/* Skip Status, use the attribute. */
/* Skip Content-Length, too often bad. */
if (IS_X_IMAPBASE (buf) || IS_X_UID (buf)
|| IS_STATUS (buf) || IS_CONTENT_LENGTH (buf))
continue;
}
else if (IS_X_UID (buffer))
{
/* Skip the X-UID. A new one will be provided. */
continue;
}
else if (IS_STATUS (buffer))
{
/* Skip, use the attribute. */
continue;
}
else if (IS_CONTENT_LENGTH (buffer))
{
/* Ignore this, too often bad. */
continue;
}
status = stream_write (mbox->carrier, buffer, nread, NULL);
status = stream_write (mbox->carrier, buf, nread, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
}
while (nread > 0);
/* Rewrite the X-IMAPbase marker If necesary. */
/* Rewrite the X-IMAPbase, if necesary, and only for the first msg. */
if (mbox->uidnext < 2 && save_uidvalidity)
{
nread = snprintf (buffer, sizeof buffer, "X-IMAPbase: %lu %lu\n",
n = snprintf (buf, sizeof buf, "X-IMAPbase: %lu %lu\n",
mbox->uidvalidity, mbox->uidnext);
status = stream_write (mbox->carrier, buffer, nread, NULL);
status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
}
/* Rewrite the Status for the attribute. */
if (attribute)
{
mbox_attribute_to_status (attribute, buffer, sizeof buffer, &nread);
status = stream_write (mbox->carrier, buffer, nread, NULL);
mbox_attribute_to_status (attribute, buf, sizeof buf, &n);
status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
}
/* Rewrite the X-UID marker . */
nread = snprintf (buffer, sizeof buffer, "X-UID: %lu\n", mbox->uidnext);
status = stream_write (mbox->carrier, buffer, nread, NULL);
n = snprintf (buf, sizeof buf, "X-UID: %lu\n", (uid) ? uid : mbox->uidnext);
status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
/* New line separator of the Header. */
return stream_write (mbox->carrier, &nl , 1, NULL);
status = stream_write (mbox->carrier, &nl , 1, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
return status;
}
/* Assuming that the file is lock. */
/* Assuming that the file is lock.
Do the mangling, line startin with "From " is mangle to ">From "
*/
static int
mbox_append_body (mbox_t mbox, stream_t bstream)
{
......@@ -219,6 +231,7 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
size_t nread = 0;
const char nl = '\n';
int status;
size_t n = 0;
/* For "From " mangling. */
*buffer = '>';
......@@ -226,9 +239,11 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
do
{
buf = buffer + 1;
status = stream_readline (bstream, buf, sizeof (buffer) - 1, &nread);
status = stream_readline (bstream, buf, sizeof (buffer) - 1,
mbox->roffset, &nread);
if (status != 0)
return status;
mbox->roffset += nread;
/* Unix Mbox:
Since it's possibpe for a message to contain lines that looks
......@@ -252,9 +267,10 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
nread++;
}
}
status = stream_write (mbox->carrier, buf, nread, NULL);
status = stream_write (mbox->carrier, buf, nread, mbox->woffset, &n);
if (status != 0)
return status ;
mbox->woffset += n;
/* Register if we read a complete line. */
was_complete_line = (nread && buf[nread - 1] == '\n') ? 1 : 0;
......@@ -262,15 +278,22 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
while (nread > 0);
/* New line separator for the next message. */
return stream_write (mbox->carrier, &nl, 1, NULL);
status = stream_write (mbox->carrier, &nl, 1, mbox->woffset, &n);
if (status != 0)
return status;
mbox->woffset += n;
return status;
}
int
mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
int save_uidvalidity, stream_t hstream, stream_t bstream)
stream_t hstream, stream_t bstream,
int save_uidvalidity, unsigned long uid)
{
int status = 0;
mbox_debug_print (mbox, "append_hb0(uid=%lu)", uid);
if (mbox == NULL || hstream == NULL || bstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -278,7 +301,6 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
{
case MU_MBOX_NO_STATE:
{
off_t size = 0;
unsigned long uidvalidity;
unsigned long uidnext;
......@@ -291,10 +313,10 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
if (status != 0)
break;
mbox->woffset = mbox->roffset = 0;
/* Move to the end of the stream. */
if ((status = stream_get_size (mbox->carrier, &size)) != 0
|| (status = stream_seek (mbox->carrier, size,
MU_STREAM_WHENCE_SET) != 0))
status = stream_get_size (mbox->carrier, &mbox->woffset);
if (status != 0)
break;
mbox->state = MU_MBOX_STATE_APPEND_SEPARATOR;
}
......@@ -309,7 +331,8 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
case MU_MBOX_STATE_APPEND_HEADER:
{
status = mbox_append_header (mbox, attribute, save_uidvalidity, hstream);
status = mbox_append_header (mbox, attribute, hstream,
save_uidvalidity, uid);
if (status != 0)
break;
mbox->state = MU_MBOX_STATE_APPEND_BODY;
......@@ -317,6 +340,9 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
case MU_MBOX_STATE_APPEND_BODY:
{
/* Hack it the same stream. do not reset the mbox->roffset. */
if (hstream != bstream)
mbox->roffset = 0;
status = mbox_append_body (mbox, bstream);
if (status != 0)
break;
......@@ -324,6 +350,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
}
default:
mbox->woffset = mbox->roffset = 0;
break;
}
......@@ -333,6 +360,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
if (status != MU_ERROR_TRY_AGAIN)
{
mbox->state = MU_MBOX_NO_STATE;
mbox->woffset = mbox->roffset = 0;
lockfile_unlock (mbox->lockfile);
}
}
......@@ -347,15 +375,15 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
}
int
mbox_append (mbox_t mbox, const char *sep, attribute_t attribute,
stream_t stream)
mbox_append_hb (mbox_t mbox, const char *sep, attribute_t attribute,
stream_t hstream, stream_t bstream)
{
return mbox_append_hb (mbox, sep, attribute, stream, stream);
return mbox_append_hb0 (mbox, sep, attribute, hstream, bstream, 1, 0);
}
int
mbox_append_hb (mbox_t mbox, const char *sep, attribute_t attribute,
stream_t hstream, stream_t bstream)
mbox_append (mbox_t mbox, const char *sep, attribute_t attribute,
stream_t stream)
{
return mbox_append_hb0 (mbox, sep, attribute, 1, hstream, bstream);
return mbox_append_hb (mbox, sep, attribute, stream, stream);
}
......
......@@ -48,14 +48,15 @@ _attribute_mbox_destroy (attribute_t *pattribute)
struct _attribute_mbox *ma = (struct _attribute_mbox *)*pattribute;
if (mu_refcount_dec (ma->refcount) == 0)
{
mu_refcount_destroy (&ma->refcount);
if (ma->msgno <= ma->mbox->messages_count)
{
/* If it is the attribute save in the mailbox structure. */
if (ma == (struct _attribute_mbox *)(ma->mbox->umessages[ma->msgno - 1]->attribute))
if (ma == (struct _attribute_mbox *)
(ma->mbox->umessages[ma->msgno - 1]->attribute))
ma->mbox->umessages[ma->msgno - 1]->attribute = NULL;
mu_refcount_destroy (&ma->refcount);
free (ma);
}
free (ma);
}
}
......@@ -66,10 +67,8 @@ _attribute_mbox_get_flags (attribute_t attribute, int *pflags)
if (pflags)
{
if (ma->msgno <= ma->mbox->messages_count)
{
*pflags = ma->mbox->umessages[ma->msgno - 1]->attr_flags;
}
}
return 0;
}
......@@ -78,9 +77,8 @@ _attribute_mbox_set_flags (attribute_t attribute, int flags)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma->msgno <= ma->mbox->messages_count)
{
ma->mbox->umessages[ma->msgno - 1]->attr_flags |= (flags | MU_ATTRIBUTE_MODIFIED);
}
ma->mbox->umessages[ma->msgno - 1]->attr_flags |=
(flags | MU_ATTRIBUTE_MODIFIED);
return 0;
}
......@@ -93,7 +91,8 @@ _attribute_mbox_unset_flags (attribute_t attribute, int flags)
ma->mbox->umessages[ma->msgno - 1]->attr_flags &= ~flags;
/* If Modified was being unset do not reset it. */
if (!(flags & MU_ATTRIBUTE_MODIFIED))
ma->mbox->umessages[ma->msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
ma->mbox->umessages[ma->msgno - 1]->attr_flags |=
MU_ATTRIBUTE_MODIFIED;
}
return 0;
}
......@@ -103,12 +102,56 @@ _attribute_mbox_clear_flags (attribute_t attribute)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma->msgno <= ma->mbox->messages_count)
{
ma->mbox->umessages[ma->msgno - 1]->attr_flags = 0;
return 0;
}
static int
_attribute_mbox_get_userflags (attribute_t attribute, int *puserflags)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (puserflags)
{
if (ma->msgno <= ma->mbox->messages_count)
*puserflags = ma->mbox->umessages[ma->msgno - 1]->attr_userflags;
}
return 0;
}
static int
_attribute_mbox_set_userflags (attribute_t attribute, int userflags)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma->msgno <= ma->mbox->messages_count)
ma->mbox->umessages[ma->msgno - 1]->attr_userflags |=
(userflags | MU_ATTRIBUTE_MODIFIED);
return 0;
}
static int
_attribute_mbox_unset_userflags (attribute_t attribute, int userflags)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma->msgno <= ma->mbox->messages_count)
{
ma->mbox->umessages[ma->msgno - 1]->attr_userflags &= ~userflags;
/* If Modified was being unset do not reset it. */
if (!(userflags & MU_ATTRIBUTE_MODIFIED))
ma->mbox->umessages[ma->msgno - 1]->attr_userflags |=
MU_ATTRIBUTE_MODIFIED;
}
return 0;
}
static int
_attribute_mbox_clear_userflags (attribute_t attribute)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma->msgno <= ma->mbox->messages_count)
ma->mbox->umessages[ma->msgno - 1]->attr_userflags = 0;
return 0;
}
static struct _attribute_vtable _attribute_mbox_vtable =
{
_attribute_mbox_ref,
......@@ -117,7 +160,12 @@ static struct _attribute_vtable _attribute_mbox_vtable =
_attribute_mbox_get_flags,
_attribute_mbox_set_flags,
_attribute_mbox_unset_flags,
_attribute_mbox_clear_flags
_attribute_mbox_clear_flags,
_attribute_mbox_get_userflags,
_attribute_mbox_set_userflags,
_attribute_mbox_unset_userflags,
_attribute_mbox_clear_userflags
};
static int
......@@ -133,12 +181,19 @@ _attribute_mbox_ctor (struct _attribute_mbox *ma, mbox_t mbox,
return 0;
}
/*
static int
_attribute_mbox_dtor (struct _attribute_mbox *ma)
void
_attribute_mbox_dtor (attribute_t attribute)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
mu_refcount_destroy (&ma->refcount);
if (ma->msgno <= ma->mbox->messages_count)
{
/* If it is the attribute save in the mailbox structure. */
if (ma == (struct _attribute_mbox *)
(ma->mbox->umessages[ma->msgno - 1]->attribute))
ma->mbox->umessages[ma->msgno - 1]->attribute = NULL;
}
}
*/
int
attribute_mbox_create (attribute_t *pattribute, mbox_t mbox,
......@@ -162,9 +217,21 @@ attribute_mbox_create (attribute_t *pattribute, mbox_t mbox,
}
int
attribute_mbox_msgno (attribute_t attribute, unsigned int msgno)
{
struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
if (ma)
ma->msgno = msgno;
return 0;
}
int
mbox_get_attribute (mbox_t mbox, unsigned int msgno, attribute_t *pattribute)
{
int status = 0;
mbox_debug_print (mbox, "attribute(%d)", msgno);
if (mbox == NULL || msgno == 0 || pattribute == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -198,16 +265,18 @@ mbox_attribute_to_status (attribute_t attribute, char *buf, size_t buflen,
if (attribute)
{
if (attribute_is_read (attribute))
strcat (a, "R");
if (attribute_is_seen (attribute))
strcat (a, "O");
if (attribute_is_read (attribute))
strcat (a, "R");
if (attribute_is_answered (attribute))
strcat (a, "A");
if (attribute_is_deleted (attribute))
strcat (a, "d");
if (attribute_is_flagged (attribute))
strcat (a, "F");
if (attribute_is_draft (attribute))
strcat (a, "T");
}
if (*a != '\0')
......
......@@ -27,6 +27,7 @@ int
mbox_get_blines (mbox_t mbox, unsigned int msgno, unsigned int *plines)
{
unsigned int lines = 0;
mbox_debug_print (mbox, "get_blines(%u)", msgno);
if (mbox && msgno)
{
msgno--;
......
......@@ -27,6 +27,7 @@ int
mbox_get_bsize (mbox_t mbox, unsigned int msgno, unsigned int *psize)
{
unsigned int size = 0;
mbox_debug_print (mbox, "get_bsize(%u)", msgno);
if (mbox && msgno)
{
msgno--;
......
......@@ -28,6 +28,8 @@ int
mbox_get_bstream (mbox_t mbox, unsigned int msgno, stream_t *pstream)
{
int status = 0;
mbox_debug_print (mbox, "get_bstream(%u)", msgno);
if (mbox == NULL || msgno == 0 || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -58,10 +60,11 @@ mbox_set_bstream (mbox_t mbox, unsigned int msgno, stream_t stream)
if (msgno > mbox->umessages_count)
return MU_ERROR_INVALID_PARAMETER;
msgno--;
if (mbox->umessages[msgno]->body.stream)
stream_destroy (&mbox->umessages[msgno]->body.stream);
if (mbox->umessages[msgno - 1]->body.stream)
mbox_release_bstream (mbox, msgno);
mbox->umessages[msgno]->body.stream = stream;
mbox->umessages[msgno - 1]->attr_flags |= MU_MBOX_BSTREAM_SET;
mbox->umessages[msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
mbox->umessages[msgno - 1]->body.stream = stream;
return 0;
}
......
......@@ -27,6 +27,7 @@
int
mbox_set_carrier (mbox_t mbox, stream_t carrier)
{
mbox_debug_print (mbox, "set_carrier");
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -42,6 +43,7 @@ mbox_set_carrier (mbox_t mbox, stream_t carrier)
int
mbox_get_carrier (mbox_t mbox, stream_t *pcarrier)
{
mbox_debug_print (mbox, "get_carrier");
if (mbox == NULL || pcarrier == NULL)
return MU_ERROR_INVALID_PARAMETER;
......
......@@ -43,6 +43,16 @@ mbox_set_newmsg_cb (mbox_t mbox, int (*cb) __P ((int, void *)), void *arg)
}
int
mbox_set_error_cb (mbox_t mbox, int (*cb) __P ((int, void *)), void *arg)
{
if (mbox)
return MU_ERROR_INVALID_PARAMETER;
mbox->error.cb = cb;
mbox->error.arg = arg;
return 0;
}
int
mbox_newmsg_cb (mbox_t mbox, int info)
{
if (mbox)
......@@ -61,3 +71,13 @@ mbox_progress_cb (mbox_t mbox, int info)
return mbox->progress.cb (info, mbox->progress.arg);
return 0;
}
int
mbox_error_cb (mbox_t mbox, int info)
{
if (mbox)
return MU_ERROR_INVALID_PARAMETER;
if (mbox->error.cb)
return mbox->error.cb (info, mbox->error.arg);
return 0;
}
......
......@@ -29,6 +29,8 @@ mbox_close (mbox_t mbox)
{
size_t i;
mbox_debug_print (mbox, "close");
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -44,31 +46,21 @@ mbox_close (mbox_t mbox)
- to prepare for another scan. */
for (i = 0; i < mbox->umessages_count; i++)
{
mbox_message_t mum = mbox->umessages[i];
/* Destroy the attach messages. */
if (mum)
{
mbox_hcache_free (mbox, i + 1);
if (mum->header.stream)
stream_destroy (&(mum->header.stream));
if (mum->body.stream)
stream_destroy (&(mum->body.stream));
if (mum->separator)
free (mum->separator);
if (mum->attribute)
attribute_destroy (&mum->attribute);
free (mum);
}
/* Destroy the attach streams and attribute. */
if (mbox->umessages[i])
mbox_release_msg (mbox, i + 1);
}
if (mbox->umessages)
free (mbox->umessages);
mbox->umessages = NULL;
mbox->umessages_count = 0;
mbox->messages_count = 0;
mbox->size = 0;
mbox->uidvalidity = 0;
mbox->uidnext = 0;
if (mbox->filename)
free (mbox->filename);
mbox->filename = NULL;
return stream_close (mbox->carrier);
}
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <mailutils/error.h>
#include <mailutils/sys/mbox.h>
int
mbox_get_debug (mbox_t mbox, mu_debug_t *pdebug)
{
if (mbox == NULL || pdebug == NULL)
return MU_ERROR_INVALID_PARAMETER;
if (mbox->debug == NULL)
{
stream_t stream;
int status = stream_stdio_create (&stream, stderr);
if (status == 0)
status = mu_debug_stream_create (&mbox->debug, stream, 0);
if (status != 0)
return status;
}
mu_debug_ref (mbox->debug);
*pdebug = mbox->debug;
return 0;
}
int
mbox_set_debug (mbox_t mbox, mu_debug_t debug)
{
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
if (mbox->debug)
mu_debug_destroy (&mbox->debug);
mbox->debug = debug;
return 0;
}
int
mbox_debug_print (mbox_t mbox, const char *fmt, ...)
{
if (mbox && mbox->debug)
{
char buf[128];
va_list ap;
snprintf (buf, sizeof buf, "mbox(%s)_",
(mbox->filename) ? mbox->filename : "");
mu_debug_print (mbox->debug, MU_DEBUG_TRACE, buf);
if (fmt)
{
va_start (ap, fmt);
vsnprintf (buf, sizeof buf, fmt, ap);
va_end (ap);
}
mu_debug_print (mbox->debug, MU_DEBUG_TRACE, buf);
mu_debug_print (mbox->debug, MU_DEBUG_TRACE, "\n");
}
return 0;
}
......@@ -24,12 +24,109 @@
#include <mailutils/sys/mbox.h>
void
mbox_release_separator (mbox_t mbox, unsigned int msgno)
{
if (mbox == NULL || msgno == 0)
return;
if (msgno > mbox->umessages_count)
return;
if (mbox->umessages[msgno - 1]->separator)
free (mbox->umessages[msgno - 1]->separator);
mbox->umessages[msgno - 1]->separator = NULL;
}
void
mbox_release_attribute (mbox_t mbox, unsigned int msgno)
{
if (mbox == NULL || msgno == 0)
return;
if (msgno > mbox->umessages_count)
return;
if (mbox->umessages[msgno - 1]->attribute)
_attribute_mbox_dtor (mbox->umessages[msgno - 1]->attribute);
mbox->umessages[msgno - 1]->attribute = NULL;
}
void
mbox_release_hstream (mbox_t mbox, unsigned int msgno)
{
if (mbox == NULL || msgno == 0)
return;
if (msgno > mbox->umessages_count)
return;
if (mbox->umessages[msgno - 1]->header.stream)
{
if (mbox->umessages[msgno - 1]->attr_userflags & MU_MBOX_HSTREAM_SET)
{
stream_destroy (&mbox->umessages[msgno - 1]->header.stream);
mbox->umessages[msgno - 1]->attr_userflags &= ~MU_MBOX_HSTREAM_SET;
}
else
_stream_mbox_dtor (mbox->umessages[msgno - 1]->header.stream);
}
mbox->umessages[msgno - 1]->header.stream = NULL;
}
void
mbox_release_bstream (mbox_t mbox, unsigned int msgno)
{
if (mbox == NULL || msgno == 0)
return;
if (msgno > mbox->umessages_count)
return;
if (mbox->umessages[msgno - 1]->body.stream)
{
if (mbox->umessages[msgno - 1]->attr_userflags & MU_MBOX_BSTREAM_SET)
{
stream_destroy (&mbox->umessages[msgno - 1]->body.stream);
mbox->umessages[msgno - 1]->attr_userflags &= ~MU_MBOX_BSTREAM_SET;
}
else
_stream_mbox_dtor (mbox->umessages[msgno - 1]->body.stream);
}
mbox->umessages[msgno - 1]->body.stream = NULL;
}
void
mbox_release_msg (mbox_t mbox, unsigned int msgno)
{
if (mbox == NULL || msgno == 0)
return;
if (msgno > mbox->umessages_count)
return;
mbox_release_hcache (mbox, msgno);
mbox_release_separator (mbox, msgno);
mbox_release_attribute (mbox, msgno);
mbox_release_hstream (mbox, msgno);
mbox_release_bstream (mbox, msgno);
free (mbox->umessages[msgno - 1]);
mbox->umessages[msgno - 1] = NULL;
}
void
mbox_destroy (mbox_t *pmbox)
{
if (pmbox && *pmbox)
{
mbox_t mbox = *pmbox;
mbox_debug_print (mbox, "destroy");
/* _close will release all the messages. */
mbox_close (mbox);
if (mbox->carrier)
stream_destroy (&mbox->carrier);
if (mbox->debug)
mu_debug_destroy (&mbox->debug);
mbox_release_hcache (mbox, 0);
free (mbox);
}
}
......
......@@ -128,6 +128,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
off_t tmp_size = 0;
size_t save_uidvalidity = 0; /* uidvalidity is save in the first message. */
mbox_debug_print (mbox, "expunge, r=%d", remove_deleted);
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -154,7 +155,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
{
if (tmp_name)
free (tmp_name);
/* mu_error ("Failed to create temporary file when expunging.\n"); */
mbox_error_cb (mbox, errno);
return errno;
}
......@@ -193,7 +194,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
mbox_destroy (&tmp_mbox);
remove (tmp_name);
free (tmp_name);
/* mu_error ("Failed to grab the lock\n"); */
mbox_error_cb (mbox, status);
return status;
}
......@@ -232,32 +233,29 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
stream_t hstream = NULL, bstream = NULL;
attribute_t attribute = NULL;
char *sep = NULL;
/* The message was not instanciated, probably the dirty flag was
set by mbox_scan(), create one here. */
if (mum->separator == NULL || mum->header.stream == NULL
|| mum->body.stream == NULL || mum->attribute == NULL)
/* The message was not instanciated, create one here. */
if (mum->separator == NULL || mum->attribute
|| mum->header.stream == NULL || mum->body.stream == NULL)
{
if (mbox_get_hstream (mbox, i + 1, &hstream) != 0
|| mbox_get_bstream (mbox, i + 1, &bstream) != 0
|| mbox_get_separator (mbox, i + 1, &sep) != 0
|| mbox_get_attribute (mbox, i + 1, &attribute) != 0)
if ((status = mbox_get_separator (mbox, i + 1, &sep) != 0)
|| (status = mbox_get_attribute (mbox, i + 1, &attribute) != 0)
|| (status = mbox_get_hstream (mbox, i + 1, &hstream) != 0)
|| (status = mbox_get_bstream (mbox, i + 1, &bstream) != 0))
{
/* mu_error ("Error expunge:%d", __LINE__); */
mbox_error_cb (mbox, status);
goto bailout0;
}
}
status = mbox_append_hb0 (tmp_mbox, mum->separator, mum->attribute,
save_uidvalidity, mum->header.stream,
mum->body.stream);
if (sep)
mum->header.stream, mum->body.stream,
save_uidvalidity, mum->uid);
free (sep);
attribute_destroy (&attribute);
stream_destroy (&hstream);
stream_destroy (&bstream);
attribute_destroy (&attribute);
if (status != 0)
{
/* mu_error ("Error expunge:%d: %s", __LINE__,
strerror (status)); */
mbox_error_cb (mbox, status);
goto bailout0;
}
/* Clear the dirty bits. */
......@@ -266,10 +264,9 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
} /* for (;;) */
/* Get the real size of the mailbox. The size maintain in
the struct _mailbox { off_t size; } the one return in
mailbox_get_size() only return the size that mbox_scan()
is aware of not necessary the size of the file after
an append. */
the struct _mailbox { off_t size; }(the one return in
mailbox_get_size()) only returns the size that mbox_scan()
is aware of, not necessary the size of the file after an append. */
stream_get_size (tmp_mbox->carrier, &tmp_size);
/* Caution: before ftruncate()ing the file see
......@@ -281,29 +278,28 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
if (stream_get_size (mbox->carrier, &size) == 0)
{
off_t len = size - mbox->size;
char buffer [1024];
off_t offset = mbox->size;
char buf [1024];
size_t n = 0;
if (len > 0)
{
stream_seek (mbox->carrier, mbox->size, MU_STREAM_WHENCE_SET);
stream_seek (tmp_mbox->carrier, tmp_size, MU_STREAM_WHENCE_SET);
while ((status = stream_read (mbox->carrier, buffer,
sizeof buffer, &n)) == 0 && n > 0)
while ((status = stream_read (mbox->carrier, buf, sizeof buf,
offset, &n)) == 0 && n > 0)
{
status = stream_write (tmp_mbox->carrier, buffer, n, NULL);
status = stream_write(tmp_mbox->carrier, buf, n, tmp_size, &n);
if (status != 0)
{
/* mu_error ("Error expunge:%d: %s", __LINE__,
strerror (status)); */
mbox_error_cb (mbox, status);
goto bailout0;
}
offset += n;
tmp_size += n;
}
}
else if (len < 0)
{
/* Corrupted mailbox. */
/* mu_error ("Error expunge:%d: %s", __LINE__,
strerror (status)); */
mbox_error_cb (mbox, status);
goto bailout0;
}
}
......@@ -312,32 +308,31 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
/* Seek and rewrite it. */
if (tmp_size > 0)
{
char buffer [1024];
char buf [1024];
size_t n = 0;
off_t tmp_off = 0;
off_t offset = marker;
stream_seek (mbox->carrier, marker, MU_STREAM_WHENCE_SET);
stream_seek (tmp_mbox->carrier, 0, MU_STREAM_WHENCE_SET);
while ((status = stream_read (tmp_mbox->carrier, buffer,
sizeof buffer, &n)) == 0 && n > 0)
while ((status = stream_read (tmp_mbox->carrier, buf, sizeof buf,
tmp_off, &n)) == 0 && n > 0)
{
status = stream_write (mbox->carrier, buffer, n, &n);
status = stream_write (mbox->carrier, buf, n, offset, &n);
if (status != 0)
{
/* mu_error ("Error expunge:%d: %s\n", __LINE__,
strerror (status)); */
mbox_error_cb (mbox, status);
goto bailout;
}
tmp_off += n;
offset += n;
}
}
/* Flush/truncation. Need to flush before truncate. */
stream_get_size (tmp_mbox->carrier, &tmp_size);
stream_flush (mbox->carrier);
status = stream_truncate (mbox->carrier, tmp_size + marker);
if (status != 0)
{
/* mu_error ("Error expunging:%d: %s\n", __LINE__,
strerror (status)); */
mbox_error_cb (mbox, status);
goto bailout;
}
......@@ -346,7 +341,6 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
remove (tmp_name);
bailout:
free (tmp_name);
/* Release the File lock. */
lockfile_unlock (mbox->lockfile);
......@@ -366,47 +360,41 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
size_t dlast;
for (j = dirty, dlast = mbox->messages_count - 1; j <= dlast; j++)
{
/* Clear all the references to streams. */
mum = mbox->umessages[j];
/* Clear all the references to streams. */
if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags))
{
if (mum->separator)
free (mum->separator);
mum->separator = NULL;
if (mum->attribute)
attribute_destroy (&mum->attribute);
if (mum->header.stream)
stream_destroy (&mum->header.stream);
if (mum->body.stream)
stream_destroy (&mum->body.stream);
mbox_hcache_free (mbox, i + 1);
/* memset (mum, 0, sizeof (*mum)); */
mbox_release_msg (mbox, j + 1);
if ((j + 1) <= dlast)
{
/* Move all the pointers up. So the message pointer
part of mum will be at the right position. */
/* Move all the pointers up. So the message pointers
will be at the right position. */
memmove (mbox->umessages + j, mbox->umessages + j + 1,
(dlast - j) * sizeof (mum));
#if 1
mum->from_ = mum->header.start = 0;
mum->body.start = mum->body.end = 0;
mum->header.lines = mum->body.lines = 0;
#endif
/* We are not free()ing the useless mum, but instead
we put it back in the pool, to be reuse. */
mbox->umessages[dlast] = mum;
(dlast - j) * sizeof mum);
dlast--;
/* Set mum to the new value after the memmove so it
gets cleared to. */
mum = mbox->umessages[j];
}
mbox->umessages_count--;
mbox->messages_count--;
}
else
{
/* Readjust the offsets and attach objects. */
mum->from_ = mum->header.start = 0;
mum->body.start = mum->body.end = 0;
mum->header.lines = mum->body.lines = 0;
stream_mbox_msgno (mum->header.stream, j + 1);
stream_mbox_msgno (mum->body.stream, j + 1);
attribute_mbox_msgno (mum->attribute, j + 1);
}
}
/* This is should reset the messages_count, the last argument 0 means
/* Must Realloc the right size before the scan. some slots
in the umessages may be NULL after remove_deleted. */
mbox->umessages = realloc (mbox->umessages,
mbox->umessages_count
* sizeof (*(mbox->umessages)));
/* This should reset the messages_count, the last argument 0 means
not to send event notification. */
mbox_scan (mbox, dirty, NULL, 0);
}
......
......@@ -21,10 +21,15 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <mailutils/error.h>
#include <mailutils/sys/mbox.h>
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
static const char *hcache_default[] =
{
"Bcc",
......@@ -35,9 +40,10 @@ static const char *hcache_default[] =
"Date",
"From",
"In-Reply-To",
"Mail-Followup-To",
"Message-ID",
"Reply-To",
"Reply-To",
"Return-Path",
"Sender",
"Subject",
"To",
......@@ -45,7 +51,7 @@ static const char *hcache_default[] =
};
void
mbox_hcache_free (mbox_t mbox, unsigned int msgno)
mbox_release_hcache (mbox_t mbox, unsigned int msgno)
{
struct _hcache *hc;
......@@ -76,36 +82,51 @@ mbox_hcache_free (mbox_t mbox, unsigned int msgno)
int
mbox_set_hcache (mbox_t mbox, const char **array, size_t len)
{
int status = 0;
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
mbox_hcache_free (mbox, 0);
mbox_release_hcache (mbox, 0);
if (array && len)
{
unsigned int i;
status = mbox_add_hcache (mbox, array, len);
mbox->hcache.values = calloc (len, sizeof (*(mbox->hcache.values)));
return status;
}
if (mbox->hcache.values == NULL)
return MU_ERROR_NO_MEMORY;
int
mbox_add_hcache (mbox_t mbox, const char **array, size_t len)
{
size_t i;
int status = 0;
if (mbox == NULL || array == NULL || len == 0)
return MU_ERROR_INVALID_PARAMETER;
for (i = 0; i < len; i++)
{
mbox->hcache.values[i] = strdup (array[i]);
if (mbox->hcache.values[i] == NULL)
char **values;
if (array[i] == NULL || array[i][0] == '\0')
continue;
values = realloc (mbox->hcache.values,
(mbox->hcache.size + 1) * sizeof (*values));
if (values == NULL)
{
mbox_set_hcache (mbox, NULL, 0);
return MU_ERROR_NO_MEMORY;
status = MU_ERROR_NO_MEMORY;
break;
}
mbox->hcache.values = values;
mbox->hcache.values[mbox->hcache.size] = strdup (array[i]);
mbox->hcache.values[mbox->hcache.size][0] =
toupper (mbox->hcache.values[mbox->hcache.size][0]);
mbox->hcache.size++;
}
}
return 0;
return status;
}
int
mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name,
mbox_append_hcache (mbox_t mbox, unsigned int msgno, const char *name,
const char *value)
{
struct _hcache *hc;
......@@ -133,7 +154,9 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name,
for (i = 0; i < mbox->hcache.size; i++)
{
if (strcasecmp (mbox->hcache.values[i], name) == 0)
if (mbox->hcache.values[i]
&& toupper (*name) == mbox->hcache.values[i][0]
&& strcasecmp (mbox->hcache.values[i], name) == 0)
{
if (value == NULL)
{
......@@ -164,8 +187,52 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name,
}
int
mbox_set_hcache_default (mbox_t mbox)
mbox_set_default_hcache (mbox_t mbox)
{
return mbox_set_hcache (mbox, hcache_default,
sizeof (hcache_default) / sizeof (*hcache_default));
(sizeof hcache_default) / sizeof (*hcache_default));
}
int
mbox_value_hcache (mbox_t mbox, unsigned int msgno, const char *name,
char *buf, size_t buflen, size_t *pn)
{
mbox_message_t mum;
size_t i;
size_t n = 0;
int status = MU_ERROR_ENTRY_NOT_EXIST;
mbox_debug_print (mbox, "value_hcache(%d)", msgno);
if (mbox == NULL || msgno == 0 || name == NULL || *name == '\0')
return MU_ERROR_INVALID_PARAMETER;
if (msgno > mbox->umessages_count)
return MU_ERROR_INVALID_PARAMETER;
mum = mbox->umessages[msgno - 1];
for (i = 0; i < mbox->hcache.size; i++)
{
if (mbox->hcache.values[i]
&& toupper (*name) == mbox->hcache.values[i][0]
&& strcasecmp (mbox->hcache.values[i], name) == 0)
{
if (mum->hcache.size == mbox->hcache.size)
{
n = strlen (mum->hcache.values[i]);
if (buf && buflen)
{
buflen--;
n = min (buflen, n);
memcpy (buf, mum->hcache.values[i], n);
buf[n] = '\0';
}
status = 0;
}
}
}
if (pn)
*pn = n;
return status;
}
......
......@@ -27,6 +27,8 @@ int
mbox_get_hlines (mbox_t mbox, unsigned int msgno, unsigned int *plines)
{
unsigned int lines = 0;
mbox_debug_print (mbox, "get_lines(%u)", msgno);
if (mbox && msgno)
{
msgno--;
......
......@@ -27,6 +27,8 @@ int
mbox_get_hsize (mbox_t mbox, unsigned int msgno, unsigned int *psize)
{
unsigned int size = 0;
mbox_debug_print (mbox, "get_hsize(%d)", msgno);
if (mbox && msgno)
{
msgno--;
......
......@@ -28,6 +28,8 @@ int
mbox_get_hstream (mbox_t mbox, unsigned int msgno, stream_t *pstream)
{
int status = 0;
mbox_debug_print (mbox, "get_hstream(%u)", msgno);
if (mbox == NULL || msgno == 0 || pstream == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -58,10 +60,11 @@ mbox_set_hstream (mbox_t mbox, unsigned int msgno, stream_t stream)
if (msgno > mbox->umessages_count)
return MU_ERROR_INVALID_PARAMETER;
msgno--;
if (mbox->umessages[msgno]->header.stream)
stream_destroy (&mbox->umessages[msgno]->header.stream);
if (mbox->umessages[msgno - 1]->header.stream)
mbox_release_hstream (mbox, msgno);
mbox->umessages[msgno]->header.stream = stream;
mbox->umessages[msgno - 1]->attr_flags |= MU_MBOX_HSTREAM_SET;
mbox->umessages[msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
mbox->umessages[msgno - 1]->header.stream = stream;
return 0;
}
......
......@@ -25,14 +25,16 @@
#include <mailutils/sys/mbox.h>
int
mbox_changed_on_disk (mbox_t mbox)
mbox_has_newmail (mbox_t mbox)
{
int changed = 0;
int newmail = 0;
mbox_debug_print (mbox, "has_newmail");
/* If the modification time is greater then the access time, the file has
been modified since the last time it was accessed. This typically means
new mail or someone tempered with the mailbox. */
if (mbox->carrier)
if (mbox && mbox->carrier)
{
int fd = -1;
if (stream_get_fd (mbox->carrier, &fd) == 0)
......@@ -41,9 +43,9 @@ mbox_changed_on_disk (mbox_t mbox)
if (fstat (fd, &statbuf) == 0)
{
if (difftime (statbuf.st_mtime, statbuf.st_atime) > 0)
changed = 1;
newmail = 1;
}
}
}
return changed;
return newmail;
}
......
......@@ -31,6 +31,8 @@ mbox_open (mbox_t mbox, const char *filename, int flags)
char from[12];
size_t n = 0;
mbox_debug_print (mbox, "open(%s,%d)", (filename) ? filename : "", flags);
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -49,12 +51,11 @@ mbox_open (mbox_t mbox, const char *filename, int flags)
return status;
/* We need to be able to seek on the stream. */
status = stream_seek (mbox->carrier, 0, MU_STREAM_WHENCE_SET);
if (status != 0)
return status;
if (!stream_is_seekable (mbox->carrier))
return MU_ERROR_NOT_SUPPORTED;
/* Check if it is indeed a mbox format. */
stream_readline (mbox->carrier, from, sizeof from, &n);
stream_readline (mbox->carrier, from, sizeof from, 0, &n);
if (status != 0)
return status;
......
......@@ -75,18 +75,32 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n)
case 'R':
mum->attr_flags |= MU_ATTRIBUTE_READ;
break;
case 'O':
case 'o':
mum->attr_flags |= MU_ATTRIBUTE_SEEN;
break;
case 'a':
case 'A':
mum->attr_flags |= MU_ATTRIBUTE_ANSWERED;
break;
case 'd':
case 'D':
mum->attr_flags |= MU_ATTRIBUTE_DELETED;
break;
case 't':
case 'T':
mum->attr_flags |= MU_ATTRIBUTE_DRAFT;
break;
case 'f':
case 'F':
mum->attr_flags |= MU_ATTRIBUTE_FLAGGED;
break;
}
}
}
......@@ -96,8 +110,6 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n)
static int
mbox_alloc_umessages (mbox_t mbox)
{
mbox_message_t mum;
unsigned int msgno = 0;
if (mbox->messages_count >= mbox->umessages_count)
{
mbox_message_t *m;
......@@ -115,11 +127,6 @@ mbox_alloc_umessages (mbox_t mbox)
return MU_ERROR_NO_MEMORY;
}
}
if (mum->separator)
free (mum->separator);
mum->separator = 0;
mbox_hcache_free (mbox, msgno + 1);
return 0;
}
......@@ -148,6 +155,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
int zn, isfrom = 0;
char *temp;
mbox_debug_print (mbox, "scan(%u,%d)", msgno, do_notif);
if (mbox == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -170,14 +179,18 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
/* Move along, move along nothing to see. */
if (!mbox_has_newmail (mbox) && mbox->size == file_size)
{
if (pcount)
*pcount = mbox->messages_count;
return 0;
}
/* Bailout early on error. */
if (status != 0)
return status;
if (mbox->hcache.size == 0)
mbox_set_hcache_default (mbox);
mbox_set_default_hcache (mbox);
/* Lock the mbox before starting. */
/* FIXME: Check error.. */
......@@ -199,15 +212,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
errno = lines = inheader = inbody = 0;
mum = NULL;
status = stream_seek (mbox->carrier, total, MU_STREAM_WHENCE_SET);
if (status != 0)
{
lockfile_unlock (mbox->lockfile);
return status;
}
while ((status = stream_readline (mbox->carrier, buf, sizeof buf, &n)) == 0
&& n > 0)
while ((status = stream_readline (mbox->carrier, buf, sizeof buf,
total, &n)) == 0 && n > 0)
{
int nl;
total += n;
......@@ -242,7 +248,6 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
lockfile_unlock (mbox->lockfile);
return status;
}
stream_seek (mbox->carrier, total, MU_STREAM_WHENCE_SET);
}
}
/* Allocate_msgs will initialize mum. */
......@@ -287,7 +292,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
{
if (buf[n - 1] == '\n')
buf[n - 1] = 0;
mbox_hcache_append (mbox, mbox->messages_count, sfield, buf);
mbox_append_hcache (mbox, mbox->messages_count, sfield, buf);
}
else
{
......@@ -299,9 +304,10 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
{
*s = '\0';
s++;
while (*s == ' ') s++;
if (buf[n - 1] == '\n')
buf[n - 1] = 0;
mbox_hcache_append (mbox, mbox->messages_count, buf, s);
mbox_append_hcache (mbox, mbox->messages_count, buf, s);
sfield = strdup (buf);
}
}
......@@ -341,7 +347,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
if (mum)
{
mum->body.end = total - newline;
mum->body.end = total;
mum->body.lines = lines - newline;
if (do_notif)
mbox_newmsg_cb (mbox, mbox->messages_count);
......@@ -358,10 +364,12 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
{
mbox->uidvalidity = (unsigned long)time (NULL);
mbox->uidnext = mbox->messages_count + 1;
/* Tell that we have been modified for expunging. */
/* The uidvalidity was not save, flag it to be save
when expunging. */
mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
}
/* Reset the IMAP uids, if necessary. UID according to IMAP RFC is a 32 bit
ascending number for each messages */
{
......@@ -376,7 +384,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
{
uid = ouid + 1;
mum->uid = ouid = uid;
/* Note that modification for when expunging. */
/* UID was not ascentind, clear this when expunging by
setting modification flag. */
mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
else
......@@ -386,8 +395,26 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
{
mum = mbox->umessages[0];
mbox->uidnext = uid + 1;
/* The uidnext was wrong rewrite it when expunging. */
mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
}
}
/* If reserved more memory then scan messages, realloc not
to waste memory. */
if (mbox->messages_count && mbox->messages_count < mbox->umessages_count)
{
size_t i;
for (i = mbox->messages_count; i < mbox->umessages_count; i++)
{
if (mbox->umessages[i])
mbox_release_msg (mbox, i + 1);
}
mbox->umessages = realloc (mbox->umessages,
mbox->messages_count
* sizeof (*(mbox->umessages)));
mbox->umessages_count = mbox->messages_count;
}
lockfile_unlock (mbox->lockfile);
return status;
}
......
......@@ -32,6 +32,8 @@ int
mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
{
mbox_debug_print (mbox, "get_separator(%u)", msgno);
if (mbox == NULL || msgno == 0 || psep == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -48,6 +50,7 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
char *p = NULL;
int len = 0 ;
size_t n = 0;
off_t offset = mbox->umessages[msgno]->from_;
len = 2;
p = malloc (len);
......@@ -57,8 +60,6 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
do
{
char *s;
stream_seek (mbox->carrier, mbox->umessages[msgno]->from_,
MU_STREAM_WHENCE_SET);
len += 128;
s = realloc (p, len);
if (s == NULL)
......@@ -67,7 +68,8 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
return MU_ERROR_NO_MEMORY;
}
p = s ;
stream_readline (mbox->carrier, p + strlen (p), len, &n);
stream_readline (mbox->carrier, p + strlen (p), len, offset, &n);
offset += n;
n = strlen (p);
} while (n && p[n - 1] != '\n');
......@@ -95,5 +97,6 @@ mbox_set_separator (mbox_t mbox, unsigned int msgno, const char *sep)
if (mbox->umessages[msgno]->separator)
free (mbox->umessages[msgno]->separator);
mbox->umessages[msgno]->separator = (sep) ? strdup (sep) : NULL;
mbox->umessage[msgno]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
return 0;
}
......
......@@ -25,6 +25,7 @@
int
mbox_get_size (mbox_t mbox, off_t *size)
{
mbox_debug_print (mbox, "get_size");
if (mbox && size)
*size = mbox->size;
return 0;
......
......@@ -36,7 +36,6 @@ struct _stream_mbox
mbox_t mbox;
unsigned int msgno;
int is_header;
off_t offset;
};
static int
......@@ -52,21 +51,23 @@ _stream_mbox_destroy (stream_t *pstream)
struct _stream_mbox *ms = (struct _stream_mbox *)*pstream;
if (mu_refcount_dec (ms->refcount) == 0)
{
if (ms->msgno <= ms->mbox->messages_count)
{
mu_refcount_destroy (&ms->refcount);
if (ms->is_header)
if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
{
/* Loose the reference only if it is the same that we saved
on the mailbox. */
if (ms->is_header && ms == (struct _stream_mbox *)
(ms->mbox->umessages[ms->msgno - 1]->header.stream))
{
if (ms == (struct _stream_mbox *)ms->mbox->umessages[ms->msgno - 1]->header.stream)
ms->mbox->umessages[ms->msgno - 1]->header.stream = NULL;
}
else
else if (ms == (struct _stream_mbox *)
(ms->mbox->umessages[ms->msgno - 1]->body.stream))
{
if (ms == (struct _stream_mbox *)ms->mbox->umessages[ms->msgno - 1]->body.stream)
ms->mbox->umessages[ms->msgno - 1]->body.stream = NULL;
}
free (ms);
}
free (ms);
}
}
......@@ -85,44 +86,59 @@ _stream_mbox_close (stream_t stream)
}
static int
_stream_mbox_read (stream_t stream, void *buf, size_t buflen, size_t *pnread)
_stream_mbox_read0 (stream_t carrier, void *buf, size_t buflen, off_t off,
size_t *pn, off_t start, off_t end)
{
off_t ln = end - (start + off);
int status = 0;
if (ln > 0)
{
size_t n = min ((size_t)ln, buflen);
status = stream_read (carrier, buf, n, start + off, pn);
}
return status;
}
static int
_stream_mbox_read (stream_t stream, void *buf, size_t buflen, off_t off,
size_t *pnread)
{
int status = 0;
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
size_t nread = 0;
size_t n = 0;
if (buf && buflen)
{
if (ms->msgno <= ms->mbox->messages_count)
if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
{
off_t ln;
mbox_message_t umessage = ms->mbox->umessages[ms->msgno - 1];
mbox_message_t mum = ms->mbox->umessages[ms->msgno - 1];
if (ms->is_header)
ln = umessage->header.end - (umessage->header.start + ms->offset);
status = _stream_mbox_read0 (ms->mbox->carrier, buf, buflen, off,
&n, mum->header.start,
mum->header.end);
else
ln = umessage->body.end - (umessage->body.start + ms->offset);
status = _stream_mbox_read0 (ms->mbox->carrier, buf, buflen, off,
&n, mum->header.start,
mum->header.end);
}
}
if (pnread)
*pnread = n;
return status;
}
static int
_stream_mbox_readline0 (stream_t carrier, char *buf, size_t buflen, off_t off,
size_t *pn, off_t start, off_t end)
{
off_t ln = end - (start + off);
int status = 0;
if (ln > 0)
{
size_t n = min ((size_t)ln, buflen);
/* Position the file pointer. */
if (ms->is_header)
status = stream_seek (ms->mbox->carrier, umessage->header.start
+ ms->offset, MU_STREAM_WHENCE_SET);
else
status = stream_seek (ms->mbox->carrier, umessage->body.start
+ ms->offset, MU_STREAM_WHENCE_SET);
if (status == 0)
{
status = stream_read (ms->mbox->carrier, buf, n, &nread);
ms->offset += nread;
status = stream_readline (carrier, buf, n, start + off, pn);
}
}
}
}
if (pnread)
*pnread = nread;
return status;
}
......@@ -131,7 +147,7 @@ _stream_mbox_read (stream_t stream, void *buf, size_t buflen, size_t *pnread)
* Stop when a newline has been read, or the count runs out.
*/
static int
_stream_mbox_readline (stream_t stream, char *buf, size_t buflen,
_stream_mbox_readline (stream_t stream, char *buf, size_t buflen, off_t off,
size_t *pnread)
{
int status = 0;
......@@ -140,31 +156,17 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen,
if (buf && buflen)
{
if (ms->msgno <= ms->mbox->messages_count)
if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
{
off_t ln;
mbox_message_t umessage = ms->mbox->umessages[ms->msgno - 1];
mbox_message_t mum = ms->mbox->umessages[ms->msgno - 1];
if (ms->is_header)
ln = umessage->header.end - (umessage->header.start + ms->offset);
status = _stream_mbox_readline0 (ms->mbox->carrier, buf, buflen,
off, &nread, mum->header.start,
mum->header.end);
else
ln = umessage->body.end - (umessage->body.start + ms->offset);
if (ln > 0)
{
size_t n = min ((size_t)ln, buflen);
/* Position the stream. */
if (ms->is_header)
status = stream_seek (ms->mbox->carrier, umessage->header.start
+ ms->offset, MU_STREAM_WHENCE_SET);
else
status = stream_seek (ms->mbox->carrier, umessage->body.start
+ ms->offset, MU_STREAM_WHENCE_SET);
if (status == 0)
{
status = stream_readline (ms->mbox->carrier, buf, n, &nread);
ms->offset += nread;
}
}
status = _stream_mbox_readline0 (ms->mbox->carrier, buf, buflen,
off, &nread, mum->body.start,
mum->body.end);
}
}
......@@ -174,10 +176,10 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen,
}
static int
_stream_mbox_write (stream_t stream, const void *buf, size_t count,
_stream_mbox_write (stream_t stream, const void *buf, size_t buflen, off_t off,
size_t *pnwrite)
{
(void)stream; (void)buf; (void)count; (void)pnwrite;
(void)stream; (void)buf; (void)buflen; (void)off, (void)pnwrite;
return MU_ERROR_IO;
}
......@@ -185,14 +187,18 @@ static int
_stream_mbox_get_fd (stream_t stream, int *pfd)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms->mbox)
return stream_get_fd (ms->mbox->carrier, pfd);
return MU_ERROR_IO;
}
static int
_stream_mbox_get_flags (stream_t stream, int *pfl)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms->mbox)
return stream_get_flags (ms->mbox->carrier, pfl);
return MU_ERROR_IO;
}
static int
......@@ -202,7 +208,7 @@ _stream_mbox_get_size (stream_t stream, off_t *psize)
if (psize)
{
if (ms->msgno <= ms->mbox->messages_count)
if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
{
if (ms->is_header)
*psize = ms->mbox->umessages[ms->msgno - 1]->header.end
......@@ -211,6 +217,8 @@ _stream_mbox_get_size (stream_t stream, off_t *psize)
*psize = ms->mbox->umessages[ms->msgno - 1]->body.end
- ms->mbox->umessages[ms->msgno - 1]->body.start;
}
else
*psize = 0;
}
return 0;
}
......@@ -233,49 +241,36 @@ static int
_stream_mbox_get_state (stream_t stream, enum stream_state *pstate)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms->mbox)
return stream_get_state (ms->mbox->carrier, pstate);
return MU_ERROR_IO;
}
static int
_stream_mbox_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_mbox_is_seekable (stream_t stream)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
off_t noff = ms->offset;
int err = 0;
if (whence == MU_STREAM_WHENCE_SET)
noff = off;
else if (whence == MU_STREAM_WHENCE_CUR)
noff += off;
else if (whence == MU_STREAM_WHENCE_END)
{
off_t size = 0;
_stream_mbox_get_size (stream, &size);
noff = size + off;
}
else
noff = -1; /* error. */
if (noff >= 0)
ms->offset = noff;
else
err = MU_ERROR_INVALID_PARAMETER;
return err;
if (ms->mbox)
return stream_is_seekable (ms->mbox->carrier);
return MU_ERROR_IO;
}
static int
_stream_mbox_tell (stream_t stream, off_t *off)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (off == NULL)
return MU_ERROR_INVALID_PARAMETER;
*off = ms->offset;
return 0;
if (ms->mbox)
return stream_tell (ms->mbox->carrier, off);
return MU_ERROR_IO;
}
static int
_stream_mbox_is_readready (stream_t stream, int timeout)
{
(void)timeout;
return stream_is_open (stream);
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms->mbox)
return stream_is_readready (ms->mbox->carrier, timeout);
return MU_ERROR_IO;
}
static int
......@@ -296,7 +291,9 @@ static int
_stream_mbox_is_open (stream_t stream)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms->mbox)
return stream_is_open (ms->mbox->carrier);
return MU_ERROR_IO;
}
......@@ -312,7 +309,6 @@ static struct _stream_vtable _stream_mbox_vtable =
_stream_mbox_readline,
_stream_mbox_write,
_stream_mbox_seek,
_stream_mbox_tell,
_stream_mbox_get_size,
......@@ -323,6 +319,7 @@ static struct _stream_vtable _stream_mbox_vtable =
_stream_mbox_get_flags,
_stream_mbox_get_state,
_stream_mbox_is_seekable,
_stream_mbox_is_readready,
_stream_mbox_is_writeready,
_stream_mbox_is_exceptionpending,
......@@ -334,24 +331,50 @@ static int
_stream_mbox_ctor (struct _stream_mbox *ms, mbox_t mbox, unsigned int msgno,
int is_header)
{
mu_refcount_create (&(ms->refcount));
mu_refcount_create (&ms->refcount);
if (ms->refcount == NULL)
return MU_ERROR_NO_MEMORY;
ms->mbox = mbox;
ms->msgno = msgno;
ms->offset = 0;
ms->is_header = is_header;
ms->base.vtable = &_stream_mbox_vtable;
return 0;
}
/*
static void
_stream_mbox_dtor (struct _stream_mbox *ms)
void
_stream_mbox_dtor (stream_t stream)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
mu_refcount_destroy (&ms->refcount);
if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
{
/* Loose the reference only if it is the same that we saved
on the mailbox. */
if (ms->is_header && ms == (struct _stream_mbox *)
(ms->mbox->umessages[ms->msgno - 1]->header.stream))
{
ms->mbox->umessages[ms->msgno - 1]->header.stream = NULL;
}
else if (ms == (struct _stream_mbox *)
(ms->mbox->umessages[ms->msgno - 1]->body.stream))
{
ms->mbox->umessages[ms->msgno - 1]->body.stream = NULL;
}
}
ms->mbox = NULL;
ms->msgno = 0;
ms->is_header = 0;
}
int
stream_mbox_msgno (stream_t stream, unsigned int msgno)
{
struct _stream_mbox *ms = (struct _stream_mbox *)stream;
if (ms)
ms->msgno = msgno;
return 0;
}
*/
int
stream_mbox_create (stream_t *pstream, mbox_t mbox, unsigned int msgno,
......
......@@ -26,6 +26,8 @@ int
mbox_get_uid (mbox_t mbox, unsigned int msgno, unsigned long *puid)
{
mbox_debug_print (mbox, "get_uid(%u)", msgno);
if (mbox == NULL || msgno == 0 || puid == NULL)
return MU_ERROR_INVALID_PARAMETER;
......
......@@ -26,6 +26,8 @@ int
mbox_get_uidnext (mbox_t mbox, unsigned long *puidnext)
{
mbox_debug_print (mbox, "get_uidnext");
if (mbox == NULL || puidnext == NULL)
return MU_ERROR_INVALID_PARAMETER;
......
......@@ -25,6 +25,9 @@
int
mbox_get_uidvalidity (mbox_t mbox, unsigned long *puidvalidity)
{
mbox_debug_print (mbox, "get_uidvalidity");
if (mbox == NULL || puidvalidity == NULL)
return MU_ERROR_INVALID_PARAMETER;
......
......@@ -117,10 +117,10 @@ MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
unsigned int i, indx, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
indx = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
......@@ -128,26 +128,26 @@ unsigned int inputLen; /* length of input block */
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
partLen = 64 - indx;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
((POINTER)&context->buffer[indx], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
indx = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
((POINTER)&context->buffer[indx], (POINTER)&input[i],
inputLen-i);
}
......@@ -159,15 +159,15 @@ unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
unsigned int indx, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
indx = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (indx < 56) ? (56 - indx) : (120 - indx);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
......
......@@ -29,6 +29,9 @@
#include <mailutils/error.h>
#include <mailutils/sys/memstream.h>
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
int
_stream_memory_ref (stream_t stream)
{
......@@ -48,18 +51,18 @@ _stream_memory_destroy (stream_t *pstream)
}
int
_stream_memory_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
_stream_memory_read (stream_t stream, void *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
size_t n = 0;
mu_refcount_lock (mem->refcount);
if (mem->ptr != NULL && (mem->offset < (off_t)mem->size))
if (mem->ptr != NULL && (offset < (off_t)mem->size))
{
n = ((mem->offset + osize) > mem->size) ?
mem->size - mem->offset : osize;
memcpy (optr, mem->ptr + mem->offset, n);
mem->offset += n;
n = ((offset + osize) > mem->size) ?
mem->size - offset : osize;
memcpy (optr, mem->ptr + offset, n);
}
mu_refcount_unlock (mem->refcount);
if (nbytes)
......@@ -68,22 +71,22 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
}
int
_stream_memory_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes)
_stream_memory_readline (stream_t stream, char *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
char *nl;
size_t n = 0;
mu_refcount_lock (mem->refcount);
if (mem->ptr && (mem->offset < (off_t)mem->size))
if (mem->ptr && (offset < (off_t)mem->size))
{
/* Save space for the null byte. */
osize--;
nl = memchr (mem->ptr + mem->offset, '\n', mem->size - mem->offset);
n = (nl) ? nl - (mem->ptr + mem->offset) + 1 : mem->size - mem->offset;
n = (n > osize) ? osize : n;
memcpy (optr, mem->ptr + mem->offset, n);
nl = memchr (mem->ptr + offset, '\n', mem->size - offset);
n = (nl) ? (size_t)(nl - (mem->ptr + offset) + 1) : mem->size - offset;
n = min (n, osize);
memcpy (optr, mem->ptr + offset, n);
optr[n] = '\0';
mem->offset += n;
}
mu_refcount_unlock (mem->refcount);
if (nbytes)
......@@ -93,27 +96,26 @@ _stream_memory_readline (stream_t stream, char *optr, size_t osize, size_t *nbyt
int
_stream_memory_write (stream_t stream, const void *iptr, size_t isize,
size_t *nbytes)
off_t offset, size_t *nbytes)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
mu_refcount_lock (mem->refcount);
/* Bigger we have to realloc. */
if (mem->capacity < (mem->offset + isize))
if (mem->capacity < (offset + isize))
{
/* Realloc by blocks of 512. */
int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
(((mem->offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1);
(((offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1);
char *tmp = realloc (mem->ptr, newsize);
if (tmp == NULL)
return ENOMEM;
mem->ptr = tmp;
mem->size = mem->offset + isize;
mem->size = offset + isize;
mem->capacity = newsize;
}
memcpy (mem->ptr + mem->offset, iptr, isize);
mem->offset += isize;
memcpy (mem->ptr + offset, iptr, isize);
mu_refcount_unlock (mem->refcount);
if (nbytes)
*nbytes = isize;
......@@ -140,7 +142,6 @@ _stream_memory_truncate (stream_t stream, off_t len)
}
mem->capacity = len;
mem->size = len;
mem->offset = len;
mu_refcount_unlock (mem->refcount);
return 0;
}
......@@ -166,7 +167,6 @@ _stream_memory_close (stream_t stream)
mem->ptr = NULL;
mem->capacity = 0;
mem->size = 0;
mem->offset = 0;
mu_refcount_unlock (mem->refcount);
return 0;
}
......@@ -206,37 +206,19 @@ _stream_memory_get_state (stream_t stream, enum stream_state *state)
}
int
_stream_memory_seek (stream_t stream, off_t off, enum stream_whence whence)
_stream_memory_is_seekable (stream_t stream)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
off_t noff = mem->offset;
int err = 0;
if (whence == MU_STREAM_WHENCE_SET)
noff = off;
else if (whence == MU_STREAM_WHENCE_CUR)
noff += off;
else if (whence == MU_STREAM_WHENCE_END)
noff = mem->size + off;
else
noff = -1; /* error. */
if (noff >= 0)
{
if (noff > mem->offset)
_stream_memory_truncate (stream, noff);
mem->offset = noff;
}
else
err = MU_ERROR_INVALID_PARAMETER;
return err;
(void)stream;
return 1;
}
int
_stream_memory_tell (stream_t stream, off_t *off)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
(void)stream;
if (off == NULL)
return MU_ERROR_INVALID_PARAMETER;
*off = mem->offset;
*off = 0;
return 0;
}
......@@ -288,7 +270,6 @@ _stream_memory_open (stream_t stream, const char *filename, int port,
mem->ptr = NULL;
mem->capacity = 0;
mem->size = 0;
mem->offset = 0;
mem->flags = flags;
if (filename)
{
......@@ -341,7 +322,6 @@ static struct _stream_vtable _stream_memory_vtable =
_stream_memory_readline,
_stream_memory_write,
_stream_memory_seek,
_stream_memory_tell,
_stream_memory_get_size,
......@@ -352,6 +332,7 @@ static struct _stream_vtable _stream_memory_vtable =
_stream_memory_get_flags,
_stream_memory_get_state,
_stream_memory_is_seekable,
_stream_memory_is_readready,
_stream_memory_is_writeready,
_stream_memory_is_exceptionpending,
......@@ -378,21 +359,23 @@ _stream_memory_ctor (struct _stream_memory *mem, size_t capacity)
else
mem->capacity = 0;
mem->size = 0;
mem->offset = 0;
mem->flags = 0;
mem->base.vtable = &_stream_memory_vtable;
return 0;
}
void
_stream_memory_dtor (struct _stream_memory *mem)
_stream_memory_dtor (stream_t stream)
{
struct _stream_memory *mem = (struct _stream_memory *)stream;
if (mem)
{
mu_refcount_destroy (&mem->refcount);
mem->ptr = NULL;
mem->capacity = 0;
mem->size = 0;
mem->offset = 0;
mem->flags = 0;
}
}
int
......
......@@ -63,6 +63,8 @@ pop3_get_carrier (pop3_t pop3, stream_t *pcarrier)
return status;
}
}
/* Since we expose the stream incremente the reference count. */
stream_ref (pop3->carrier);
*pcarrier = pop3->carrier;
return 0;
}
......
......@@ -60,6 +60,8 @@ pop3_connect (pop3_t pop3, const char *host, unsigned int port)
stream_t carrier;
status = pop3_get_carrier (pop3, &carrier);
POP3_CHECK_ERROR (pop3, status);
/* An stream_ref was done in po3_get_carrier (). */
stream_destroy (&carrier);
}
else
{
......
......@@ -44,6 +44,7 @@ pop3_get_debug (pop3_t pop3, mu_debug_t *pdebug)
if (status != 0)
return status;
}
mu_debug_ref (pop3->debug);
*pdebug = pop3->debug;
return 0;
}
......
......@@ -50,9 +50,10 @@ pop3_getline (pop3_t pop3)
}
status = stream_readline (pop3->carrier, pop3->io.buf + total,
pop3->io.len - total, &n);
pop3->io.len - total, pop3->offset, &n);
if (status != 0)
return status;
pop3->offset += n;
/* The server went away: It maybe a timeout and some pop server
does not send the -ERR. Consider this like an error. */
......@@ -118,7 +119,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
size_t nread = 0;
size_t n = 0;
int status;
int status = 0;
/* Do we need to fill up? Yes if no NL or the buffer is empty. */
if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
......
......@@ -54,7 +54,7 @@ pop3_send (pop3_t pop3)
return MU_ERROR_TIMEOUT;
}
status = stream_write (pop3->carrier, pop3->io.buf, len, &n);
status = stream_write (pop3->carrier, pop3->io.buf, len, 0, &n);
if (n)
{
/* Consume what we sent. */
......
......@@ -34,11 +34,10 @@ static void p_destroy __P ((stream_t *));
static int p_open __P ((stream_t, const char *, int, int));
static int p_close __P ((stream_t));
static int p_read __P ((stream_t, void *, size_t, size_t *));
static int p_readline __P ((stream_t, char *, size_t, size_t *));
static int p_write __P ((stream_t, const void *, size_t, size_t *));
static int p_read __P ((stream_t, void *, size_t, off_t, size_t *));
static int p_readline __P ((stream_t, char *, size_t, off_t, size_t *));
static int p_write __P ((stream_t, const void *, size_t, off_t, size_t *));
static int p_seek __P ((stream_t, off_t, enum stream_whence));
static int p_tell __P ((stream_t, off_t *));
static int p_get_size __P ((stream_t, off_t *));
......@@ -49,6 +48,7 @@ static int p_get_fd __P ((stream_t, int *));
static int p_get_flags __P ((stream_t, int *));
static int p_get_state __P ((stream_t, enum stream_state *));
static int p_is_seekable __P ((stream_t));
static int p_is_readready __P ((stream_t, int timeout));
static int p_is_writeready __P ((stream_t, int timeout));
static int p_is_exceptionpending __P ((stream_t, int timeout));
......@@ -67,7 +67,6 @@ static struct _stream_vtable p_s_vtable =
p_readline,
p_write,
p_seek,
p_tell,
p_get_size,
......@@ -78,6 +77,7 @@ static struct _stream_vtable p_s_vtable =
p_get_flags,
p_get_state,
p_is_seekable,
p_is_readready,
p_is_writeready,
p_is_exceptionpending,
......@@ -151,12 +151,14 @@ p_close (stream_t stream)
}
static int
p_read (stream_t stream, void *buf, size_t buflen, size_t *pn)
p_read (stream_t stream, void *buf, size_t buflen, off_t offset, size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
size_t n = 0;
int status = 0;
char *p = buf;
(void)offset;
if (p_stream)
{
mu_refcount_lock (p_stream->refcount);
......@@ -202,11 +204,14 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn)
}
static int
p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn)
p_readline (stream_t stream, char *buf, size_t buflen, off_t offset,
size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
size_t n = 0;
int status = 0;
(void)offset;
if (p_stream)
{
mu_refcount_lock (p_stream->refcount);
......@@ -227,17 +232,18 @@ p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn)
}
static int
p_write (stream_t stream, const void *buf, size_t buflen, size_t *pn)
p_write (stream_t stream, const void *buf, size_t buflen, off_t offset,
size_t *pn)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_write (p_stream->pop3->carrier, buf, buflen, pn);
return stream_write (p_stream->pop3->carrier, buf, buflen, offset, pn);
}
static int
p_seek (stream_t stream, off_t offset, enum stream_whence whence)
p_is_seekable (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return stream_seek (p_stream->pop3->carrier, offset, whence);
return stream_is_seekable (p_stream->pop3->carrier);
}
static int
......
......@@ -60,15 +60,22 @@ pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
*uidl = NULL;
{
char *space;
/* Format: +OK msgno uidlstring */
/* Pass the "+OK". */
space = strchr (pop3->ack.buf, ' ');
if (space)
{
/* Skip spaces. */
while (*space == ' ') space++;
/* Pass the number. */
space = strchr (space, ' ');
if (space)
{
size_t len = strlen (space);
size_t len;
/* Skip spaces between msgno and uidlstring */
while (*space == ' ') space++;
len = strlen (space);
if (space[len - 1] == '\n')
{
space[len - 1] = '\0';
......
......@@ -83,17 +83,16 @@ pop3_uidl_current (iterator_t iterator, unsigned int *pno, char **puidl)
{
char *space;
unsigned int msgno = 0;
/* The format is: msgno uidlstring */
space = strchr (buf, ' ');
if (space)
{
*space++ = '\0';
msgno = strtoul (buf, NULL, 10);
}
msgno = strtoul (buf, &space, 10);
if (space && space[strlen (space) - 1] == '\n')
space[strlen (space) - 1] = '\0';
/* Oops. */
if (space == NULL)
space = (char *)"";
if (pno)
*pno = msgno;
if (puidl)
......
......@@ -90,6 +90,7 @@ pop3_t pop3;
/* When non-zero, this global means the user is done using this program. */
int done;
#if 0
void *
xmalloc (size_t size)
{
......@@ -101,6 +102,7 @@ xmalloc (size_t size)
}
return m;
}
#endif
char *
dupstr (const char *s)
......@@ -371,6 +373,7 @@ com_uidl (char *arg)
unsigned int msgno = strtoul (arg, NULL, 10);
if (pop3_uidl (pop3, msgno, &uidl) == 0)
printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : "");
free (uidl);
}
return 0;
}
......@@ -549,7 +552,7 @@ com_top (char *arg)
{
size_t n = 0;
char buf[128];
while ((stream_readline (stream, buf, sizeof buf, &n) == 0) && n)
while ((stream_readline (stream, buf, sizeof buf, 0, &n) == 0) && n)
printf ("%s", buf);
stream_destroy (&stream);
}
......@@ -573,7 +576,7 @@ com_retr (char *arg)
{
size_t n = 0;
char buf[128];
while ((stream_readline (stream, buf, sizeof buf, &n) == 0) && n)
while ((stream_readline (stream, buf, sizeof buf, 0, &n) == 0) && n)
printf ("%s", buf);
stream_destroy (&stream);
}
......@@ -600,6 +603,7 @@ com_connect (char *arg)
mu_debug_t debug;
pop3_get_debug (pop3, &debug);
mu_debug_set_level (debug, MU_DEBUG_PROT);
mu_debug_destroy (&debug);
pop3_connect (pop3, host, port);
}
else
......
......@@ -110,8 +110,10 @@ _ticket_prompt_ctor (struct _ticket_prompt *prompt)
}
void
_ticket_prompt_dtor (struct _ticket_prompt *prompt)
_ticket_prompt_dtor (ticket_t ticket)
{
struct _ticket_prompt *prompt = (struct _ticket_prompt *)ticket;
if (prompt)
mu_refcount_destroy (&prompt->refcount);
}
......
......@@ -76,6 +76,8 @@ int
_mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg)
{
struct _mu_debug_stream *sdebug = (struct _mu_debug_stream *)debug;
size_t n = 0;
int status;
if (mesg == NULL)
return MU_ERROR_INVALID_PARAMETER;
......@@ -83,7 +85,10 @@ _mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg)
if (!(sdebug->level & level))
return 0;
return stream_write (sdebug->stream, mesg, strlen (mesg), NULL);
status = stream_write (sdebug->stream, mesg, strlen (mesg), sdebug->offset,
&n);
sdebug->offset += n;
return status;
}
static struct _mu_debug_vtable _mu_debug_stream_vtable =
......@@ -117,6 +122,7 @@ mu_debug_stream_create (mu_debug_t *pdebug, stream_t stream,
}
sdebug->level = 0;
sdebug->offset = 0;
sdebug->stream = stream;
sdebug->close_on_destroy = close_on_destroy;
sdebug->base.vtable = &_mu_debug_stream_vtable;
......
......@@ -63,39 +63,30 @@ stream_close (stream_t stream)
}
int
stream_read (stream_t stream, void *buf, size_t buflen, size_t *n)
stream_read (stream_t stream, void *buf, size_t buflen, off_t o, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->read == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->read (stream, buf, buflen, n);
return stream->vtable->read (stream, buf, buflen, o, n);
}
int
stream_readline (stream_t stream, char *buf, size_t buflen, size_t *n)
stream_readline (stream_t stream, char *buf, size_t buflen, off_t o, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->readline == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->readline (stream, buf, buflen, n);
return stream->vtable->readline (stream, buf, buflen, o, n);
}
int
stream_write (stream_t stream, const void *buf, size_t buflen, size_t *n)
stream_write (stream_t stream, const void *buf, size_t buflen, off_t o, size_t *n)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->write == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->write (stream, buf, buflen, n);
}
int
stream_seek (stream_t stream, off_t off, enum stream_whence whence)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->seek == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->seek (stream, off, whence);
return stream->vtable->write (stream, buf, buflen, o, n);
}
int
......@@ -162,6 +153,15 @@ stream_get_state (stream_t stream, enum stream_state *state)
}
int
stream_is_seekable (stream_t stream)
{
if (stream == NULL || stream->vtable == NULL
|| stream->vtable->is_seekable == NULL)
return MU_ERROR_NOT_SUPPORTED;
return stream->vtable->is_seekable (stream);
}
int
stream_is_readready (stream_t stream, int timeout)
{
if (stream == NULL || stream->vtable == NULL
......
......@@ -55,7 +55,7 @@ _stream_tcp_destroy (stream_t *pstream)
struct _stream_tcp *tcp = (struct _stream_tcp *)*pstream;
if (mu_refcount_dec (tcp->base.refcount) == 0)
{
_stream_fd_dtor (&tcp->base);
_stream_fd_dtor (*pstream);
if (tcp->host)
free (tcp->host);
free (tcp);
......