Commit de5a84ae de5a84ae4a3a5c8f8ffa096dcd0cb40ddec9f217 by Alain Magloire

attribute.c attribute.h attribute0.h header.c header.h

 	header0.h io.c io.h io0.h mailbox.c mailbox0.h mbx_unix.c
 	message.c message.h message0.h rfc822.c

message_t is a pure interface.
1 parent c77752c0
......@@ -22,7 +22,7 @@
#include <errno.h>
int
attribute_init (attribute_t *pattr)
attribute_init (attribute_t *pattr, void *owner)
{
attribute_t attr;
if (pattr == NULL)
......@@ -30,19 +30,24 @@ attribute_init (attribute_t *pattr)
attr = calloc (1, sizeof(*attr));
if (attr == NULL)
return ENOMEM;
attr->owner = owner;
*pattr = attr;
return 0;
}
void
attribute_destroy (attribute_t *pattr)
attribute_destroy (attribute_t *pattr, void *owner)
{
if (pattr && *pattr)
{
attribute_t attr = *pattr;
/* no owner we really can free it */
if (! attr->message)
free (*pattr);
attr->ref_count--;
if ((attr->owner && attr->owner == owner) ||
(attr->owner == NULL && attr->ref_count <= 0))
{
free (attr);
}
/* loose the link */
*pattr = NULL;
}
......@@ -249,20 +254,11 @@ attribute_copy (attribute_t dest, attribute_t src)
}
int
attribute_set_owner (attribute_t attr, message_t *msg)
{
if (attr == NULL)
return EINVAL;
attr->message = msg;
return 0;
}
int
attribute_get_owner (attribute_t attr, message_t *msg)
attribute_get_owner (attribute_t attr, void **powner)
{
if (attr == NULL)
return EINVAL;
if (msg)
*msg = attr->message;
if (powner)
*powner = attr->owner;
return 0;
}
......
......@@ -33,8 +33,8 @@ extern "C" {
struct _attribute;
typedef struct _attribute * attribute_t;
extern int attribute_init __P ((attribute_t *));
extern void attribute_destroy __P ((attribute_t *));
extern int attribute_init __P ((attribute_t *, void *owner));
extern void attribute_destroy __P ((attribute_t *, void *owner));
extern int attribute_is_seen __P ((attribute_t));
extern int attribute_is_answered __P ((attribute_t));
......
......@@ -46,13 +46,13 @@ extern "C" {
struct _attribute
{
size_t flag;
void *message;
void *owner;
int ref_count;
};
/* not user visible ?? */
extern int attribute_copy __P ((attribute_t dst, attribute_t src));
extern int attribute_set_owner __P ((attribute_t attr, message_t *msg));
extern int attribute_get_owner __P ((attribute_t attr, message_t *msg));
extern int attribute_get_owner __P ((attribute_t attr, void **owner));
#ifdef __cplusplus
}
......
......@@ -26,18 +26,19 @@
#include <errno.h>
int
header_init (header_t *ph, const char *blurb, size_t len, int flag)
header_init (header_t *ph, const char *blurb, size_t len,
int flag, void *owner)
{
if (flag != MU_HEADER_RFC822)
return ENOTSUP;
return rfc822_init (ph, blurb, len);
return rfc822_init (ph, blurb, len, owner);
}
void
header_destroy (header_t *ph)
header_destroy (header_t *ph, void *owner)
{
if (ph && *ph)
(*ph)->_destroy (ph);
(*ph)->_destroy (ph, owner);
}
/* stub functions */
......
......@@ -69,8 +69,8 @@ struct _header;
typedef struct _header * header_t;
extern int header_init __P ((header_t *, const char *blurb,
size_t ln, int flag));
extern void header_destroy __P ((header_t *));
size_t ln, int flag, void *owner));
extern void header_destroy __P ((header_t *, void *owner));
extern int header_set_value __P ((header_t, const char *fn,
const char *fv, size_t n, int replace));
......
......@@ -48,15 +48,17 @@ struct _header
size_t num;
/* Data */
void *data;
/* owner ? */
void *message;
/* streams */
istream_t is;
ostream_t os;
/* owner ? */
void *owner;
int ref_count;
/* Functions */
int (*_init) __P ((header_t *, const char *, size_t));
void (*_destroy) __P ((header_t *));
int (*_init) __P ((header_t *, const char *, size_t, void *owner));
void (*_destroy) __P ((header_t *, void *owner));
int (*_set_value) __P ((header_t, const char *fn, const char *fv,
size_t n, int replace));
int (*_get_value) __P ((header_t, const char *fn, char *fv,
......@@ -72,8 +74,9 @@ struct _header
};
/* rfc822 */
extern int rfc822_init __P ((header_t *ph, const char *blurb, size_t len));
extern void rfc822_destroy __P ((header_t *ph));
extern int rfc822_init __P ((header_t *ph, const char *blurb,
size_t len, void *owner));
extern void rfc822_destroy __P ((header_t *ph, void *owner));
#ifdef _cpluscplus
}
......
......@@ -22,7 +22,9 @@
#include <stdio.h>
int
istream_init (istream_t *pis)
istream_init (istream_t *pis, int (*_read)
__P ((istream_t, char *, size_t, off_t, ssize_t *)),
void *owner)
{
istream_t is;
if (pis == NULL)
......@@ -30,12 +32,16 @@ istream_init (istream_t *pis)
is = calloc (1, sizeof (*is));
if (is == NULL)
return ENOMEM;
is->owner = owner;
is->_read = _read;
*pis = is;
return 0;
}
int
ostream_init (ostream_t *pos)
ostream_init (ostream_t *pos, int (*_write)
__P ((ostream_t, const char *, size_t, off_t, ssize_t *)),
void *owner)
{
ostream_t os;
if (pos == NULL)
......@@ -43,60 +49,54 @@ ostream_init (ostream_t *pos)
os = calloc (1, sizeof (*os));
if (os == NULL)
return ENOMEM;
os->owner = owner;
os->_write = _write;
*pos = os;
return 0;
}
void
istream_destroy (istream_t *pis)
istream_destroy (istream_t *pis, void *owner)
{
if (pis && *pis)
{
istream_t is = *pis;
is->ref_count--;
if ((is->owner && is->owner == owner) ||
(is->owner == NULL && is->ref_count <= 0))
free (pis);
*pis = NULL;
}
}
void
ostream_destroy (ostream_t *pos)
ostream_destroy (ostream_t *pos, void *owner)
{
free (pos);
if (pos && (*pos))
{
ostream_t os = *pos;
os->ref_count--;
if ((os->owner && os->owner == owner) ||
(os->owner == NULL && os->ref_count <= 0))
free (*pos);
*pos = NULL;
}
}
int
istream_set_read (istream_t is, ssize_t (*read)
__P ((istream_t, char *, size_t, off_t)))
istream_read (istream_t is, char *buf, size_t count,
off_t offset, ssize_t *pnread)
{
if (is == NULL)
if (is == NULL || is->_read == NULL)
return EINVAL;
is->_read = read;
return 0;
return is->_read (is, buf, count, offset, pnread);
}
int
ostream_set_write (ostream_t os, ssize_t (*write)
__P ((ostream_t, const char *, size_t, off_t)))
{
if (os == NULL)
return EINVAL;
os->_write = write;
return 0;
}
ssize_t
istream_read (istream_t is, char *buf, size_t count, off_t offset)
{
if (is == NULL || is->_read == NULL)
{
errno = EINVAL;
return -1;
}
return is->_read (is, buf, count, offset);
}
ssize_t
ostream_write (ostream_t os, const char *buf, size_t count, off_t offset)
ostream_write (ostream_t os, const char *buf, size_t count,
off_t offset, ssize_t *pnwrite)
{
if (os == NULL || os->_write == NULL)
{
errno = EINVAL;
return -1;
}
return os->_write (os, buf, count, offset);
return EINVAL;
return os->_write (os, buf, count, offset, pnwrite);
}
......
......@@ -33,13 +33,14 @@ extern "C" {
#endif /*__P */
struct _istream;
typedef struct _istream * istream_t;
typedef struct _istream *istream_t;
struct _ostream;
typedef struct _ostream * ostream_t;
typedef struct _ostream *ostream_t;
extern ssize_t istream_read __P ((istream_t, char *, size_t, off_t));
extern int istream_read __P ((istream_t, char *, size_t, off_t, ssize_t *));
extern ssize_t ostream_write __P ((ostream_t, const char *, size_t, off_t));
extern int ostream_write __P ((ostream_t, const char *, size_t,
off_t, ssize_t *));
#ifdef __cplusplus
}
......
......@@ -36,20 +36,28 @@ struct _istream
{
/* owner of the stream can not be a specific type */
void *owner;
ssize_t (*_read) __P ((istream_t, char *, size_t, off_t));
int ref_count;
int (*_read) __P ((istream_t, char *, size_t, off_t, ssize_t *));
};
struct _ostream
{
/* owner of the stream can not be a specific type */
void *owner;
ssize_t (*_write) __P ((ostream_t, const char *, size_t, off_t));
int ref_count;
int (*_write) __P ((ostream_t, const char *, size_t, off_t, ssize_t *));
};
extern int istream_init __P ((istream_t *));
extern void istream_destroy __P ((istream_t *));
extern int ostream_init __P ((ostream_t *));
extern void ostream_destroy __P ((ostream_t *));
extern int istream_init __P ((istream_t *,
int (*_read) __P ((istream_t, char *,
size_t, off_t, ssize_t *)),
void *owner));
extern void istream_destroy __P ((istream_t *, void *owner));
extern int ostream_init __P ((ostream_t *,
int (*_write) __P ((ostream_t, const char *,
size_t, off_t, ssize_t *)),
void *owner));
extern void ostream_destroy __P ((ostream_t *, void *owner));
#ifdef __cplusplus
}
......
......@@ -112,17 +112,9 @@ mailbox_append_message (mailbox_t mbox, message_t msg)
int
mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
{
int status;
if (mbox == NULL || pmsg == NULL)
if (mbox == NULL || mbox->_get_message == NULL)
return EINVAL;
if (mailbox_is_deleted (mbox, msgno))
return EINVAL;
status = message_init (pmsg);
if (status != 0)
return status;
(*pmsg)->mailbox = mbox;
(*pmsg)->num = msgno;
return 0;
return mbox->_get_message (mbox, msgno, pmsg);
}
int
......@@ -194,24 +186,6 @@ mailbox_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
return mbox->_get_size (mbox, msgno, h, b);
}
ssize_t
mailbox_get_header (mailbox_t mbox, size_t msgno, char *h,
size_t len, off_t off, int *err)
{
if (mbox == NULL || mbox->_get_header == NULL)
return ENOSYS;
return mbox->_get_header (mbox, msgno, h, len, off, err);
}
ssize_t
mailbox_get_body (mailbox_t mbox, size_t msgno, char *b,
size_t len, off_t off, int *err)
{
if (mbox == NULL || mbox->_get_body == NULL)
return ENOSYS;
return mbox->_get_body (mbox, msgno, b, len, off, err);
}
/* locking */
int
mailbox_set_locker (mailbox_t mbox, locker_t locker)
......@@ -251,18 +225,3 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth)
return 0;
}
int
mailbox_get_attribute (mailbox_t mbox, size_t msgno, attribute_t *pattr)
{
if (mbox == NULL || mbox->_get_attribute == NULL)
return ENOSYS;
return mbox->_get_attribute (mbox, msgno, pattr);
}
int
mailbox_set_attribute (mailbox_t mbox, size_t msgno, attribute_t attr)
{
if (mbox == NULL || mbox->_set_attribute == NULL)
return ENOSYS;
return mbox->_set_attribute (mbox, msgno, attr);
}
......
......@@ -38,17 +38,10 @@ extern "C" {
struct _mailbox
{
/* Data */
char *name;
FILE *file;
message_t *messages;
size_t messages_num;
off_t size;
auth_t auth;
locker_t locker;
url_t url;
int (*_progress) __P ((int, void *arg));
void *progress_arg;
......@@ -80,15 +73,6 @@ struct _mailbox
int (*_num_deleted) __P ((mailbox_t, size_t *));
int (*_get_size) __P ((mailbox_t, size_t msgno,
size_t *h, size_t *b));
ssize_t (*_get_header) __P ((mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err));
ssize_t (*_get_body) __P ((mailbox_t, size_t msgno, char *b,
size_t len, off_t off, int *err));
int (*_get_attribute) __P ((mailbox_t mbox, size_t msgno,
attribute_t *attr));
int (*_set_attribute) __P ((mailbox_t mbox, size_t msgno,
attribute_t attr));
};
/* private */
......
......@@ -22,8 +22,8 @@
#include <message0.h>
#include <url0.h>
#include <attribute0.h>
#include <io0.h>
#include <header.h>
#include <io.h>
#include <auth.h>
#include <locker.h>
......@@ -37,6 +37,7 @@
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#else
......@@ -62,6 +63,7 @@ struct mailbox_registrar _mailbox_unix_registrar =
*/
typedef struct _mailbox_unix_message
{
/* offset of the parts of the messages in the mailbox*/
off_t header;
off_t header_end;
/* little hack to make things easier
......@@ -71,13 +73,28 @@ typedef struct _mailbox_unix_message
off_t hdr_status_end;
off_t body;
off_t body_end;
/* old_attr contains the definition of Header: */
/* new_attr what we want when expunging */
attribute_t old_attr;
attribute_t new_attr;
/* some sort of uniq id, maybe we should use the
* Message-ID of the message, but we'll have to free
* when done.
*/
time_t uid;
size_t num;
FILE *file;
/* if we have a message attach to it */
message_t message;
} *mailbox_unix_message_t;
typedef struct _mailbox_unix_data
{
mailbox_unix_message_t messages;
mailbox_unix_message_t umessages;
size_t messages_count;
FILE *file;
char *dirname;
......@@ -93,6 +110,7 @@ typedef struct _mailbox_unix_data
static int mailbox_unix_open (mailbox_t mbox, int flag);
static int mailbox_unix_close (mailbox_t mbox);
static int mailbox_unix_get_message (mailbox_t, size_t msgno, message_t *msg);
static int mailbox_unix_append_message (mailbox_t, message_t msg);
static int mailbox_unix_messages_count (mailbox_t, size_t *msgno);
static int mailbox_unix_delete (mailbox_t, size_t msgno);
......@@ -108,18 +126,13 @@ static int mailbox_unix_is_updated (mailbox_t);
static int mailbox_unix_size (mailbox_t, off_t *size);
static int mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno,
attribute_t *pattribute);
static int mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno,
attribute_t attribute);
static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err);
static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b,
size_t len, off_t off, int *err);
/* private stuff */
static int mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
off_t off, ssize_t *pnread);
static int mailbox_unix_is_from (const char *);
static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length, size_t msgno);
......@@ -130,12 +143,11 @@ static int mailbox_unix_ilock (mailbox_t mbox, int flag);
static int mailbox_unix_iunlock (mailbox_t mbox);
/* We allocate the mailbox_t struct, but don't do any
* parsing on the name or even thest for existence.
* parsing on the name or even test for existence.
* However we do strip any leading "unix:" part of
* our name, this is suppose to be the protocol/scheme name.
* the name, this is suppose to be the protocol/scheme name.
* Hopefully there will not be a mailbox name "unix:"
*/
static int
mailbox_unix_init (mailbox_t *pmbox, const char *name)
{
......@@ -259,6 +271,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
mbox->_close = mailbox_unix_close;
/* messages */
mbox->_get_message = mailbox_unix_get_message;
mbox->_append_message = mailbox_unix_append_message;
mbox->_messages_count = mailbox_unix_messages_count;
mbox->_delete = mailbox_unix_delete;
......@@ -272,12 +285,6 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
mbox->_size = mailbox_unix_size;
mbox->_get_attribute = mailbox_unix_get_attribute;
mbox->_set_attribute = mailbox_unix_set_attribute;
mbox->_get_header = mailbox_unix_get_header;
mbox->_get_body = mailbox_unix_get_body;
(*pmbox) = mbox;
return 0; /* okdoke */
......@@ -298,27 +305,16 @@ mailbox_unix_destroy (mailbox_t *pmbox)
free (mud->basename);
for (i = 0; i < mud->messages_count; i++)
{
/* orphan the message */
mud->messages[i].old_attr->message = NULL;
mud->messages[i].new_attr->message = NULL;
attribute_destroy (&(mud->messages[i].old_attr));
attribute_destroy (&(mud->messages[i].new_attr));
mailbox_unix_message_t mum = &(mud->umessages[i]);
/* Destroy the attach messages */
message_destroy (&(mum->message), mum);
attribute_destroy (&(mum->old_attr), mbox);
attribute_destroy (&(mum->new_attr), mbox);
}
free (mud->messages);
free (mud->umessages);
free (mbox->data);
}
free (mbox->name);
if (mbox->messages)
{
size_t i;
for (i = 0; i < mbox->messages_num; i++)
{
/* first orphan them */
mbox->messages[i]->mailbox = NULL;
message_destroy (&(mbox->messages[i]));
}
}
free (mbox->messages);
/* destroy the url */
if (mbox->url)
url_destroy (&(mbox->url));
......@@ -327,7 +323,7 @@ mailbox_unix_destroy (mailbox_t *pmbox)
}
}
/* start of mbox Implementation */
/* Open the file. */
static int
mailbox_unix_open (mailbox_t mbox, int flags)
{
......@@ -546,7 +542,7 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
mailbox_unix_message_t mum = &mud->messages[msgno];
mailbox_unix_message_t mum = &mud->umessages[msgno];
char *sep;
/* skip over the remaining header */
......@@ -690,7 +686,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
/* allocate space for the new message */
if (count > mud->messages_count)
{
mum = realloc (mud->messages, count * sizeof (*mum));
mum = realloc (mud->umessages, count * sizeof (*mum));
if (mum == NULL)
{
funlockfile (mud->file);
......@@ -700,10 +696,13 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
}
mud->messages_count++;
memset (&mum[count - 1], 0, sizeof (*mum));
attribute_init (&(mum[count - 1].old_attr));
attribute_init (&(mum[count - 1].new_attr));
attribute_init (&(mum[count - 1].old_attr), mbox);
attribute_init (&(mum[count - 1].new_attr), mbox);
mum[count - 1].uid = time (NULL);
mum[count - 1].file = mud->file;
mum[count - 1].num = count - 1;
}
mud->messages = mum;
mud->umessages = mum;
mum[count - 1].header = ftell (mud->file);
/* substract the overrun */
mum[count - 1].header -= over;
......@@ -794,7 +793,7 @@ mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno)
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
! mailbox_unix_is_valid (mbox, msgno))
return 0;
return attribute_is_deleted (mud->messages[msgno].new_attr);
return attribute_is_deleted (mud->umessages[msgno].new_attr);
}
static int
......@@ -813,7 +812,7 @@ mailbox_unix_delete (mailbox_t mbox, size_t msgno)
return 0;
/* Mark for deletion */
attribute_set_deleted (mud->messages[msgno].new_attr);
attribute_set_deleted (mud->umessages[msgno].new_attr);
return 0;
}
......@@ -828,7 +827,7 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *num)
return EINVAL;
for (i = total = 0; i < mud->messages_count; i++)
{
mum = &mud->messages[i];
mum = &mud->umessages[i];
if (attribute_is_deleted (mum->new_attr))
total++;
}
......@@ -853,7 +852,7 @@ mailbox_unix_undelete (mailbox_t mbox, size_t msgno)
return 0;
/* Mark undeletion */
attribute_unset_deleted (mud->messages[msgno].new_attr);
attribute_unset_deleted (mud->umessages[msgno].new_attr);
return 0;
}
......@@ -905,6 +904,8 @@ mailbox_unix_expunge (mailbox_t mbox)
return ENOLCK;
}
/* FIXME: send notification to all the listeners */
/* Critical section, we can not allowed signal here */
/* FIXME: If NONBLOCKING is set we should unset reset to
* later, we can not afford to luxury here
......@@ -949,7 +950,7 @@ mailbox_unix_expunge (mailbox_t mbox)
/* Go to the first mail with an attribute change */
for (j = 0; j < mud->messages_count; j++)
{
mum = &mud->messages[j];
mum = &mud->umessages[j];
if (! attribute_is_equal (mum->old_attr, mum->new_attr))
break;
}
......@@ -963,14 +964,14 @@ mailbox_unix_expunge (mailbox_t mbox)
}
/* set the marker position */
total = marker = mud->messages[j].header;
total = marker = mud->umessages[j].header;
/* copy to tempfile emails not mark changed */
for (first = 1, i = j; i < mud->messages_count; i++)
{
size_t len;
off_t current;
mum = &mud->messages[i];
mum = &mud->umessages[i];
/* skip it, if mark for deletion */
if (attribute_is_deleted (mum->new_attr))
......@@ -1138,6 +1139,8 @@ mailbox_unix_expunge (mailbox_t mbox)
clearerr (mud->file);
fflush (mud->file);
/* FIXME: update the num of all the messages */
bailout:
/* Release the locks */
if (oflags > 0)
......@@ -1150,92 +1153,78 @@ bailout:
return status;
}
/* reading */
static ssize_t
mailbox_unix_get_body (mailbox_t mbox, size_t msgno, char *buffer,
size_t len, off_t off, int *err)
static int
mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
off_t off, ssize_t *pnread)
{
mailbox_unix_data_t mud;
mailbox_unix_message_t mum;
size_t len;
size_t nread = 0;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
{
if (err)
*err = EINVAL;
return -1;
}
if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL)
return EINVAL;
/* check if valid */
if (len == 0 || mud == NULL || ! mailbox_unix_is_valid (mbox, msgno))
if (buffer == NULL || buflen == 0)
{
if (err)
*err = EINVAL;
return -1;
if (pnread)
*pnread = nread;
return 0;
}
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
flockfile (mum->file);
{
mailbox_unix_message_t mum = &(mud->messages[msgno]);
off_t ln = mum->body_end - (mum->body + off);
if (ln > 0)
{
nread = ((size_t)ln < len) ? ln : len;
/* position the file pointer and the buffer */
if (fseek (mud->file, mum->body + off, SEEK_SET) < 0)
if (fseek (mum->file, mum->body + off, SEEK_SET) < 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (err)
*err = EIO;
return -1;
funlockfile (mum->file);
return errno;
}
if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
if (fread (buffer, sizeof (*buffer), nread, mum->file) != nread)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (err)
*err = EIO;
return -1;
funlockfile (mum->file);
return errno;
}
}
else
nread = 0;
}
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
funlockfile (mum->file);
return nread;
if (pnread)
*pnread = nread;
return 0;
}
static ssize_t
static int
mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
size_t len, off_t off, int *err)
size_t len, off_t off, ssize_t *pnread)
{
mailbox_unix_data_t mud;
size_t nread = 0;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
{
if (err)
*err = EINVAL;
return -1;
}
return EINVAL;
/* check if valid */
if (len == 0 || ! mailbox_unix_is_valid (mbox, msgno))
if (! mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
if (buffer == NULL || len == 0)
{
if (err)
*err = EINVAL;
return -1;
if (pnread)
*pnread = nread;
return 0;
}
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
{
mailbox_unix_message_t mum = &(mud->messages[msgno]);
mailbox_unix_message_t mum = &(mud->umessages[msgno]);
off_t ln = mum->header_end - (mum->header + off);
if (ln > 0)
{
......@@ -1245,17 +1234,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (err)
*err = EIO;
return -1;
return errno;
}
if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
if (err)
*err = EIO;
return -1;
return errno;
}
}
else
......@@ -1264,7 +1249,98 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return nread;
if (pnread)
*pnread = nread;
return 0;
}
static int
mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
{
int status;
ssize_t nread;
char *pbuf = NULL;
char *tbuf = NULL;
char buf[BUFSIZ];
off_t offset = 0;
mailbox_unix_data_t mud;
mailbox_unix_message_t mum;
message_t msg;
istream_t is;
header_t header;
if (mbox == NULL || pmsg == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
mailbox_unix_is_deleted (mbox, msgno))
return EINVAL;
mum = &(mud->umessages[msgno]);
/* check if we already have it */
if (mum->message)
{
if (pmsg)
*pmsg = mum->message;
return 0;
}
/* get the headers */
do {
status = mailbox_unix_get_header (mbox, msgno, buf, sizeof(buf),
offset, &nread);
if (status != 0)
{
free (pbuf);
return status;
}
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
free (pbuf);
return ENOMEM;
}
else
pbuf = tbuf;
memcpy (pbuf + offset, buf, nread);
offset += nread;
} while (nread > 0);
/* get an empty message struct */
status = message_init (&msg, mum);
if (status != 0)
{
free (pbuf);
return status;
}
/* set the header */
status = header_init (&header, pbuf, offset, MU_HEADER_RFC822, mum);
if (status != 0)
{
free (pbuf);
message_destroy (&msg, mum);
return status;
}
free (pbuf);
message_set_header (msg, header, mum);
/* prepare the istream */
status = istream_init (&is, mailbox_unix_readstream, mum);
if (status != 0)
{
free (pbuf);
message_destroy (&msg, mum);
return status;
}
message_set_istream (msg, is, mum);
/* set the attribute */
status = message_set_attribute (msg, mum->new_attr, mum);
if (pmsg)
*pmsg = msg;
return 0;
}
static int
......@@ -1274,6 +1350,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
if (mbox == NULL || msg == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
/* simple check on the flag */
if (! ((mud->flags & MU_MAILBOX_APPEND) ||
(mud->flags & MU_MAILBOX_RDWR) ||
(mud->flags & MU_MAILBOX_WRONLY)))
......@@ -1288,6 +1366,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
size_t nread;
off_t off = 0;
istream_t is;
header_t hdr;
int status;
fd = fileno (mud->file);
if (fstat (fd, &st) != 0)
......@@ -1302,33 +1382,32 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
mailbox_unix_unlock (mbox);
return errno;
}
/* header */
{
header_t hdr;
message_get_header (msg, &hdr);
header_get_istream (hdr, &is);
if (st.st_size != 0)
fputc ('\n', mud->file);
while ((nread = istream_read (is, buffer, sizeof (buffer), off)) > 0)
{
do {
status = istream_read (is, buffer, sizeof (buffer), off, &nread);
if (status != 0)
return status;
fwrite (buffer, sizeof (*buffer), nread, mud->file);
off += nread;
}
}
} while (nread > 0);
*buffer = '\0';
/* separator */
fputc ('\n', mud->file);
/* body */
{
off = 0;
message_get_istream (msg, &is);
while ((nread = istream_read (is, buffer, sizeof (buffer), off)) > 0)
{
do {
istream_read (is, buffer, sizeof (buffer), off, &nread);
fwrite (buffer, sizeof (*buffer), nread, mud->file);
off += nread;
}
}
} while (nread > 0);
}
fflush(mud->file);
funlockfile (mud->file);
......@@ -1369,7 +1448,7 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
!mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
mum = &(mud->messages[msgno]);
mum = &(mud->umessages[msgno]);
if (h)
*h = mum->header_end - mum->header;
if (b)
......@@ -1393,34 +1472,6 @@ mailbox_unix_messages_count (mailbox_t mbox, size_t *count)
return 0;
}
static int
mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno,
attribute_t *pattribute)
{
mailbox_unix_data_t mud;
if (mbox == NULL || pattribute == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
! mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
*pattribute = mud->messages[msgno].new_attr;
return 0;
}
static int
mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno,
attribute_t attribute)
{
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
! mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
attribute_copy (mud->messages[msgno].new_attr, attribute);
return 0;
}
/* locking */
static int
mailbox_unix_lock (mailbox_t mbox, int flag)
......
......@@ -26,8 +26,116 @@
#include <stdio.h>
#include <stdlib.h>
static int message_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread );
static int message_write (ostream_t os, const char *buf, size_t buflen,
off_t off, ssize_t *pnwrite);
int message_clone (message_t omsg, message_t *pmsg)
{
int status;
FILE *file;
message_t msg;
istream_t is;
ostream_t os;
header_t header;
char buffer[BUFSIZ];
char *pbuf = NULL;
char *tbuf = NULL;
off_t offset = 0;
size_t nread = 0;
/* retreive the header */
{
status = message_get_header (omsg, &header);
if (status != 0)
return status;
status = header_get_istream (header, &is);
if (status != 0)
return status;
do {
status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
if (status != 0)
{
free (pbuf);
return status;
}
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
free (pbuf);
return ENOMEM;
}
else
pbuf = tbuf;
memcpy (pbuf + offset, buffer, nread);
offset += nread;
} while (nread > 0);
status = header_init (&header, pbuf, offset, MU_HEADER_RFC822, NULL);
if (status != 0)
{
free (pbuf);
return status;
}
free (pbuf);
}
/* retrieve the body */
{
file = tmpfile ();
if (file == NULL)
{
header_destroy (&header, NULL);
return errno;
}
offset = 0;
message_get_istream (omsg, &is);
do {
istream_read (is, buffer, sizeof (buffer), offset, &nread);
fwrite (buffer, sizeof (*buffer), nread, file);
offset += nread;
} while (nread > 0);
rewind (file);
}
/* create the message */
status = message_init (&msg, NULL);
if (status != 0)
return status;
/* set the header */
message_set_header (msg, header, NULL);
/* set the body with the streams */
msg->body = calloc (1, sizeof (*(msg->body)));
if (msg->body == NULL)
{
fclose (file);
message_destroy (&msg, NULL);
return ENOMEM;
}
status = istream_init (&is, message_read, NULL);
if (status != 0)
{
message_destroy (&msg, NULL);
return status;
}
status = ostream_init (&os, message_write, NULL);
if (status != 0)
{
message_destroy (&msg, NULL);
return status;
}
*pmsg = msg;
return 0;
}
int
message_init (message_t *pmsg)
message_init (message_t *pmsg, void *owner)
{
message_t msg;
......@@ -36,51 +144,32 @@ message_init (message_t *pmsg)
msg = calloc (1, sizeof (*msg));
if (msg == NULL)
return ENOMEM;
msg->owner = owner;
*pmsg = msg;
return 0;
}
void
message_destroy (message_t *pmsg)
message_destroy (message_t *pmsg, void *owner)
{
if (pmsg && *pmsg)
{
message_t msg = *pmsg;
/*
* The message has a mailbox owner
* let the mailbox destroy when it finishes
*/
if (msg->mailbox)
{
/* but still loose the link */
*pmsg = NULL;
return;
}
/* is the header own by us ? */
if (msg->header && msg->header->message == msg)
{
msg->header->message = NULL;
header_destroy (&(msg->header));
}
/* is the attribute own by us ? */
if (msg->attribute && msg->attribute->message == msg)
{
msg->attribute->message = NULL;
attribute_destroy (&(msg->attribute));
}
/* is the istream own by us */
if (msg->is && msg->is->owner == msg)
{
msg->is->owner = NULL;
istream_destroy (&(msg->is));
}
/* is the ostream own by us */
if (msg->os && msg->os->owner == msg)
msg->ref_count--;
if ((msg->owner && msg->owner != owner) ||
(msg->owner == NULL && msg->ref_count <= 0))
{
msg->os->owner = NULL;
ostream_destroy (&(msg->os));
}
/* is it sometype of floating/temporary message */
/* header */
header_destroy (&(msg->header), owner);
/* attribute */
attribute_destroy (&(msg->attribute), owner);
/* istream */
istream_destroy (&(msg->is), owner);
/* ostream */
ostream_destroy (&(msg->os), owner);
/* if sometype of floating/temporary message */
if (msg->body)
{
body_t body = msg->body;
......@@ -90,6 +179,7 @@ message_destroy (message_t *pmsg)
free (msg->body);
}
free (msg);
}
/* loose the link */
*pmsg = NULL;
}
......@@ -98,115 +188,105 @@ message_destroy (message_t *pmsg)
int
message_get_header (message_t msg, header_t *phdr)
{
int err = 0;
int nread;
char *tbuf = NULL;
char buf[BUFSIZ];
if (phdr == NULL || msg == NULL)
return EINVAL;
/* header allready retrieve ? */
if (msg->header != NULL)
{
*phdr = msg->header;
return 0;
}
}
if (msg->mailbox == NULL)
int
message_set_header (message_t msg, header_t hdr, void *owner)
{
if (msg == NULL )
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->header = hdr;
return 0;
}
/* Ok this is where the fun begins, we have to take to account
* the F&$#*#^#&g O_NONBLOCKING, thanks very much to Brian and David.
* So POP for example is a stream protocol where the server
* keeps on sending the data til' the wire turn red. So when
* we hit a bottleneck (EAGAIN, EWOULDBLOCK, EINPROGRESS, etc ..)
* we save our state and propagate the error up. Hopefully
* the people upstairs will do the right thing by recalling
* us again.
* To resume my thoughts ... I do not like it.
*/
while ((nread = mailbox_get_header (msg->mailbox,
msg->num, buf, sizeof(buf),
msg->header_offset, &err)) > 0)
{
tbuf = realloc (msg->header_buffer, msg->header_offset + nread);
if (tbuf == NULL)
{
free (msg->header_buffer);
msg->header_buffer = NULL;
msg->header_offset = 0;
return ENOMEM;
}
else
msg->header_buffer = tbuf;
memcpy (msg->header_buffer + msg->header_offset, buf, nread);
msg->header_offset += nread;
}
int
message_get_istream (message_t msg, istream_t *pis)
{
if (msg == NULL || pis == NULL)
return EINVAL;
*pis = msg->is;
return 0;
}
if (nread < 0)
{
if (err == EAGAIN || err == EINPROGRESS || err == EWOULDBLOCK)
return EAGAIN;
free (msg->header_buffer);
msg->header_buffer = NULL;
msg->header_offset = 0;
return err;
}
int
message_set_istream (message_t msg, istream_t is, void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->is = is;
return 0;
}
err = header_init (&(msg->header), msg->header_buffer,
msg->header_offset, MU_HEADER_RFC822);
if (err == 0)
{
/* we own it */
msg->header->message = msg;
*phdr = msg->header;
msg->header = NULL;
}
/* we can discard it */
free (msg->header_buffer);
msg->header_buffer = NULL;
msg->header_offset = 0;
return err;
int
message_get_ostream (message_t msg, ostream_t *pos)
{
if (msg == NULL || pos == NULL)
return EINVAL;
*pos = msg->os;
return 0;
}
int
message_set_header (message_t msg, header_t hdr)
message_set_ostream (message_t msg, ostream_t os, void *owner)
{
/* Can not do that on a mailbox */
if (msg == NULL || msg->mailbox == NULL)
if (msg == NULL)
return EINVAL;
/* we own it ? */
if (msg->header && msg->header->message == msg)
{
msg->header->message = NULL;
header_destroy (&(msg->header));
}
msg->header = hdr;
if (msg->owner != owner)
return EACCES;
msg->os = os;
return 0;
}
int
message_size (message_t msg, size_t *size)
{
if (msg == NULL)
return EINVAL;
if (msg->_size)
return msg->_size (msg, size);
return ENOSYS;
}
int
message_get_attribute (message_t msg, attribute_t *pattribute)
{
if (msg == NULL || pattribute == NULL)
return EINVAL;
*pattribute = msg->attribute;
return 0;
}
int
message_set_attribute (message_t msg, attribute_t attribute, void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->attribute = attribute;
return 0;
}
static ssize_t
message_read (istream_t is, char *buf, size_t buflen, off_t off)
static int
message_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread )
{
message_t msg = NULL;
ssize_t nread = -1;
int err = 0;
ssize_t nread = 0;
if (is == NULL || (msg = (message_t)is->owner) == NULL)
{
errno = EINVAL;
return -1;
}
if (is == NULL)
return EINVAL;
/* is it own by a mailbox ? */
if (msg->mailbox)
{
nread = mailbox_get_body (msg->mailbox, msg->num, buf,
buflen, off, &err);
errno = err;
}
else if (msg->body)
if (msg->body)
{
body_t body = msg->body;
if (body->file)
......@@ -221,8 +301,8 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off)
if (nread == 0)
{
if (ferror (body->file))
nread = -1;
/* clear the error even for feof() */
return errno;
/* clear the error for feof() */
clearerr (body->file);
}
/* errno set by fread()/fseek() ? */
......@@ -241,54 +321,26 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off)
}
else
{
errno = EINVAL;
nread = -1;
return EINVAL;
}
}
return nread;
}
int
message_get_istream (message_t msg, istream_t *pis)
{
int err;
if (msg == NULL || pis == NULL)
return EINVAL;
/* already done */
if (msg->is)
*pis = msg->is;
err = istream_init (&(msg->is));
if (err != 0)
return err;
/* tell the world this is ours */
msg->is->owner = msg;
msg->is->_read = message_read;
*pis = msg->is;
if (pnread)
*pnread = nread;
return 0;
}
static int
message_write (ostream_t os, const char *buf, size_t buflen, off_t off)
message_write (ostream_t os, const char *buf, size_t buflen,
off_t off, ssize_t *pnwrite)
{
message_t msg = NULL;
ssize_t nwrite = -1;
ssize_t nwrite = 0;
if (os == NULL || (msg = (message_t)os->owner) == NULL)
{
errno = EINVAL;
return -1;
}
if (os == NULL)
return EINVAL;
/* is it own by a mailbox ? */
if (msg->mailbox)
{
/* We can not write in a mailbox this way */
errno = ENOSYS;
return -1;
}
else if (msg->body)
if (msg->body)
{
body_t body = msg->body;
if (body->file)
......@@ -303,8 +355,8 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off)
if (nwrite == 0)
{
if (ferror (body->file))
nwrite = -1;
/* clear the error even for feof() */
return errno;
/* clear the error for feof() */
clearerr (body->file);
}
/* errno set by fread()/fseek() ? */
......@@ -319,108 +371,14 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off)
}
else
nwrite = 0;
errno = 0;
}
else
{
errno = EINVAL;
nwrite = -1;
}
}
return nwrite;
}
int
message_get_ostream (message_t msg, ostream_t *pos)
{
int err;
if (msg == NULL || pos == NULL)
return EINVAL;
/* already done */
if (msg->os)
*pos = msg->os;
err = ostream_init (&(msg->os));
if (err != 0)
return err;
/* tell the world this is ours */
msg->os->owner = msg;
msg->os->_write = message_write;
*pos = msg->os;
return 0;
}
int
message_size (message_t msg, size_t *size)
{
if (msg == NULL || size == NULL)
return EINVAL;
if (msg->mailbox)
{
size_t hs, bs;
int status;
status = mailbox_get_size (msg->mailbox, msg->num, &hs, &bs);
if (status != 0)
return status;
*size = hs + bs;
return 0;
}
return ENOSYS;
}
int
message_get_attribute (message_t msg, attribute_t *pattribute)
{
int status;
if (msg == NULL || pattribute == NULL)
return EINVAL;
/* killroy was here ? */
if (msg->attribute)
*pattribute = msg->attribute;
if (msg->mailbox)
{
int status;
status = mailbox_get_attribute (msg->mailbox, msg->num, pattribute);
if (status != 0)
return status;
msg->attribute = *pattribute;
/* set the owner of the attribute to be us */
(*pattribute)->message = msg;
return 0;
}
status = attribute_init (&(msg->attribute));
if (status == 0)
{
/* we own this baby */
msg->attribute->message = msg;
*pattribute = msg->attribute;
}
return status;
}
int
message_set_attribute (message_t msg, attribute_t attribute)
{
if (msg == NULL)
return EINVAL;
/* own by a mailbox can no set attribute this way */
if (msg->mailbox)
return ENOSYS;
/* we own it ? */
if (msg->attribute && msg->attribute->message == msg)
{
/* orphan it */
msg->attribute->message = NULL;
attribute_destroy (&(msg->attribute));
}
msg->attribute = attribute;
if (pnwrite)
*pnwrite = nwrite;
return 0;
}
......
......@@ -40,23 +40,23 @@ extern "C" {
struct _message;
typedef struct _message *message_t;
extern int message_init __P ((message_t *));
extern void message_destroy __P ((message_t *));
extern int message_init __P ((message_t *, void *owner));
extern void message_destroy __P ((message_t *, void *owner));
extern int message_get_header __P ((message_t, header_t *));
extern int message_set_header __P ((message_t, header_t));
extern int message_set_header __P ((message_t, header_t, void *owner));
extern int message_get_istream __P ((message_t, istream_t *));
extern int message_set_istream __P ((message_t, istream_t *));
extern int message_set_istream __P ((message_t, istream_t, void *owner));
extern int message_get_ostream __P ((message_t, ostream_t *));
extern int message_set_ostream __P ((message_t, ostream_t *));
extern int message_set_ostream __P ((message_t, ostream_t, void *owner));
extern int message_is_multipart __P ((message_t));
extern int message_get_size __P ((message_t, size_t *));
extern int message_get_attribute __P ((message_t, attribute_t *));
extern int message_set_attribute __P ((message_t, attribute_t));
extern int message_set_attribute __P ((message_t, attribute_t, void *owner));
extern int message_clone __P ((message_t, message_t *));
......
......@@ -42,27 +42,27 @@ typedef struct _body * body_t;
/* forward declaration */
struct _message
{
/* whos is the owner, only mailbox can own messages */
mailbox_t mailbox;
header_t header;
istream_t is;
ostream_t os;
body_t body;
size_t num;
attribute_t attribute;
char *header_buffer;
off_t header_offset;
size_t num;
/* who is the owner */
void *owner;
int ref_count;
int (*_get_header) __P ((message_t msg, header_t *hdr));
int (*_set_header) __P ((message_t msg, header_t hdr));
int (*_set_header) __P ((message_t msg, header_t hdr, void *owner));
int (*_get_attribute) __P ((message_t msg, attribute_t *attr));
int (*_set_attribute) __P ((message_t msg, attribute_t attr));
int (*_set_attribute) __P ((message_t msg, attribute_t attr, void *owner));
int (*_get_istream) __P ((message_t msg, istream_t *));
int (*_set_istream) __P ((message_t msg, istream_t));
int (*_set_istream) __P ((message_t msg, istream_t, void *owner));
int (*_get_ostream) __P ((message_t msg, ostream_t *));
int (*_set_ostream) __P ((message_t msg, ostream_t));
int (*_set_ostream) __P ((message_t msg, ostream_t, void *owner));
int (*_size) __P ((message_t msg, size_t *size));
......
......@@ -37,7 +37,8 @@ static int rfc822_entry_value (header_t h, size_t num, char *buf,
size_t buflen, size_t *total);
static int rfc822_get_istream (header_t h, istream_t *pis);
static int rfc822_get_ostream (header_t h, ostream_t *pos);
static ssize_t rfc822_read (istream_t is, char *buf, size_t buflen, off_t off);
static int rfc822_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread);
struct _rfc822
{
......@@ -51,13 +52,14 @@ typedef struct _rfc822 * rfc822_t;
int
rfc822_init (header_t *ph, const char *blurb, size_t len)
rfc822_init (header_t *ph, const char *blurb, size_t len, void *owner)
{
header_t h;
int status;
h = calloc (1, sizeof (*h));
if (h == NULL)
return ENOMEM;
h->owner = owner;
h->_init = rfc822_init;
h->_destroy = rfc822_destroy;
h->_parse = rfc822_parse;
......@@ -77,29 +79,23 @@ rfc822_init (header_t *ph, const char *blurb, size_t len)
}
void
rfc822_destroy (header_t *ph)
rfc822_destroy (header_t *ph, void *owner)
{
if (ph && *ph)
{
header_t h = *ph;
/* own by a message */
if (h->message)
{
*ph = NULL;
return;
}
/* is the istream own by us */
if (h->is && h->is->owner == h)
{
h->is->owner = NULL;
istream_destroy (&(h->is));
}
/* is the ostream own by us */
if (h->os && h->os->owner == h)
/* if destroy is call always decremente */
h->ref_count--;
/* can we destroy ? */
if ((h->owner && h->owner == owner) ||
(h->owner == NULL && h->ref_count <= 0))
{
h->os->owner = NULL;
ostream_destroy (&(h->os));
}
/* io */
istream_destroy (&(h->is), owner);
ostream_destroy (&(h->os), owner);
if (h->data)
{
rfc822_t rfc = (rfc822_t)h->data;
......@@ -108,6 +104,7 @@ rfc822_destroy (header_t *ph)
free (rfc);
}
free (h);
}
*ph = NULL;
}
}
......@@ -342,8 +339,9 @@ rfc822_entry_value (header_t h, size_t num, char *buf,
return 0;
}
static ssize_t
rfc822_read (istream_t is, char *buf, size_t buflen, off_t off)
static int
rfc822_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread)
{
header_t h;
rfc822_t rfc = NULL;
......@@ -351,10 +349,7 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off)
if (is == NULL || (h = (header_t)is->owner) == NULL ||
(rfc = (rfc822_t)h->data) == NULL)
{
errno = EINVAL;
return -1;
}
return EINVAL;
len = rfc->blurb_len - off;
if ((rfc->blurb_len - off) > 0)
......@@ -368,7 +363,9 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off)
else
len = 0;
return len;
if (pnread)
*pnread = len;
return 0;
}
int
......@@ -381,7 +378,7 @@ rfc822_get_istream (header_t h, istream_t *pis)
if (h->is)
*pis = h->is;
err = istream_init (&(h->is));
err = istream_init (&(h->is), rfc822_read, h->owner);
if (err != 0)
return err;
/* tell the world this is ours */
......