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.
Showing
16 changed files
with
543 additions
and
585 deletions
... | @@ -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 */ | ... | ... |
-
Please register or sign in to post a comment