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 @@ ...@@ -22,7 +22,7 @@
22 #include <errno.h> 22 #include <errno.h>
23 23
24 int 24 int
25 attribute_init (attribute_t *pattr) 25 attribute_init (attribute_t *pattr, void *owner)
26 { 26 {
27 attribute_t attr; 27 attribute_t attr;
28 if (pattr == NULL) 28 if (pattr == NULL)
...@@ -30,19 +30,24 @@ attribute_init (attribute_t *pattr) ...@@ -30,19 +30,24 @@ attribute_init (attribute_t *pattr)
30 attr = calloc (1, sizeof(*attr)); 30 attr = calloc (1, sizeof(*attr));
31 if (attr == NULL) 31 if (attr == NULL)
32 return ENOMEM; 32 return ENOMEM;
33 attr->owner = owner;
33 *pattr = attr; 34 *pattr = attr;
34 return 0; 35 return 0;
35 } 36 }
36 37
37 void 38 void
38 attribute_destroy (attribute_t *pattr) 39 attribute_destroy (attribute_t *pattr, void *owner)
39 { 40 {
40 if (pattr && *pattr) 41 if (pattr && *pattr)
41 { 42 {
42 attribute_t attr = *pattr; 43 attribute_t attr = *pattr;
43 /* no owner we really can free it */ 44
44 if (! attr->message) 45 attr->ref_count--;
45 free (*pattr); 46 if ((attr->owner && attr->owner == owner) ||
47 (attr->owner == NULL && attr->ref_count <= 0))
48 {
49 free (attr);
50 }
46 /* loose the link */ 51 /* loose the link */
47 *pattr = NULL; 52 *pattr = NULL;
48 } 53 }
...@@ -249,20 +254,11 @@ attribute_copy (attribute_t dest, attribute_t src) ...@@ -249,20 +254,11 @@ attribute_copy (attribute_t dest, attribute_t src)
249 } 254 }
250 255
251 int 256 int
252 attribute_set_owner (attribute_t attr, message_t *msg) 257 attribute_get_owner (attribute_t attr, void **powner)
253 {
254 if (attr == NULL)
255 return EINVAL;
256 attr->message = msg;
257 return 0;
258 }
259
260 int
261 attribute_get_owner (attribute_t attr, message_t *msg)
262 { 258 {
263 if (attr == NULL) 259 if (attr == NULL)
264 return EINVAL; 260 return EINVAL;
265 if (msg) 261 if (powner)
266 *msg = attr->message; 262 *powner = attr->owner;
267 return 0; 263 return 0;
268 } 264 }
......
...@@ -33,8 +33,8 @@ extern "C" { ...@@ -33,8 +33,8 @@ extern "C" {
33 struct _attribute; 33 struct _attribute;
34 typedef struct _attribute * attribute_t; 34 typedef struct _attribute * attribute_t;
35 35
36 extern int attribute_init __P ((attribute_t *)); 36 extern int attribute_init __P ((attribute_t *, void *owner));
37 extern void attribute_destroy __P ((attribute_t *)); 37 extern void attribute_destroy __P ((attribute_t *, void *owner));
38 38
39 extern int attribute_is_seen __P ((attribute_t)); 39 extern int attribute_is_seen __P ((attribute_t));
40 extern int attribute_is_answered __P ((attribute_t)); 40 extern int attribute_is_answered __P ((attribute_t));
......
...@@ -46,13 +46,13 @@ extern "C" { ...@@ -46,13 +46,13 @@ extern "C" {
46 struct _attribute 46 struct _attribute
47 { 47 {
48 size_t flag; 48 size_t flag;
49 void *message; 49 void *owner;
50 int ref_count;
50 }; 51 };
51 52
52 /* not user visible ?? */ 53 /* not user visible ?? */
53 extern int attribute_copy __P ((attribute_t dst, attribute_t src)); 54 extern int attribute_copy __P ((attribute_t dst, attribute_t src));
54 extern int attribute_set_owner __P ((attribute_t attr, message_t *msg)); 55 extern int attribute_get_owner __P ((attribute_t attr, void **owner));
55 extern int attribute_get_owner __P ((attribute_t attr, message_t *msg));
56 56
57 #ifdef __cplusplus 57 #ifdef __cplusplus
58 } 58 }
......
...@@ -26,18 +26,19 @@ ...@@ -26,18 +26,19 @@
26 #include <errno.h> 26 #include <errno.h>
27 27
28 int 28 int
29 header_init (header_t *ph, const char *blurb, size_t len, int flag) 29 header_init (header_t *ph, const char *blurb, size_t len,
30 int flag, void *owner)
30 { 31 {
31 if (flag != MU_HEADER_RFC822) 32 if (flag != MU_HEADER_RFC822)
32 return ENOTSUP; 33 return ENOTSUP;
33 return rfc822_init (ph, blurb, len); 34 return rfc822_init (ph, blurb, len, owner);
34 } 35 }
35 36
36 void 37 void
37 header_destroy (header_t *ph) 38 header_destroy (header_t *ph, void *owner)
38 { 39 {
39 if (ph && *ph) 40 if (ph && *ph)
40 (*ph)->_destroy (ph); 41 (*ph)->_destroy (ph, owner);
41 } 42 }
42 43
43 /* stub functions */ 44 /* stub functions */
......
...@@ -69,8 +69,8 @@ struct _header; ...@@ -69,8 +69,8 @@ struct _header;
69 typedef struct _header * header_t; 69 typedef struct _header * header_t;
70 70
71 extern int header_init __P ((header_t *, const char *blurb, 71 extern int header_init __P ((header_t *, const char *blurb,
72 size_t ln, int flag)); 72 size_t ln, int flag, void *owner));
73 extern void header_destroy __P ((header_t *)); 73 extern void header_destroy __P ((header_t *, void *owner));
74 74
75 extern int header_set_value __P ((header_t, const char *fn, 75 extern int header_set_value __P ((header_t, const char *fn,
76 const char *fv, size_t n, int replace)); 76 const char *fv, size_t n, int replace));
......
...@@ -48,15 +48,17 @@ struct _header ...@@ -48,15 +48,17 @@ struct _header
48 size_t num; 48 size_t num;
49 /* Data */ 49 /* Data */
50 void *data; 50 void *data;
51 /* owner ? */
52 void *message;
53 /* streams */ 51 /* streams */
54 istream_t is; 52 istream_t is;
55 ostream_t os; 53 ostream_t os;
56 54
55 /* owner ? */
56 void *owner;
57 int ref_count;
58
57 /* Functions */ 59 /* Functions */
58 int (*_init) __P ((header_t *, const char *, size_t)); 60 int (*_init) __P ((header_t *, const char *, size_t, void *owner));
59 void (*_destroy) __P ((header_t *)); 61 void (*_destroy) __P ((header_t *, void *owner));
60 int (*_set_value) __P ((header_t, const char *fn, const char *fv, 62 int (*_set_value) __P ((header_t, const char *fn, const char *fv,
61 size_t n, int replace)); 63 size_t n, int replace));
62 int (*_get_value) __P ((header_t, const char *fn, char *fv, 64 int (*_get_value) __P ((header_t, const char *fn, char *fv,
...@@ -72,8 +74,9 @@ struct _header ...@@ -72,8 +74,9 @@ struct _header
72 }; 74 };
73 75
74 /* rfc822 */ 76 /* rfc822 */
75 extern int rfc822_init __P ((header_t *ph, const char *blurb, size_t len)); 77 extern int rfc822_init __P ((header_t *ph, const char *blurb,
76 extern void rfc822_destroy __P ((header_t *ph)); 78 size_t len, void *owner));
79 extern void rfc822_destroy __P ((header_t *ph, void *owner));
77 80
78 #ifdef _cpluscplus 81 #ifdef _cpluscplus
79 } 82 }
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
22 #include <stdio.h> 22 #include <stdio.h>
23 23
24 int 24 int
25 istream_init (istream_t *pis) 25 istream_init (istream_t *pis, int (*_read)
26 __P ((istream_t, char *, size_t, off_t, ssize_t *)),
27 void *owner)
26 { 28 {
27 istream_t is; 29 istream_t is;
28 if (pis == NULL) 30 if (pis == NULL)
...@@ -30,12 +32,16 @@ istream_init (istream_t *pis) ...@@ -30,12 +32,16 @@ istream_init (istream_t *pis)
30 is = calloc (1, sizeof (*is)); 32 is = calloc (1, sizeof (*is));
31 if (is == NULL) 33 if (is == NULL)
32 return ENOMEM; 34 return ENOMEM;
35 is->owner = owner;
36 is->_read = _read;
33 *pis = is; 37 *pis = is;
34 return 0; 38 return 0;
35 } 39 }
36 40
37 int 41 int
38 ostream_init (ostream_t *pos) 42 ostream_init (ostream_t *pos, int (*_write)
43 __P ((ostream_t, const char *, size_t, off_t, ssize_t *)),
44 void *owner)
39 { 45 {
40 ostream_t os; 46 ostream_t os;
41 if (pos == NULL) 47 if (pos == NULL)
...@@ -43,60 +49,54 @@ ostream_init (ostream_t *pos) ...@@ -43,60 +49,54 @@ ostream_init (ostream_t *pos)
43 os = calloc (1, sizeof (*os)); 49 os = calloc (1, sizeof (*os));
44 if (os == NULL) 50 if (os == NULL)
45 return ENOMEM; 51 return ENOMEM;
52 os->owner = owner;
53 os->_write = _write;
46 *pos = os; 54 *pos = os;
47 return 0; 55 return 0;
48 } 56 }
49 57
50 void 58 void
51 istream_destroy (istream_t *pis) 59 istream_destroy (istream_t *pis, void *owner)
52 { 60 {
61 if (pis && *pis)
62 {
63 istream_t is = *pis;
64 is->ref_count--;
65 if ((is->owner && is->owner == owner) ||
66 (is->owner == NULL && is->ref_count <= 0))
53 free (pis); 67 free (pis);
68 *pis = NULL;
69 }
54 } 70 }
55 71
56 void 72 void
57 ostream_destroy (ostream_t *pos) 73 ostream_destroy (ostream_t *pos, void *owner)
58 { 74 {
59 free (pos); 75 if (pos && (*pos))
76 {
77 ostream_t os = *pos;
78 os->ref_count--;
79 if ((os->owner && os->owner == owner) ||
80 (os->owner == NULL && os->ref_count <= 0))
81 free (*pos);
82 *pos = NULL;
83 }
60 } 84 }
61 85
62 int 86 int
63 istream_set_read (istream_t is, ssize_t (*read) 87 istream_read (istream_t is, char *buf, size_t count,
64 __P ((istream_t, char *, size_t, off_t))) 88 off_t offset, ssize_t *pnread)
65 { 89 {
66 if (is == NULL) 90 if (is == NULL || is->_read == NULL)
67 return EINVAL; 91 return EINVAL;
68 is->_read = read; 92 return is->_read (is, buf, count, offset, pnread);
69 return 0;
70 } 93 }
71 94
72 int 95 int
73 ostream_set_write (ostream_t os, ssize_t (*write) 96 ostream_write (ostream_t os, const char *buf, size_t count,
74 __P ((ostream_t, const char *, size_t, off_t))) 97 off_t offset, ssize_t *pnwrite)
75 {
76 if (os == NULL)
77 return EINVAL;
78 os->_write = write;
79 return 0;
80 }
81
82 ssize_t
83 istream_read (istream_t is, char *buf, size_t count, off_t offset)
84 {
85 if (is == NULL || is->_read == NULL)
86 {
87 errno = EINVAL;
88 return -1;
89 }
90 return is->_read (is, buf, count, offset);
91 }
92
93 ssize_t
94 ostream_write (ostream_t os, const char *buf, size_t count, off_t offset)
95 { 98 {
96 if (os == NULL || os->_write == NULL) 99 if (os == NULL || os->_write == NULL)
97 { 100 return EINVAL;
98 errno = EINVAL; 101 return os->_write (os, buf, count, offset, pnwrite);
99 return -1;
100 }
101 return os->_write (os, buf, count, offset);
102 } 102 }
......
...@@ -33,13 +33,14 @@ extern "C" { ...@@ -33,13 +33,14 @@ extern "C" {
33 #endif /*__P */ 33 #endif /*__P */
34 34
35 struct _istream; 35 struct _istream;
36 typedef struct _istream * istream_t; 36 typedef struct _istream *istream_t;
37 struct _ostream; 37 struct _ostream;
38 typedef struct _ostream * ostream_t; 38 typedef struct _ostream *ostream_t;
39 39
40 extern ssize_t istream_read __P ((istream_t, char *, size_t, off_t)); 40 extern int istream_read __P ((istream_t, char *, size_t, off_t, ssize_t *));
41 41
42 extern ssize_t ostream_write __P ((ostream_t, const char *, size_t, off_t)); 42 extern int ostream_write __P ((ostream_t, const char *, size_t,
43 off_t, ssize_t *));
43 44
44 #ifdef __cplusplus 45 #ifdef __cplusplus
45 } 46 }
......
...@@ -36,20 +36,28 @@ struct _istream ...@@ -36,20 +36,28 @@ struct _istream
36 { 36 {
37 /* owner of the stream can not be a specific type */ 37 /* owner of the stream can not be a specific type */
38 void *owner; 38 void *owner;
39 ssize_t (*_read) __P ((istream_t, char *, size_t, off_t)); 39 int ref_count;
40 int (*_read) __P ((istream_t, char *, size_t, off_t, ssize_t *));
40 }; 41 };
41 42
42 struct _ostream 43 struct _ostream
43 { 44 {
44 /* owner of the stream can not be a specific type */ 45 /* owner of the stream can not be a specific type */
45 void *owner; 46 void *owner;
46 ssize_t (*_write) __P ((ostream_t, const char *, size_t, off_t)); 47 int ref_count;
48 int (*_write) __P ((ostream_t, const char *, size_t, off_t, ssize_t *));
47 }; 49 };
48 50
49 extern int istream_init __P ((istream_t *)); 51 extern int istream_init __P ((istream_t *,
50 extern void istream_destroy __P ((istream_t *)); 52 int (*_read) __P ((istream_t, char *,
51 extern int ostream_init __P ((ostream_t *)); 53 size_t, off_t, ssize_t *)),
52 extern void ostream_destroy __P ((ostream_t *)); 54 void *owner));
55 extern void istream_destroy __P ((istream_t *, void *owner));
56 extern int ostream_init __P ((ostream_t *,
57 int (*_write) __P ((ostream_t, const char *,
58 size_t, off_t, ssize_t *)),
59 void *owner));
60 extern void ostream_destroy __P ((ostream_t *, void *owner));
53 61
54 #ifdef __cplusplus 62 #ifdef __cplusplus
55 } 63 }
......
...@@ -112,17 +112,9 @@ mailbox_append_message (mailbox_t mbox, message_t msg) ...@@ -112,17 +112,9 @@ mailbox_append_message (mailbox_t mbox, message_t msg)
112 int 112 int
113 mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) 113 mailbox_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
114 { 114 {
115 int status; 115 if (mbox == NULL || mbox->_get_message == NULL)
116 if (mbox == NULL || pmsg == NULL)
117 return EINVAL; 116 return EINVAL;
118 if (mailbox_is_deleted (mbox, msgno)) 117 return mbox->_get_message (mbox, msgno, pmsg);
119 return EINVAL;
120 status = message_init (pmsg);
121 if (status != 0)
122 return status;
123 (*pmsg)->mailbox = mbox;
124 (*pmsg)->num = msgno;
125 return 0;
126 } 118 }
127 119
128 int 120 int
...@@ -194,24 +186,6 @@ mailbox_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) ...@@ -194,24 +186,6 @@ mailbox_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
194 return mbox->_get_size (mbox, msgno, h, b); 186 return mbox->_get_size (mbox, msgno, h, b);
195 } 187 }
196 188
197 ssize_t
198 mailbox_get_header (mailbox_t mbox, size_t msgno, char *h,
199 size_t len, off_t off, int *err)
200 {
201 if (mbox == NULL || mbox->_get_header == NULL)
202 return ENOSYS;
203 return mbox->_get_header (mbox, msgno, h, len, off, err);
204 }
205
206 ssize_t
207 mailbox_get_body (mailbox_t mbox, size_t msgno, char *b,
208 size_t len, off_t off, int *err)
209 {
210 if (mbox == NULL || mbox->_get_body == NULL)
211 return ENOSYS;
212 return mbox->_get_body (mbox, msgno, b, len, off, err);
213 }
214
215 /* locking */ 189 /* locking */
216 int 190 int
217 mailbox_set_locker (mailbox_t mbox, locker_t locker) 191 mailbox_set_locker (mailbox_t mbox, locker_t locker)
...@@ -251,18 +225,3 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth) ...@@ -251,18 +225,3 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth)
251 return 0; 225 return 0;
252 } 226 }
253 227
254 int
255 mailbox_get_attribute (mailbox_t mbox, size_t msgno, attribute_t *pattr)
256 {
257 if (mbox == NULL || mbox->_get_attribute == NULL)
258 return ENOSYS;
259 return mbox->_get_attribute (mbox, msgno, pattr);
260 }
261
262 int
263 mailbox_set_attribute (mailbox_t mbox, size_t msgno, attribute_t attr)
264 {
265 if (mbox == NULL || mbox->_set_attribute == NULL)
266 return ENOSYS;
267 return mbox->_set_attribute (mbox, msgno, attr);
268 }
......
...@@ -38,17 +38,10 @@ extern "C" { ...@@ -38,17 +38,10 @@ extern "C" {
38 struct _mailbox 38 struct _mailbox
39 { 39 {
40 /* Data */ 40 /* Data */
41
42 char *name; 41 char *name;
43 FILE *file;
44 message_t *messages;
45 size_t messages_num;
46 off_t size;
47
48 auth_t auth; 42 auth_t auth;
49 locker_t locker; 43 locker_t locker;
50 url_t url; 44 url_t url;
51
52 int (*_progress) __P ((int, void *arg)); 45 int (*_progress) __P ((int, void *arg));
53 void *progress_arg; 46 void *progress_arg;
54 47
...@@ -80,15 +73,6 @@ struct _mailbox ...@@ -80,15 +73,6 @@ struct _mailbox
80 int (*_num_deleted) __P ((mailbox_t, size_t *)); 73 int (*_num_deleted) __P ((mailbox_t, size_t *));
81 int (*_get_size) __P ((mailbox_t, size_t msgno, 74 int (*_get_size) __P ((mailbox_t, size_t msgno,
82 size_t *h, size_t *b)); 75 size_t *h, size_t *b));
83
84 ssize_t (*_get_header) __P ((mailbox_t, size_t msgno, char *h,
85 size_t len, off_t off, int *err));
86 ssize_t (*_get_body) __P ((mailbox_t, size_t msgno, char *b,
87 size_t len, off_t off, int *err));
88 int (*_get_attribute) __P ((mailbox_t mbox, size_t msgno,
89 attribute_t *attr));
90 int (*_set_attribute) __P ((mailbox_t mbox, size_t msgno,
91 attribute_t attr));
92 }; 76 };
93 77
94 /* private */ 78 /* private */
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
22 #include <message0.h> 22 #include <message0.h>
23 #include <url0.h> 23 #include <url0.h>
24 #include <attribute0.h> 24 #include <attribute0.h>
25 #include <io0.h>
25 #include <header.h> 26 #include <header.h>
26 #include <io.h>
27 #include <auth.h> 27 #include <auth.h>
28 #include <locker.h> 28 #include <locker.h>
29 29
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
37 #include <unistd.h> 37 #include <unistd.h>
38 #include <signal.h> 38 #include <signal.h>
39 #include <errno.h> 39 #include <errno.h>
40 #include <time.h>
40 #ifdef HAVE_PTHREAD_H 41 #ifdef HAVE_PTHREAD_H
41 # include <pthread.h> 42 # include <pthread.h>
42 #else 43 #else
...@@ -62,6 +63,7 @@ struct mailbox_registrar _mailbox_unix_registrar = ...@@ -62,6 +63,7 @@ struct mailbox_registrar _mailbox_unix_registrar =
62 */ 63 */
63 typedef struct _mailbox_unix_message 64 typedef struct _mailbox_unix_message
64 { 65 {
66 /* offset of the parts of the messages in the mailbox*/
65 off_t header; 67 off_t header;
66 off_t header_end; 68 off_t header_end;
67 /* little hack to make things easier 69 /* little hack to make things easier
...@@ -71,13 +73,28 @@ typedef struct _mailbox_unix_message ...@@ -71,13 +73,28 @@ typedef struct _mailbox_unix_message
71 off_t hdr_status_end; 73 off_t hdr_status_end;
72 off_t body; 74 off_t body;
73 off_t body_end; 75 off_t body_end;
76
77 /* old_attr contains the definition of Header: */
78 /* new_attr what we want when expunging */
74 attribute_t old_attr; 79 attribute_t old_attr;
75 attribute_t new_attr; 80 attribute_t new_attr;
81
82 /* some sort of uniq id, maybe we should use the
83 * Message-ID of the message, but we'll have to free
84 * when done.
85 */
86 time_t uid;
87 size_t num;
88 FILE *file;
89
90 /* if we have a message attach to it */
91 message_t message;
92
76 } *mailbox_unix_message_t; 93 } *mailbox_unix_message_t;
77 94
78 typedef struct _mailbox_unix_data 95 typedef struct _mailbox_unix_data
79 { 96 {
80 mailbox_unix_message_t messages; 97 mailbox_unix_message_t umessages;
81 size_t messages_count; 98 size_t messages_count;
82 FILE *file; 99 FILE *file;
83 char *dirname; 100 char *dirname;
...@@ -93,6 +110,7 @@ typedef struct _mailbox_unix_data ...@@ -93,6 +110,7 @@ typedef struct _mailbox_unix_data
93 static int mailbox_unix_open (mailbox_t mbox, int flag); 110 static int mailbox_unix_open (mailbox_t mbox, int flag);
94 static int mailbox_unix_close (mailbox_t mbox); 111 static int mailbox_unix_close (mailbox_t mbox);
95 112
113 static int mailbox_unix_get_message (mailbox_t, size_t msgno, message_t *msg);
96 static int mailbox_unix_append_message (mailbox_t, message_t msg); 114 static int mailbox_unix_append_message (mailbox_t, message_t msg);
97 static int mailbox_unix_messages_count (mailbox_t, size_t *msgno); 115 static int mailbox_unix_messages_count (mailbox_t, size_t *msgno);
98 static int mailbox_unix_delete (mailbox_t, size_t msgno); 116 static int mailbox_unix_delete (mailbox_t, size_t msgno);
...@@ -108,18 +126,13 @@ static int mailbox_unix_is_updated (mailbox_t); ...@@ -108,18 +126,13 @@ static int mailbox_unix_is_updated (mailbox_t);
108 126
109 static int mailbox_unix_size (mailbox_t, off_t *size); 127 static int mailbox_unix_size (mailbox_t, off_t *size);
110 128
111 static int mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno,
112 attribute_t *pattribute);
113 static int mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno,
114 attribute_t attribute);
115
116 static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h, 129 static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h,
117 size_t len, off_t off, int *err); 130 size_t len, off_t off, int *err);
118 static ssize_t mailbox_unix_get_body (mailbox_t, size_t msgno, char *b,
119 size_t len, off_t off, int *err);
120 131
121 132
122 /* private stuff */ 133 /* private stuff */
134 static int mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
135 off_t off, ssize_t *pnread);
123 static int mailbox_unix_is_from (const char *); 136 static int mailbox_unix_is_from (const char *);
124 static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, 137 static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
125 off_t *content_length, size_t msgno); 138 off_t *content_length, size_t msgno);
...@@ -130,12 +143,11 @@ static int mailbox_unix_ilock (mailbox_t mbox, int flag); ...@@ -130,12 +143,11 @@ static int mailbox_unix_ilock (mailbox_t mbox, int flag);
130 static int mailbox_unix_iunlock (mailbox_t mbox); 143 static int mailbox_unix_iunlock (mailbox_t mbox);
131 144
132 /* We allocate the mailbox_t struct, but don't do any 145 /* We allocate the mailbox_t struct, but don't do any
133 * parsing on the name or even thest for existence. 146 * parsing on the name or even test for existence.
134 * However we do strip any leading "unix:" part of 147 * However we do strip any leading "unix:" part of
135 * our name, this is suppose to be the protocol/scheme name. 148 * the name, this is suppose to be the protocol/scheme name.
136 * Hopefully there will not be a mailbox name "unix:" 149 * Hopefully there will not be a mailbox name "unix:"
137 */ 150 */
138
139 static int 151 static int
140 mailbox_unix_init (mailbox_t *pmbox, const char *name) 152 mailbox_unix_init (mailbox_t *pmbox, const char *name)
141 { 153 {
...@@ -259,6 +271,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) ...@@ -259,6 +271,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
259 mbox->_close = mailbox_unix_close; 271 mbox->_close = mailbox_unix_close;
260 272
261 /* messages */ 273 /* messages */
274 mbox->_get_message = mailbox_unix_get_message;
262 mbox->_append_message = mailbox_unix_append_message; 275 mbox->_append_message = mailbox_unix_append_message;
263 mbox->_messages_count = mailbox_unix_messages_count; 276 mbox->_messages_count = mailbox_unix_messages_count;
264 mbox->_delete = mailbox_unix_delete; 277 mbox->_delete = mailbox_unix_delete;
...@@ -272,12 +285,6 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) ...@@ -272,12 +285,6 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
272 285
273 mbox->_size = mailbox_unix_size; 286 mbox->_size = mailbox_unix_size;
274 287
275 mbox->_get_attribute = mailbox_unix_get_attribute;
276 mbox->_set_attribute = mailbox_unix_set_attribute;
277
278 mbox->_get_header = mailbox_unix_get_header;
279 mbox->_get_body = mailbox_unix_get_body;
280
281 (*pmbox) = mbox; 288 (*pmbox) = mbox;
282 289
283 return 0; /* okdoke */ 290 return 0; /* okdoke */
...@@ -298,27 +305,16 @@ mailbox_unix_destroy (mailbox_t *pmbox) ...@@ -298,27 +305,16 @@ mailbox_unix_destroy (mailbox_t *pmbox)
298 free (mud->basename); 305 free (mud->basename);
299 for (i = 0; i < mud->messages_count; i++) 306 for (i = 0; i < mud->messages_count; i++)
300 { 307 {
301 /* orphan the message */ 308 mailbox_unix_message_t mum = &(mud->umessages[i]);
302 mud->messages[i].old_attr->message = NULL; 309 /* Destroy the attach messages */
303 mud->messages[i].new_attr->message = NULL; 310 message_destroy (&(mum->message), mum);
304 attribute_destroy (&(mud->messages[i].old_attr)); 311 attribute_destroy (&(mum->old_attr), mbox);
305 attribute_destroy (&(mud->messages[i].new_attr)); 312 attribute_destroy (&(mum->new_attr), mbox);
306 } 313 }
307 free (mud->messages); 314 free (mud->umessages);
308 free (mbox->data); 315 free (mbox->data);
309 } 316 }
310 free (mbox->name); 317 free (mbox->name);
311 if (mbox->messages)
312 {
313 size_t i;
314 for (i = 0; i < mbox->messages_num; i++)
315 {
316 /* first orphan them */
317 mbox->messages[i]->mailbox = NULL;
318 message_destroy (&(mbox->messages[i]));
319 }
320 }
321 free (mbox->messages);
322 /* destroy the url */ 318 /* destroy the url */
323 if (mbox->url) 319 if (mbox->url)
324 url_destroy (&(mbox->url)); 320 url_destroy (&(mbox->url));
...@@ -327,7 +323,7 @@ mailbox_unix_destroy (mailbox_t *pmbox) ...@@ -327,7 +323,7 @@ mailbox_unix_destroy (mailbox_t *pmbox)
327 } 323 }
328 } 324 }
329 325
330 /* start of mbox Implementation */ 326 /* Open the file. */
331 static int 327 static int
332 mailbox_unix_open (mailbox_t mbox, int flags) 328 mailbox_unix_open (mailbox_t mbox, int flags)
333 { 329 {
...@@ -546,7 +542,7 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len, ...@@ -546,7 +542,7 @@ mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
546 off_t *content_length, size_t msgno) 542 off_t *content_length, size_t msgno)
547 { 543 {
548 mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data; 544 mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
549 mailbox_unix_message_t mum = &mud->messages[msgno]; 545 mailbox_unix_message_t mum = &mud->umessages[msgno];
550 char *sep; 546 char *sep;
551 547
552 /* skip over the remaining header */ 548 /* skip over the remaining header */
...@@ -690,7 +686,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) ...@@ -690,7 +686,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
690 /* allocate space for the new message */ 686 /* allocate space for the new message */
691 if (count > mud->messages_count) 687 if (count > mud->messages_count)
692 { 688 {
693 mum = realloc (mud->messages, count * sizeof (*mum)); 689 mum = realloc (mud->umessages, count * sizeof (*mum));
694 if (mum == NULL) 690 if (mum == NULL)
695 { 691 {
696 funlockfile (mud->file); 692 funlockfile (mud->file);
...@@ -700,10 +696,13 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) ...@@ -700,10 +696,13 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
700 } 696 }
701 mud->messages_count++; 697 mud->messages_count++;
702 memset (&mum[count - 1], 0, sizeof (*mum)); 698 memset (&mum[count - 1], 0, sizeof (*mum));
703 attribute_init (&(mum[count - 1].old_attr)); 699 attribute_init (&(mum[count - 1].old_attr), mbox);
704 attribute_init (&(mum[count - 1].new_attr)); 700 attribute_init (&(mum[count - 1].new_attr), mbox);
701 mum[count - 1].uid = time (NULL);
702 mum[count - 1].file = mud->file;
703 mum[count - 1].num = count - 1;
705 } 704 }
706 mud->messages = mum; 705 mud->umessages = mum;
707 mum[count - 1].header = ftell (mud->file); 706 mum[count - 1].header = ftell (mud->file);
708 /* substract the overrun */ 707 /* substract the overrun */
709 mum[count - 1].header -= over; 708 mum[count - 1].header -= over;
...@@ -794,7 +793,7 @@ mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno) ...@@ -794,7 +793,7 @@ mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno)
794 (mud = (mailbox_unix_data_t)mbox->data) == NULL || 793 (mud = (mailbox_unix_data_t)mbox->data) == NULL ||
795 ! mailbox_unix_is_valid (mbox, msgno)) 794 ! mailbox_unix_is_valid (mbox, msgno))
796 return 0; 795 return 0;
797 return attribute_is_deleted (mud->messages[msgno].new_attr); 796 return attribute_is_deleted (mud->umessages[msgno].new_attr);
798 } 797 }
799 798
800 static int 799 static int
...@@ -813,7 +812,7 @@ mailbox_unix_delete (mailbox_t mbox, size_t msgno) ...@@ -813,7 +812,7 @@ mailbox_unix_delete (mailbox_t mbox, size_t msgno)
813 return 0; 812 return 0;
814 813
815 /* Mark for deletion */ 814 /* Mark for deletion */
816 attribute_set_deleted (mud->messages[msgno].new_attr); 815 attribute_set_deleted (mud->umessages[msgno].new_attr);
817 return 0; 816 return 0;
818 } 817 }
819 818
...@@ -828,7 +827,7 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *num) ...@@ -828,7 +827,7 @@ mailbox_unix_num_deleted (mailbox_t mbox, size_t *num)
828 return EINVAL; 827 return EINVAL;
829 for (i = total = 0; i < mud->messages_count; i++) 828 for (i = total = 0; i < mud->messages_count; i++)
830 { 829 {
831 mum = &mud->messages[i]; 830 mum = &mud->umessages[i];
832 if (attribute_is_deleted (mum->new_attr)) 831 if (attribute_is_deleted (mum->new_attr))
833 total++; 832 total++;
834 } 833 }
...@@ -853,7 +852,7 @@ mailbox_unix_undelete (mailbox_t mbox, size_t msgno) ...@@ -853,7 +852,7 @@ mailbox_unix_undelete (mailbox_t mbox, size_t msgno)
853 return 0; 852 return 0;
854 853
855 /* Mark undeletion */ 854 /* Mark undeletion */
856 attribute_unset_deleted (mud->messages[msgno].new_attr); 855 attribute_unset_deleted (mud->umessages[msgno].new_attr);
857 return 0; 856 return 0;
858 } 857 }
859 858
...@@ -905,6 +904,8 @@ mailbox_unix_expunge (mailbox_t mbox) ...@@ -905,6 +904,8 @@ mailbox_unix_expunge (mailbox_t mbox)
905 return ENOLCK; 904 return ENOLCK;
906 } 905 }
907 906
907 /* FIXME: send notification to all the listeners */
908
908 /* Critical section, we can not allowed signal here */ 909 /* Critical section, we can not allowed signal here */
909 /* FIXME: If NONBLOCKING is set we should unset reset to 910 /* FIXME: If NONBLOCKING is set we should unset reset to
910 * later, we can not afford to luxury here 911 * later, we can not afford to luxury here
...@@ -949,7 +950,7 @@ mailbox_unix_expunge (mailbox_t mbox) ...@@ -949,7 +950,7 @@ mailbox_unix_expunge (mailbox_t mbox)
949 /* Go to the first mail with an attribute change */ 950 /* Go to the first mail with an attribute change */
950 for (j = 0; j < mud->messages_count; j++) 951 for (j = 0; j < mud->messages_count; j++)
951 { 952 {
952 mum = &mud->messages[j]; 953 mum = &mud->umessages[j];
953 if (! attribute_is_equal (mum->old_attr, mum->new_attr)) 954 if (! attribute_is_equal (mum->old_attr, mum->new_attr))
954 break; 955 break;
955 } 956 }
...@@ -963,14 +964,14 @@ mailbox_unix_expunge (mailbox_t mbox) ...@@ -963,14 +964,14 @@ mailbox_unix_expunge (mailbox_t mbox)
963 } 964 }
964 965
965 /* set the marker position */ 966 /* set the marker position */
966 total = marker = mud->messages[j].header; 967 total = marker = mud->umessages[j].header;
967 968
968 /* copy to tempfile emails not mark changed */ 969 /* copy to tempfile emails not mark changed */
969 for (first = 1, i = j; i < mud->messages_count; i++) 970 for (first = 1, i = j; i < mud->messages_count; i++)
970 { 971 {
971 size_t len; 972 size_t len;
972 off_t current; 973 off_t current;
973 mum = &mud->messages[i]; 974 mum = &mud->umessages[i];
974 975
975 /* skip it, if mark for deletion */ 976 /* skip it, if mark for deletion */
976 if (attribute_is_deleted (mum->new_attr)) 977 if (attribute_is_deleted (mum->new_attr))
...@@ -1138,6 +1139,8 @@ mailbox_unix_expunge (mailbox_t mbox) ...@@ -1138,6 +1139,8 @@ mailbox_unix_expunge (mailbox_t mbox)
1138 clearerr (mud->file); 1139 clearerr (mud->file);
1139 fflush (mud->file); 1140 fflush (mud->file);
1140 1141
1142 /* FIXME: update the num of all the messages */
1143
1141 bailout: 1144 bailout:
1142 /* Release the locks */ 1145 /* Release the locks */
1143 if (oflags > 0) 1146 if (oflags > 0)
...@@ -1150,92 +1153,78 @@ bailout: ...@@ -1150,92 +1153,78 @@ bailout:
1150 return status; 1153 return status;
1151 } 1154 }
1152 1155
1153 /* reading */ 1156 static int
1154 static ssize_t 1157 mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
1155 mailbox_unix_get_body (mailbox_t mbox, size_t msgno, char *buffer, 1158 off_t off, ssize_t *pnread)
1156 size_t len, off_t off, int *err)
1157 { 1159 {
1158 mailbox_unix_data_t mud; 1160 mailbox_unix_message_t mum;
1161 size_t len;
1159 size_t nread = 0; 1162 size_t nread = 0;
1160 1163
1161 if (mbox == NULL || 1164 if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL)
1162 (mud = (mailbox_unix_data_t)mbox->data) == NULL) 1165 return EINVAL;
1163 {
1164 if (err)
1165 *err = EINVAL;
1166 return -1;
1167 }
1168 1166
1169 /* check if valid */ 1167 if (buffer == NULL || buflen == 0)
1170 if (len == 0 || mud == NULL || ! mailbox_unix_is_valid (mbox, msgno))
1171 { 1168 {
1172 if (err) 1169 if (pnread)
1173 *err = EINVAL; 1170 *pnread = nread;
1174 return -1; 1171 return 0;
1175 } 1172 }
1176 1173
1177 mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK); 1174 flockfile (mum->file);
1178 flockfile (mud->file);
1179 { 1175 {
1180 mailbox_unix_message_t mum = &(mud->messages[msgno]);
1181 off_t ln = mum->body_end - (mum->body + off); 1176 off_t ln = mum->body_end - (mum->body + off);
1182 if (ln > 0) 1177 if (ln > 0)
1183 { 1178 {
1184 nread = ((size_t)ln < len) ? ln : len; 1179 nread = ((size_t)ln < len) ? ln : len;
1185 /* position the file pointer and the buffer */ 1180 /* position the file pointer and the buffer */
1186 if (fseek (mud->file, mum->body + off, SEEK_SET) < 0) 1181 if (fseek (mum->file, mum->body + off, SEEK_SET) < 0)
1187 { 1182 {
1188 funlockfile (mud->file); 1183 funlockfile (mum->file);
1189 mailbox_unix_iunlock (mbox); 1184 return errno;
1190 if (err)
1191 *err = EIO;
1192 return -1;
1193 } 1185 }
1194 if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread) 1186 if (fread (buffer, sizeof (*buffer), nread, mum->file) != nread)
1195 { 1187 {
1196 funlockfile (mud->file); 1188 funlockfile (mum->file);
1197 mailbox_unix_iunlock (mbox); 1189 return errno;
1198 if (err)
1199 *err = EIO;
1200 return -1;
1201 } 1190 }
1202 } 1191 }
1203 else 1192 else
1204 nread = 0; 1193 nread = 0;
1205 } 1194 }
1206 funlockfile (mud->file); 1195 funlockfile (mum->file);
1207 mailbox_unix_iunlock (mbox);
1208 1196
1209 return nread; 1197 if (pnread)
1198 *pnread = nread;
1199 return 0;
1210 } 1200 }
1211 1201
1212 static ssize_t 1202 static int
1213 mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer, 1203 mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
1214 size_t len, off_t off, int *err) 1204 size_t len, off_t off, ssize_t *pnread)
1215 { 1205 {
1216 mailbox_unix_data_t mud; 1206 mailbox_unix_data_t mud;
1217 size_t nread = 0; 1207 size_t nread = 0;
1218 1208
1219 if (mbox == NULL || 1209 if (mbox == NULL ||
1220 (mud = (mailbox_unix_data_t)mbox->data) == NULL) 1210 (mud = (mailbox_unix_data_t)mbox->data) == NULL)
1221 { 1211 return EINVAL;
1222 if (err)
1223 *err = EINVAL;
1224 return -1;
1225 }
1226 1212
1227 /* check if valid */ 1213 /* check if valid */
1228 if (len == 0 || ! mailbox_unix_is_valid (mbox, msgno)) 1214 if (! mailbox_unix_is_valid (mbox, msgno))
1215 return EINVAL;
1216
1217 if (buffer == NULL || len == 0)
1229 { 1218 {
1230 if (err) 1219 if (pnread)
1231 *err = EINVAL; 1220 *pnread = nread;
1232 return -1; 1221 return 0;
1233 } 1222 }
1234 1223
1235 mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK); 1224 mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
1236 flockfile (mud->file); 1225 flockfile (mud->file);
1237 { 1226 {
1238 mailbox_unix_message_t mum = &(mud->messages[msgno]); 1227 mailbox_unix_message_t mum = &(mud->umessages[msgno]);
1239 off_t ln = mum->header_end - (mum->header + off); 1228 off_t ln = mum->header_end - (mum->header + off);
1240 if (ln > 0) 1229 if (ln > 0)
1241 { 1230 {
...@@ -1245,17 +1234,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer, ...@@ -1245,17 +1234,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
1245 { 1234 {
1246 funlockfile (mud->file); 1235 funlockfile (mud->file);
1247 mailbox_unix_iunlock (mbox); 1236 mailbox_unix_iunlock (mbox);
1248 if (err) 1237 return errno;
1249 *err = EIO;
1250 return -1;
1251 } 1238 }
1252 if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread) 1239 if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
1253 { 1240 {
1254 funlockfile (mud->file); 1241 funlockfile (mud->file);
1255 mailbox_unix_iunlock (mbox); 1242 mailbox_unix_iunlock (mbox);
1256 if (err) 1243 return errno;
1257 *err = EIO;
1258 return -1;
1259 } 1244 }
1260 } 1245 }
1261 else 1246 else
...@@ -1264,7 +1249,98 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer, ...@@ -1264,7 +1249,98 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
1264 funlockfile (mud->file); 1249 funlockfile (mud->file);
1265 mailbox_unix_iunlock (mbox); 1250 mailbox_unix_iunlock (mbox);
1266 1251
1267 return nread; 1252 if (pnread)
1253 *pnread = nread;
1254 return 0;
1255 }
1256
1257 static int
1258 mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
1259 {
1260 int status;
1261 ssize_t nread;
1262 char *pbuf = NULL;
1263 char *tbuf = NULL;
1264 char buf[BUFSIZ];
1265 off_t offset = 0;
1266 mailbox_unix_data_t mud;
1267 mailbox_unix_message_t mum;
1268 message_t msg;
1269 istream_t is;
1270 header_t header;
1271
1272 if (mbox == NULL || pmsg == NULL ||
1273 (mud = (mailbox_unix_data_t)mbox->data) == NULL ||
1274 mailbox_unix_is_deleted (mbox, msgno))
1275 return EINVAL;
1276
1277 mum = &(mud->umessages[msgno]);
1278
1279 /* check if we already have it */
1280 if (mum->message)
1281 {
1282 if (pmsg)
1283 *pmsg = mum->message;
1284 return 0;
1285 }
1286
1287 /* get the headers */
1288 do {
1289 status = mailbox_unix_get_header (mbox, msgno, buf, sizeof(buf),
1290 offset, &nread);
1291 if (status != 0)
1292 {
1293 free (pbuf);
1294 return status;
1295 }
1296
1297 tbuf = realloc (pbuf, offset + nread);
1298 if (tbuf == NULL)
1299 {
1300 free (pbuf);
1301 return ENOMEM;
1302 }
1303 else
1304 pbuf = tbuf;
1305 memcpy (pbuf + offset, buf, nread);
1306 offset += nread;
1307 } while (nread > 0);
1308
1309 /* get an empty message struct */
1310 status = message_init (&msg, mum);
1311 if (status != 0)
1312 {
1313 free (pbuf);
1314 return status;
1315 }
1316
1317 /* set the header */
1318 status = header_init (&header, pbuf, offset, MU_HEADER_RFC822, mum);
1319 if (status != 0)
1320 {
1321 free (pbuf);
1322 message_destroy (&msg, mum);
1323 return status;
1324 }
1325 free (pbuf);
1326 message_set_header (msg, header, mum);
1327
1328 /* prepare the istream */
1329 status = istream_init (&is, mailbox_unix_readstream, mum);
1330 if (status != 0)
1331 {
1332 free (pbuf);
1333 message_destroy (&msg, mum);
1334 return status;
1335 }
1336 message_set_istream (msg, is, mum);
1337
1338 /* set the attribute */
1339 status = message_set_attribute (msg, mum->new_attr, mum);
1340
1341 if (pmsg)
1342 *pmsg = msg;
1343 return 0;
1268 } 1344 }
1269 1345
1270 static int 1346 static int
...@@ -1274,6 +1350,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) ...@@ -1274,6 +1350,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
1274 if (mbox == NULL || msg == NULL || 1350 if (mbox == NULL || msg == NULL ||
1275 (mud = (mailbox_unix_data_t)mbox->data) == NULL) 1351 (mud = (mailbox_unix_data_t)mbox->data) == NULL)
1276 return EINVAL; 1352 return EINVAL;
1353
1354 /* simple check on the flag */
1277 if (! ((mud->flags & MU_MAILBOX_APPEND) || 1355 if (! ((mud->flags & MU_MAILBOX_APPEND) ||
1278 (mud->flags & MU_MAILBOX_RDWR) || 1356 (mud->flags & MU_MAILBOX_RDWR) ||
1279 (mud->flags & MU_MAILBOX_WRONLY))) 1357 (mud->flags & MU_MAILBOX_WRONLY)))
...@@ -1288,6 +1366,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) ...@@ -1288,6 +1366,8 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
1288 size_t nread; 1366 size_t nread;
1289 off_t off = 0; 1367 off_t off = 0;
1290 istream_t is; 1368 istream_t is;
1369 header_t hdr;
1370 int status;
1291 1371
1292 fd = fileno (mud->file); 1372 fd = fileno (mud->file);
1293 if (fstat (fd, &st) != 0) 1373 if (fstat (fd, &st) != 0)
...@@ -1302,33 +1382,32 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg) ...@@ -1302,33 +1382,32 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
1302 mailbox_unix_unlock (mbox); 1382 mailbox_unix_unlock (mbox);
1303 return errno; 1383 return errno;
1304 } 1384 }
1385
1305 /* header */ 1386 /* header */
1306 {
1307 header_t hdr;
1308 message_get_header (msg, &hdr); 1387 message_get_header (msg, &hdr);
1309 header_get_istream (hdr, &is); 1388 header_get_istream (hdr, &is);
1310 if (st.st_size != 0) 1389 if (st.st_size != 0)
1311 fputc ('\n', mud->file); 1390 fputc ('\n', mud->file);
1312 while ((nread = istream_read (is, buffer, sizeof (buffer), off)) > 0) 1391 do {
1313 { 1392 status = istream_read (is, buffer, sizeof (buffer), off, &nread);
1393 if (status != 0)
1394 return status;
1314 fwrite (buffer, sizeof (*buffer), nread, mud->file); 1395 fwrite (buffer, sizeof (*buffer), nread, mud->file);
1315 off += nread; 1396 off += nread;
1316 } 1397 } while (nread > 0);
1317 } 1398
1318 *buffer = '\0'; 1399 *buffer = '\0';
1319 /* separator */ 1400 /* separator */
1320 fputc ('\n', mud->file); 1401 fputc ('\n', mud->file);
1321 1402
1322 /* body */ 1403 /* body */
1323 {
1324 off = 0; 1404 off = 0;
1325 message_get_istream (msg, &is); 1405 message_get_istream (msg, &is);
1326 while ((nread = istream_read (is, buffer, sizeof (buffer), off)) > 0) 1406 do {
1327 { 1407 istream_read (is, buffer, sizeof (buffer), off, &nread);
1328 fwrite (buffer, sizeof (*buffer), nread, mud->file); 1408 fwrite (buffer, sizeof (*buffer), nread, mud->file);
1329 off += nread; 1409 off += nread;
1330 } 1410 } while (nread > 0);
1331 }
1332 } 1411 }
1333 fflush(mud->file); 1412 fflush(mud->file);
1334 funlockfile (mud->file); 1413 funlockfile (mud->file);
...@@ -1369,7 +1448,7 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b) ...@@ -1369,7 +1448,7 @@ mailbox_unix_get_size (mailbox_t mbox, size_t msgno, size_t *h, size_t *b)
1369 !mailbox_unix_is_valid (mbox, msgno)) 1448 !mailbox_unix_is_valid (mbox, msgno))
1370 return EINVAL; 1449 return EINVAL;
1371 1450
1372 mum = &(mud->messages[msgno]); 1451 mum = &(mud->umessages[msgno]);
1373 if (h) 1452 if (h)
1374 *h = mum->header_end - mum->header; 1453 *h = mum->header_end - mum->header;
1375 if (b) 1454 if (b)
...@@ -1393,34 +1472,6 @@ mailbox_unix_messages_count (mailbox_t mbox, size_t *count) ...@@ -1393,34 +1472,6 @@ mailbox_unix_messages_count (mailbox_t mbox, size_t *count)
1393 return 0; 1472 return 0;
1394 } 1473 }
1395 1474
1396 static int
1397 mailbox_unix_get_attribute (mailbox_t mbox, size_t msgno,
1398 attribute_t *pattribute)
1399 {
1400 mailbox_unix_data_t mud;
1401
1402 if (mbox == NULL || pattribute == NULL ||
1403 (mud = (mailbox_unix_data_t)mbox->data) == NULL ||
1404 ! mailbox_unix_is_valid (mbox, msgno))
1405 return EINVAL;
1406
1407 *pattribute = mud->messages[msgno].new_attr;
1408 return 0;
1409 }
1410
1411 static int
1412 mailbox_unix_set_attribute (mailbox_t mbox, size_t msgno,
1413 attribute_t attribute)
1414 {
1415 mailbox_unix_data_t mud;
1416 if (mbox == NULL ||
1417 (mud = (mailbox_unix_data_t)mbox->data) == NULL ||
1418 ! mailbox_unix_is_valid (mbox, msgno))
1419 return EINVAL;
1420 attribute_copy (mud->messages[msgno].new_attr, attribute);
1421 return 0;
1422 }
1423
1424 /* locking */ 1475 /* locking */
1425 static int 1476 static int
1426 mailbox_unix_lock (mailbox_t mbox, int flag) 1477 mailbox_unix_lock (mailbox_t mbox, int flag)
......
...@@ -26,8 +26,116 @@ ...@@ -26,8 +26,116 @@
26 #include <stdio.h> 26 #include <stdio.h>
27 #include <stdlib.h> 27 #include <stdlib.h>
28 28
29 static int message_read (istream_t is, char *buf, size_t buflen,
30 off_t off, ssize_t *pnread );
31 static int message_write (ostream_t os, const char *buf, size_t buflen,
32 off_t off, ssize_t *pnwrite);
33
34 int message_clone (message_t omsg, message_t *pmsg)
35 {
36 int status;
37 FILE *file;
38 message_t msg;
39 istream_t is;
40 ostream_t os;
41 header_t header;
42 char buffer[BUFSIZ];
43 char *pbuf = NULL;
44 char *tbuf = NULL;
45 off_t offset = 0;
46 size_t nread = 0;
47
48 /* retreive the header */
49 {
50 status = message_get_header (omsg, &header);
51 if (status != 0)
52 return status;
53 status = header_get_istream (header, &is);
54 if (status != 0)
55 return status;
56
57 do {
58 status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
59 if (status != 0)
60 {
61 free (pbuf);
62 return status;
63 }
64 tbuf = realloc (pbuf, offset + nread);
65 if (tbuf == NULL)
66 {
67 free (pbuf);
68 return ENOMEM;
69 }
70 else
71 pbuf = tbuf;
72 memcpy (pbuf + offset, buffer, nread);
73 offset += nread;
74 } while (nread > 0);
75
76
77 status = header_init (&header, pbuf, offset, MU_HEADER_RFC822, NULL);
78 if (status != 0)
79 {
80 free (pbuf);
81 return status;
82 }
83 free (pbuf);
84
85 }
86
87 /* retrieve the body */
88 {
89 file = tmpfile ();
90 if (file == NULL)
91 {
92 header_destroy (&header, NULL);
93 return errno;
94 }
95 offset = 0;
96 message_get_istream (omsg, &is);
97 do {
98 istream_read (is, buffer, sizeof (buffer), offset, &nread);
99 fwrite (buffer, sizeof (*buffer), nread, file);
100 offset += nread;
101 } while (nread > 0);
102 rewind (file);
103 }
104
105 /* create the message */
106 status = message_init (&msg, NULL);
107 if (status != 0)
108 return status;
109
110 /* set the header */
111 message_set_header (msg, header, NULL);
112
113 /* set the body with the streams */
114 msg->body = calloc (1, sizeof (*(msg->body)));
115 if (msg->body == NULL)
116 {
117 fclose (file);
118 message_destroy (&msg, NULL);
119 return ENOMEM;
120 }
121 status = istream_init (&is, message_read, NULL);
122 if (status != 0)
123 {
124 message_destroy (&msg, NULL);
125 return status;
126 }
127 status = ostream_init (&os, message_write, NULL);
128 if (status != 0)
129 {
130 message_destroy (&msg, NULL);
131 return status;
132 }
133 *pmsg = msg;
134 return 0;
135 }
136
29 int 137 int
30 message_init (message_t *pmsg) 138 message_init (message_t *pmsg, void *owner)
31 { 139 {
32 message_t msg; 140 message_t msg;
33 141
...@@ -36,51 +144,32 @@ message_init (message_t *pmsg) ...@@ -36,51 +144,32 @@ message_init (message_t *pmsg)
36 msg = calloc (1, sizeof (*msg)); 144 msg = calloc (1, sizeof (*msg));
37 if (msg == NULL) 145 if (msg == NULL)
38 return ENOMEM; 146 return ENOMEM;
147 msg->owner = owner;
39 *pmsg = msg; 148 *pmsg = msg;
40 return 0; 149 return 0;
41 } 150 }
42 151
43 void 152 void
44 message_destroy (message_t *pmsg) 153 message_destroy (message_t *pmsg, void *owner)
45 { 154 {
46 if (pmsg && *pmsg) 155 if (pmsg && *pmsg)
47 { 156 {
48 message_t msg = *pmsg; 157 message_t msg = *pmsg;
49 /* 158
50 * The message has a mailbox owner 159 msg->ref_count--;
51 * let the mailbox destroy when it finishes 160 if ((msg->owner && msg->owner != owner) ||
52 */ 161 (msg->owner == NULL && msg->ref_count <= 0))
53 if (msg->mailbox)
54 {
55 /* but still loose the link */
56 *pmsg = NULL;
57 return;
58 }
59 /* is the header own by us ? */
60 if (msg->header && msg->header->message == msg)
61 {
62 msg->header->message = NULL;
63 header_destroy (&(msg->header));
64 }
65 /* is the attribute own by us ? */
66 if (msg->attribute && msg->attribute->message == msg)
67 {
68 msg->attribute->message = NULL;
69 attribute_destroy (&(msg->attribute));
70 }
71 /* is the istream own by us */
72 if (msg->is && msg->is->owner == msg)
73 {
74 msg->is->owner = NULL;
75 istream_destroy (&(msg->is));
76 }
77 /* is the ostream own by us */
78 if (msg->os && msg->os->owner == msg)
79 { 162 {
80 msg->os->owner = NULL; 163 /* header */
81 ostream_destroy (&(msg->os)); 164 header_destroy (&(msg->header), owner);
82 } 165 /* attribute */
83 /* is it sometype of floating/temporary message */ 166 attribute_destroy (&(msg->attribute), owner);
167 /* istream */
168 istream_destroy (&(msg->is), owner);
169 /* ostream */
170 ostream_destroy (&(msg->os), owner);
171
172 /* if sometype of floating/temporary message */
84 if (msg->body) 173 if (msg->body)
85 { 174 {
86 body_t body = msg->body; 175 body_t body = msg->body;
...@@ -90,6 +179,7 @@ message_destroy (message_t *pmsg) ...@@ -90,6 +179,7 @@ message_destroy (message_t *pmsg)
90 free (msg->body); 179 free (msg->body);
91 } 180 }
92 free (msg); 181 free (msg);
182 }
93 /* loose the link */ 183 /* loose the link */
94 *pmsg = NULL; 184 *pmsg = NULL;
95 } 185 }
...@@ -98,115 +188,105 @@ message_destroy (message_t *pmsg) ...@@ -98,115 +188,105 @@ message_destroy (message_t *pmsg)
98 int 188 int
99 message_get_header (message_t msg, header_t *phdr) 189 message_get_header (message_t msg, header_t *phdr)
100 { 190 {
101 int err = 0;
102 int nread;
103 char *tbuf = NULL;
104 char buf[BUFSIZ];
105
106 if (phdr == NULL || msg == NULL) 191 if (phdr == NULL || msg == NULL)
107 return EINVAL; 192 return EINVAL;
108 193
109 /* header allready retrieve ? */
110 if (msg->header != NULL)
111 {
112 *phdr = msg->header; 194 *phdr = msg->header;
113 return 0; 195 return 0;
114 } 196 }
115 197
116 if (msg->mailbox == NULL) 198 int
199 message_set_header (message_t msg, header_t hdr, void *owner)
200 {
201 if (msg == NULL )
117 return EINVAL; 202 return EINVAL;
203 if (msg->owner != owner)
204 return EACCES;
205 msg->header = hdr;
206 return 0;
207 }
118 208
119 /* Ok this is where the fun begins, we have to take to account 209 int
120 * the F&$#*#^#&g O_NONBLOCKING, thanks very much to Brian and David. 210 message_get_istream (message_t msg, istream_t *pis)
121 * So POP for example is a stream protocol where the server 211 {
122 * keeps on sending the data til' the wire turn red. So when 212 if (msg == NULL || pis == NULL)
123 * we hit a bottleneck (EAGAIN, EWOULDBLOCK, EINPROGRESS, etc ..) 213 return EINVAL;
124 * we save our state and propagate the error up. Hopefully 214 *pis = msg->is;
125 * the people upstairs will do the right thing by recalling 215 return 0;
126 * us again. 216 }
127 * To resume my thoughts ... I do not like it.
128 */
129 while ((nread = mailbox_get_header (msg->mailbox,
130 msg->num, buf, sizeof(buf),
131 msg->header_offset, &err)) > 0)
132 {
133 tbuf = realloc (msg->header_buffer, msg->header_offset + nread);
134 if (tbuf == NULL)
135 {
136 free (msg->header_buffer);
137 msg->header_buffer = NULL;
138 msg->header_offset = 0;
139 return ENOMEM;
140 }
141 else
142 msg->header_buffer = tbuf;
143 memcpy (msg->header_buffer + msg->header_offset, buf, nread);
144 msg->header_offset += nread;
145 }
146 217
147 if (nread < 0) 218 int
148 { 219 message_set_istream (message_t msg, istream_t is, void *owner)
149 if (err == EAGAIN || err == EINPROGRESS || err == EWOULDBLOCK) 220 {
150 return EAGAIN; 221 if (msg == NULL)
151 free (msg->header_buffer); 222 return EINVAL;
152 msg->header_buffer = NULL; 223 if (msg->owner != owner)
153 msg->header_offset = 0; 224 return EACCES;
154 return err; 225 msg->is = is;
155 } 226 return 0;
227 }
156 228
157 err = header_init (&(msg->header), msg->header_buffer, 229 int
158 msg->header_offset, MU_HEADER_RFC822); 230 message_get_ostream (message_t msg, ostream_t *pos)
159 if (err == 0) 231 {
160 { 232 if (msg == NULL || pos == NULL)
161 /* we own it */ 233 return EINVAL;
162 msg->header->message = msg; 234 *pos = msg->os;
163 *phdr = msg->header; 235 return 0;
164 msg->header = NULL;
165 }
166 /* we can discard it */
167 free (msg->header_buffer);
168 msg->header_buffer = NULL;
169 msg->header_offset = 0;
170 return err;
171 } 236 }
172 237
173 int 238 int
174 message_set_header (message_t msg, header_t hdr) 239 message_set_ostream (message_t msg, ostream_t os, void *owner)
175 { 240 {
176 /* Can not do that on a mailbox */ 241 if (msg == NULL)
177 if (msg == NULL || msg->mailbox == NULL)
178 return EINVAL; 242 return EINVAL;
179 /* we own it ? */ 243 if (msg->owner != owner)
180 if (msg->header && msg->header->message == msg) 244 return EACCES;
181 { 245 msg->os = os;
182 msg->header->message = NULL; 246 return 0;
183 header_destroy (&(msg->header)); 247 }
184 } 248
185 msg->header = hdr; 249 int
250 message_size (message_t msg, size_t *size)
251 {
252 if (msg == NULL)
253 return EINVAL;
254 if (msg->_size)
255 return msg->_size (msg, size);
256 return ENOSYS;
257 }
258
259 int
260 message_get_attribute (message_t msg, attribute_t *pattribute)
261 {
262 if (msg == NULL || pattribute == NULL)
263 return EINVAL;
264 *pattribute = msg->attribute;
265 return 0;
266 }
267
268 int
269 message_set_attribute (message_t msg, attribute_t attribute, void *owner)
270 {
271 if (msg == NULL)
272 return EINVAL;
273 if (msg->owner != owner)
274 return EACCES;
275 msg->attribute = attribute;
186 return 0; 276 return 0;
187 } 277 }
188 278
189 static ssize_t 279 static int
190 message_read (istream_t is, char *buf, size_t buflen, off_t off) 280 message_read (istream_t is, char *buf, size_t buflen,
281 off_t off, ssize_t *pnread )
191 { 282 {
192 message_t msg = NULL; 283 message_t msg = NULL;
193 ssize_t nread = -1; 284 ssize_t nread = 0;
194 int err = 0;
195 285
196 if (is == NULL || (msg = (message_t)is->owner) == NULL) 286 if (is == NULL)
197 { 287 return EINVAL;
198 errno = EINVAL;
199 return -1;
200 }
201 288
202 /* is it own by a mailbox ? */ 289 if (msg->body)
203 if (msg->mailbox)
204 {
205 nread = mailbox_get_body (msg->mailbox, msg->num, buf,
206 buflen, off, &err);
207 errno = err;
208 }
209 else if (msg->body)
210 { 290 {
211 body_t body = msg->body; 291 body_t body = msg->body;
212 if (body->file) 292 if (body->file)
...@@ -221,8 +301,8 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off) ...@@ -221,8 +301,8 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off)
221 if (nread == 0) 301 if (nread == 0)
222 { 302 {
223 if (ferror (body->file)) 303 if (ferror (body->file))
224 nread = -1; 304 return errno;
225 /* clear the error even for feof() */ 305 /* clear the error for feof() */
226 clearerr (body->file); 306 clearerr (body->file);
227 } 307 }
228 /* errno set by fread()/fseek() ? */ 308 /* errno set by fread()/fseek() ? */
...@@ -241,54 +321,26 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off) ...@@ -241,54 +321,26 @@ message_read (istream_t is, char *buf, size_t buflen, off_t off)
241 } 321 }
242 else 322 else
243 { 323 {
244 errno = EINVAL; 324 return EINVAL;
245 nread = -1;
246 } 325 }
247 } 326 }
248 327
249 return nread; 328 if (pnread)
250 } 329 *pnread = nread;
251
252 int
253 message_get_istream (message_t msg, istream_t *pis)
254 {
255 int err;
256 if (msg == NULL || pis == NULL)
257 return EINVAL;
258 /* already done */
259 if (msg->is)
260 *pis = msg->is;
261
262 err = istream_init (&(msg->is));
263 if (err != 0)
264 return err;
265 /* tell the world this is ours */
266 msg->is->owner = msg;
267 msg->is->_read = message_read;
268 *pis = msg->is;
269 return 0; 330 return 0;
270 } 331 }
271 332
272 static int 333 static int
273 message_write (ostream_t os, const char *buf, size_t buflen, off_t off) 334 message_write (ostream_t os, const char *buf, size_t buflen,
335 off_t off, ssize_t *pnwrite)
274 { 336 {
275 message_t msg = NULL; 337 message_t msg = NULL;
276 ssize_t nwrite = -1; 338 ssize_t nwrite = 0;
277 339
278 if (os == NULL || (msg = (message_t)os->owner) == NULL) 340 if (os == NULL)
279 { 341 return EINVAL;
280 errno = EINVAL;
281 return -1;
282 }
283 342
284 /* is it own by a mailbox ? */ 343 if (msg->body)
285 if (msg->mailbox)
286 {
287 /* We can not write in a mailbox this way */
288 errno = ENOSYS;
289 return -1;
290 }
291 else if (msg->body)
292 { 344 {
293 body_t body = msg->body; 345 body_t body = msg->body;
294 if (body->file) 346 if (body->file)
...@@ -303,8 +355,8 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off) ...@@ -303,8 +355,8 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off)
303 if (nwrite == 0) 355 if (nwrite == 0)
304 { 356 {
305 if (ferror (body->file)) 357 if (ferror (body->file))
306 nwrite = -1; 358 return errno;
307 /* clear the error even for feof() */ 359 /* clear the error for feof() */
308 clearerr (body->file); 360 clearerr (body->file);
309 } 361 }
310 /* errno set by fread()/fseek() ? */ 362 /* errno set by fread()/fseek() ? */
...@@ -319,108 +371,14 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off) ...@@ -319,108 +371,14 @@ message_write (ostream_t os, const char *buf, size_t buflen, off_t off)
319 } 371 }
320 else 372 else
321 nwrite = 0; 373 nwrite = 0;
322 errno = 0;
323 } 374 }
324 else 375 else
325 { 376 {
326 errno = EINVAL;
327 nwrite = -1;
328 }
329 }
330
331 return nwrite;
332 }
333
334 int
335 message_get_ostream (message_t msg, ostream_t *pos)
336 {
337 int err;
338 if (msg == NULL || pos == NULL)
339 return EINVAL;
340 /* already done */
341 if (msg->os)
342 *pos = msg->os;
343
344 err = ostream_init (&(msg->os));
345 if (err != 0)
346 return err;
347 /* tell the world this is ours */
348 msg->os->owner = msg;
349 msg->os->_write = message_write;
350 *pos = msg->os;
351 return 0;
352 }
353
354 int
355 message_size (message_t msg, size_t *size)
356 {
357 if (msg == NULL || size == NULL)
358 return EINVAL;
359 if (msg->mailbox)
360 {
361 size_t hs, bs;
362 int status;
363 status = mailbox_get_size (msg->mailbox, msg->num, &hs, &bs);
364 if (status != 0)
365 return status;
366 *size = hs + bs;
367 return 0;
368 }
369 return ENOSYS;
370 }
371
372 int
373 message_get_attribute (message_t msg, attribute_t *pattribute)
374 {
375 int status;
376
377 if (msg == NULL || pattribute == NULL)
378 return EINVAL; 377 return EINVAL;
379
380 /* killroy was here ? */
381 if (msg->attribute)
382 *pattribute = msg->attribute;
383
384 if (msg->mailbox)
385 {
386 int status;
387 status = mailbox_get_attribute (msg->mailbox, msg->num, pattribute);
388 if (status != 0)
389 return status;
390 msg->attribute = *pattribute;
391 /* set the owner of the attribute to be us */
392 (*pattribute)->message = msg;
393 return 0;
394 } 378 }
395
396 status = attribute_init (&(msg->attribute));
397 if (status == 0)
398 {
399 /* we own this baby */
400 msg->attribute->message = msg;
401 *pattribute = msg->attribute;
402 } 379 }
403 380
404 return status; 381 if (pnwrite)
405 } 382 *pnwrite = nwrite;
406
407 int
408 message_set_attribute (message_t msg, attribute_t attribute)
409 {
410 if (msg == NULL)
411 return EINVAL;
412
413 /* own by a mailbox can no set attribute this way */
414 if (msg->mailbox)
415 return ENOSYS;
416
417 /* we own it ? */
418 if (msg->attribute && msg->attribute->message == msg)
419 {
420 /* orphan it */
421 msg->attribute->message = NULL;
422 attribute_destroy (&(msg->attribute));
423 }
424 msg->attribute = attribute;
425 return 0; 383 return 0;
426 } 384 }
......
...@@ -40,23 +40,23 @@ extern "C" { ...@@ -40,23 +40,23 @@ extern "C" {
40 struct _message; 40 struct _message;
41 typedef struct _message *message_t; 41 typedef struct _message *message_t;
42 42
43 extern int message_init __P ((message_t *)); 43 extern int message_init __P ((message_t *, void *owner));
44 extern void message_destroy __P ((message_t *)); 44 extern void message_destroy __P ((message_t *, void *owner));
45 45
46 extern int message_get_header __P ((message_t, header_t *)); 46 extern int message_get_header __P ((message_t, header_t *));
47 extern int message_set_header __P ((message_t, header_t)); 47 extern int message_set_header __P ((message_t, header_t, void *owner));
48 48
49 extern int message_get_istream __P ((message_t, istream_t *)); 49 extern int message_get_istream __P ((message_t, istream_t *));
50 extern int message_set_istream __P ((message_t, istream_t *)); 50 extern int message_set_istream __P ((message_t, istream_t, void *owner));
51 extern int message_get_ostream __P ((message_t, ostream_t *)); 51 extern int message_get_ostream __P ((message_t, ostream_t *));
52 extern int message_set_ostream __P ((message_t, ostream_t *)); 52 extern int message_set_ostream __P ((message_t, ostream_t, void *owner));
53 53
54 extern int message_is_multipart __P ((message_t)); 54 extern int message_is_multipart __P ((message_t));
55 55
56 extern int message_get_size __P ((message_t, size_t *)); 56 extern int message_get_size __P ((message_t, size_t *));
57 57
58 extern int message_get_attribute __P ((message_t, attribute_t *)); 58 extern int message_get_attribute __P ((message_t, attribute_t *));
59 extern int message_set_attribute __P ((message_t, attribute_t)); 59 extern int message_set_attribute __P ((message_t, attribute_t, void *owner));
60 60
61 extern int message_clone __P ((message_t, message_t *)); 61 extern int message_clone __P ((message_t, message_t *));
62 62
......
...@@ -42,27 +42,27 @@ typedef struct _body * body_t; ...@@ -42,27 +42,27 @@ typedef struct _body * body_t;
42 /* forward declaration */ 42 /* forward declaration */
43 struct _message 43 struct _message
44 { 44 {
45 /* whos is the owner, only mailbox can own messages */
46 mailbox_t mailbox;
47 header_t header; 45 header_t header;
48 istream_t is; 46 istream_t is;
49 ostream_t os; 47 ostream_t os;
50 body_t body; 48 body_t body;
51 size_t num;
52 attribute_t attribute; 49 attribute_t attribute;
53 char *header_buffer; 50 size_t num;
54 off_t header_offset; 51
52 /* who is the owner */
53 void *owner;
54 int ref_count;
55 55
56 int (*_get_header) __P ((message_t msg, header_t *hdr)); 56 int (*_get_header) __P ((message_t msg, header_t *hdr));
57 int (*_set_header) __P ((message_t msg, header_t hdr)); 57 int (*_set_header) __P ((message_t msg, header_t hdr, void *owner));
58 58
59 int (*_get_attribute) __P ((message_t msg, attribute_t *attr)); 59 int (*_get_attribute) __P ((message_t msg, attribute_t *attr));
60 int (*_set_attribute) __P ((message_t msg, attribute_t attr)); 60 int (*_set_attribute) __P ((message_t msg, attribute_t attr, void *owner));
61 61
62 int (*_get_istream) __P ((message_t msg, istream_t *)); 62 int (*_get_istream) __P ((message_t msg, istream_t *));
63 int (*_set_istream) __P ((message_t msg, istream_t)); 63 int (*_set_istream) __P ((message_t msg, istream_t, void *owner));
64 int (*_get_ostream) __P ((message_t msg, ostream_t *)); 64 int (*_get_ostream) __P ((message_t msg, ostream_t *));
65 int (*_set_ostream) __P ((message_t msg, ostream_t)); 65 int (*_set_ostream) __P ((message_t msg, ostream_t, void *owner));
66 66
67 int (*_size) __P ((message_t msg, size_t *size)); 67 int (*_size) __P ((message_t msg, size_t *size));
68 68
......
...@@ -37,7 +37,8 @@ static int rfc822_entry_value (header_t h, size_t num, char *buf, ...@@ -37,7 +37,8 @@ static int rfc822_entry_value (header_t h, size_t num, char *buf,
37 size_t buflen, size_t *total); 37 size_t buflen, size_t *total);
38 static int rfc822_get_istream (header_t h, istream_t *pis); 38 static int rfc822_get_istream (header_t h, istream_t *pis);
39 static int rfc822_get_ostream (header_t h, ostream_t *pos); 39 static int rfc822_get_ostream (header_t h, ostream_t *pos);
40 static ssize_t rfc822_read (istream_t is, char *buf, size_t buflen, off_t off); 40 static int rfc822_read (istream_t is, char *buf, size_t buflen,
41 off_t off, ssize_t *pnread);
41 42
42 struct _rfc822 43 struct _rfc822
43 { 44 {
...@@ -51,13 +52,14 @@ typedef struct _rfc822 * rfc822_t; ...@@ -51,13 +52,14 @@ typedef struct _rfc822 * rfc822_t;
51 52
52 53
53 int 54 int
54 rfc822_init (header_t *ph, const char *blurb, size_t len) 55 rfc822_init (header_t *ph, const char *blurb, size_t len, void *owner)
55 { 56 {
56 header_t h; 57 header_t h;
57 int status; 58 int status;
58 h = calloc (1, sizeof (*h)); 59 h = calloc (1, sizeof (*h));
59 if (h == NULL) 60 if (h == NULL)
60 return ENOMEM; 61 return ENOMEM;
62 h->owner = owner;
61 h->_init = rfc822_init; 63 h->_init = rfc822_init;
62 h->_destroy = rfc822_destroy; 64 h->_destroy = rfc822_destroy;
63 h->_parse = rfc822_parse; 65 h->_parse = rfc822_parse;
...@@ -77,29 +79,23 @@ rfc822_init (header_t *ph, const char *blurb, size_t len) ...@@ -77,29 +79,23 @@ rfc822_init (header_t *ph, const char *blurb, size_t len)
77 } 79 }
78 80
79 void 81 void
80 rfc822_destroy (header_t *ph) 82 rfc822_destroy (header_t *ph, void *owner)
81 { 83 {
82 if (ph && *ph) 84 if (ph && *ph)
83 { 85 {
84 header_t h = *ph; 86 header_t h = *ph;
85 /* own by a message */ 87
86 if (h->message) 88 /* if destroy is call always decremente */
87 { 89 h->ref_count--;
88 *ph = NULL; 90
89 return; 91 /* can we destroy ? */
90 } 92 if ((h->owner && h->owner == owner) ||
91 /* is the istream own by us */ 93 (h->owner == NULL && h->ref_count <= 0))
92 if (h->is && h->is->owner == h)
93 {
94 h->is->owner = NULL;
95 istream_destroy (&(h->is));
96 }
97 /* is the ostream own by us */
98 if (h->os && h->os->owner == h)
99 { 94 {
100 h->os->owner = NULL; 95 /* io */
101 ostream_destroy (&(h->os)); 96 istream_destroy (&(h->is), owner);
102 } 97 ostream_destroy (&(h->os), owner);
98
103 if (h->data) 99 if (h->data)
104 { 100 {
105 rfc822_t rfc = (rfc822_t)h->data; 101 rfc822_t rfc = (rfc822_t)h->data;
...@@ -108,6 +104,7 @@ rfc822_destroy (header_t *ph) ...@@ -108,6 +104,7 @@ rfc822_destroy (header_t *ph)
108 free (rfc); 104 free (rfc);
109 } 105 }
110 free (h); 106 free (h);
107 }
111 *ph = NULL; 108 *ph = NULL;
112 } 109 }
113 } 110 }
...@@ -342,8 +339,9 @@ rfc822_entry_value (header_t h, size_t num, char *buf, ...@@ -342,8 +339,9 @@ rfc822_entry_value (header_t h, size_t num, char *buf,
342 return 0; 339 return 0;
343 } 340 }
344 341
345 static ssize_t 342 static int
346 rfc822_read (istream_t is, char *buf, size_t buflen, off_t off) 343 rfc822_read (istream_t is, char *buf, size_t buflen,
344 off_t off, ssize_t *pnread)
347 { 345 {
348 header_t h; 346 header_t h;
349 rfc822_t rfc = NULL; 347 rfc822_t rfc = NULL;
...@@ -351,10 +349,7 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off) ...@@ -351,10 +349,7 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off)
351 349
352 if (is == NULL || (h = (header_t)is->owner) == NULL || 350 if (is == NULL || (h = (header_t)is->owner) == NULL ||
353 (rfc = (rfc822_t)h->data) == NULL) 351 (rfc = (rfc822_t)h->data) == NULL)
354 { 352 return EINVAL;
355 errno = EINVAL;
356 return -1;
357 }
358 353
359 len = rfc->blurb_len - off; 354 len = rfc->blurb_len - off;
360 if ((rfc->blurb_len - off) > 0) 355 if ((rfc->blurb_len - off) > 0)
...@@ -368,7 +363,9 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off) ...@@ -368,7 +363,9 @@ rfc822_read (istream_t is, char *buf, size_t buflen, off_t off)
368 else 363 else
369 len = 0; 364 len = 0;
370 365
371 return len; 366 if (pnread)
367 *pnread = len;
368 return 0;
372 } 369 }
373 370
374 int 371 int
...@@ -381,7 +378,7 @@ rfc822_get_istream (header_t h, istream_t *pis) ...@@ -381,7 +378,7 @@ rfc822_get_istream (header_t h, istream_t *pis)
381 if (h->is) 378 if (h->is)
382 *pis = h->is; 379 *pis = h->is;
383 380
384 err = istream_init (&(h->is)); 381 err = istream_init (&(h->is), rfc822_read, h->owner);
385 if (err != 0) 382 if (err != 0)
386 return err; 383 return err;
387 /* tell the world this is ours */ 384 /* tell the world this is ours */
......