Commit d3e3053a d3e3053a81c71f237a7598276f2d7221b0068754 by Alain Magloire

auth.c auth.h header.h mbx_unix.c message.c message.h

 	message0.h

add flaoting message support. Corrected a bug in mailbox_unix_expunge
1 parent 95b223e7
...@@ -25,15 +25,14 @@ ...@@ -25,15 +25,14 @@
25 25
26 struct _auth 26 struct _auth
27 { 27 {
28 char *login; 28 void *owner;
29 char *passwd; 29 int (*_prologue) (auth_t);
30 uid_t owner; 30 int (*_authenticate) (auth_t);
31 gid_t group; 31 int (*_epilogue) (auth_t);
32 mode_t mode;
33 }; 32 };
34 33
35 int 34 int
36 auth_init (auth_t *pauth) 35 auth_init (auth_t *pauth, void *owner)
37 { 36 {
38 auth_t auth; 37 auth_t auth;
39 if (pauth == NULL) 38 if (pauth == NULL)
...@@ -41,140 +40,77 @@ auth_init (auth_t *pauth) ...@@ -41,140 +40,77 @@ auth_init (auth_t *pauth)
41 auth = calloc (1, sizeof (*auth)); 40 auth = calloc (1, sizeof (*auth));
42 if (auth == NULL) 41 if (auth == NULL)
43 return ENOMEM; 42 return ENOMEM;
44 auth->owner = auth->group = -1; 43 auth->owner = owner;
45 auth->mode = 0600;
46 *pauth = auth; 44 *pauth = auth;
47 return 0; 45 return 0;
48 } 46 }
49 47
50 void 48 void
51 auth_destroy (auth_t *pauth) 49 auth_destroy (auth_t *pauth, void *owner)
52 { 50 {
53 if (pauth && *pauth) 51 if (pauth && *pauth)
54 { 52 {
55 auth_t auth = *pauth; 53 auth_t auth = *pauth;
56 free (auth->login); 54 if (auth->owner == owner)
57 free (auth->passwd); 55 free (auth);
58 free (auth);
59 *pauth = NULL; 56 *pauth = NULL;
60 } 57 }
61 } 58 }
62 59
63 /* login/passwd */
64 int 60 int
65 auth_get_login (auth_t auth, char *login, size_t len, size_t *n) 61 auth_set_authenticate (auth_t auth, int (*_authenticate)(auth_t),
62 void *owner)
66 { 63 {
67 size_t nwrite = 0;
68 if (auth == NULL) 64 if (auth == NULL)
69 return EINVAL; 65 return EINVAL;
70 nwrite = _cpystr (login, auth->login, len); 66 if (auth->owner != owner)
71 if (n) 67 return EPERM;
72 *n = nwrite; 68 auth->_authenticate = _authenticate;
73 return 0; 69 return 0;
74 } 70 }
75 71
76 int 72 int
77 auth_set_login (auth_t auth, const char *login, size_t len) 73 auth_authenticate (auth_t auth)
78 { 74 {
79 char *log = NULL; 75 if (auth == NULL || auth->_authenticate == NULL)
80 if (auth == NULL)
81 return EINVAL; 76 return EINVAL;
82 if (login != NULL) 77 return auth->_authenticate (auth);
83 {
84 log = calloc (len + 1, sizeof (char));
85 if (log == NULL)
86 return ENOMEM;
87 memcpy (log, login, len);
88 }
89 free (auth->login);
90 auth->login = log;
91 return 0;
92 } 78 }
93 79
94 int 80 int
95 auth_get_passwd (auth_t auth, char *passwd, size_t len, size_t *n) 81 auth_set_epilogue (auth_t auth, int (*_epilogue)(auth_t), void *owner)
96 { 82 {
97 size_t nwrite = 0;
98 if (auth == NULL) 83 if (auth == NULL)
99 return EINVAL; 84 return EINVAL;
100 nwrite = _cpystr (passwd, auth->passwd, len); 85 if (auth->owner != owner)
101 if (n) 86 return EPERM;
102 *n = nwrite; 87 auth->_epilogue = _epilogue;
103 return 0; 88 return 0;
104 } 89 }
105 90
106 int 91 int
107 auth_set_passwd (auth_t auth, const char *passwd, size_t len) 92 auth_epilogue (auth_t auth)
108 { 93 {
109 char *pass = NULL; 94 if (auth == NULL && auth->_epilogue == NULL)
110 if (auth == NULL)
111 return EINVAL; 95 return EINVAL;
112 if (passwd != NULL) 96 return auth->_epilogue (auth);
113 {
114 char *pass = calloc (len + 1, sizeof (char));
115 if (pass == NULL)
116 return ENOMEM;
117 memcpy (pass, passwd, len);
118 }
119 free (auth->passwd);
120 auth->passwd = pass;
121 return 0;
122 } 97 }
123 98
124 /* owner and group */
125 int 99 int
126 auth_get_owner (auth_t auth, uid_t *powner) 100 auth_set_prologue (auth_t auth, int (*_prologue)(auth_t), void *owner)
127 { 101 {
128 if (auth == NULL) 102 if (auth == NULL)
129 return EINVAL; 103 return EINVAL;
130 if (powner) 104 if (auth->owner != owner)
131 *powner = auth->owner; 105 return EPERM;
132 return 0; 106 auth->_prologue = _prologue;
133 }
134
135 int
136 auth_set_owner (auth_t auth, uid_t owner)
137 {
138 if (auth == NULL)
139 return 0;
140 auth->owner = owner;
141 return 0; 107 return 0;
142 } 108 }
143 109
144 int 110 int
145 auth_get_group (auth_t auth, gid_t *pgroup) 111 auth_prologue (auth_t auth)
146 { 112 {
147 if (auth == NULL) 113 if (auth == NULL && auth->_prologue == NULL)
148 return EINVAL; 114 return EINVAL;
149 if (pgroup) 115 return auth->_prologue (auth);
150 *pgroup = auth->group;
151 return 0;
152 }
153
154 int
155 auth_set_group (auth_t auth, gid_t group)
156 {
157 if (auth == NULL)
158 return EINVAL;
159 auth->group = group;
160 return 0;
161 }
162
163 int
164 auth_get_mode (auth_t auth, mode_t *pmode)
165 {
166 if (auth == NULL)
167 return EINVAL;
168 if (pmode)
169 *pmode = auth->mode;
170 return 0;
171 }
172
173 int
174 auth_set_mode (auth_t auth, mode_t mode)
175 {
176 if (auth == NULL)
177 return EINVAL;
178 auth->mode = mode;
179 return 0;
180 } 116 }
......
...@@ -36,25 +36,23 @@ extern "C" { ...@@ -36,25 +36,23 @@ extern "C" {
36 struct _auth; 36 struct _auth;
37 typedef struct _auth *auth_t; 37 typedef struct _auth *auth_t;
38 38
39 extern int auth_init __P ((auth_t *)); 39 extern int auth_init __P ((auth_t *, void *owner));
40 extern void auth_destroy __P ((auth_t *)); 40 extern void auth_destroy __P ((auth_t *, void *owner));
41 41
42 /* login/passwd */ 42 extern int auth_prologue __P ((auth_t));
43 extern int auth_get_login __P ((auth_t, char *login, 43 extern int auth_set_prologue __P ((auth_t auth,
44 size_t len, size_t *n)); 44 int (*_prologue) __P ((auth_t)),
45 extern int auth_set_login __P ((auth_t, const char *login, size_t len)); 45 void *owner));
46 46
47 extern int auth_get_passwd __P ((auth_t, char *passwd, 47 extern int auth_authenticate __P ((auth_t));
48 size_t len, size_t *n)); 48 extern int auth_set_authenticate __P ((auth_t auth,
49 extern int auth_set_passwd __P ((auth_t, const char *passwd, size_t len)); 49 int (*_authenticate) __P ((auth_t)),
50 50 void *owner));
51 /* owner group mode*/ 51
52 extern int auth_get_owner __P ((auth_t, uid_t *uid)); 52 extern int auth_epilogue __P ((auth_t));
53 extern int auth_set_owner __P ((auth_t, uid_t uid)); 53 extern int auth_set_epilogue __P ((auth_t auth,
54 extern int auth_get_group __P ((auth_t, gid_t *gid)); 54 int (*_epilogue) __P ((auth_t)),
55 extern int auth_set_group __P ((auth_t, gid_t gid)); 55 void *owner));
56 extern int auth_get_mode __P ((auth_t, mode_t *mode));
57 extern int auth_set_mode __P ((auth_t, mode_t mode));
58 56
59 #ifdef _cpluscplus 57 #ifdef _cpluscplus
60 } 58 }
......
...@@ -81,6 +81,7 @@ extern int header_entry_value __P ((header_t, size_t num, char *buf, ...@@ -81,6 +81,7 @@ extern int header_entry_value __P ((header_t, size_t num, char *buf,
81 size_t buflen, size_t *total)); 81 size_t buflen, size_t *total));
82 extern int header_get_istream __P ((header_t, istream_t *pis)); 82 extern int header_get_istream __P ((header_t, istream_t *pis));
83 extern int header_get_ostream __P ((header_t, ostream_t *pos)); 83 extern int header_get_ostream __P ((header_t, ostream_t *pos));
84 extern int header_get_size __P ((header_t, size_t *size));
84 #ifdef _cpluscplus 85 #ifdef _cpluscplus
85 } 86 }
86 #endif 87 #endif
......
...@@ -91,6 +91,14 @@ typedef struct _mailbox_unix_message ...@@ -91,6 +91,14 @@ typedef struct _mailbox_unix_message
91 91
92 } *mailbox_unix_message_t; 92 } *mailbox_unix_message_t;
93 93
94 /*
95 * umessages is an array of pointers that contains umessages_count
96 * of mailbox_unix_message_t*; umessages[umessages_count].
97 * We do it this because realloc() can move everything to
98 * a new memory region and invalidating all the pointers someone
99 * has on the message. Thanks to <Dave Inglis> for pointing this out.
100 * messages_count is the count number of messages parsed so far.
101 */
94 typedef struct _mailbox_unix_data 102 typedef struct _mailbox_unix_data
95 { 103 {
96 mailbox_unix_message_t *umessages; 104 mailbox_unix_message_t *umessages;
...@@ -167,7 +175,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) ...@@ -167,7 +175,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
167 #define UNIX_SCHEME_LEN 5 175 #define UNIX_SCHEME_LEN 5
168 #define SEPARATOR '/' 176 #define SEPARATOR '/'
169 177
170 /* sskip the url scheme */ 178 /* skip the url scheme */
171 if (name_len > UNIX_SCHEME_LEN && 179 if (name_len > UNIX_SCHEME_LEN &&
172 (name[0] == 'u' || name[0] == 'U') && 180 (name[0] == 'u' || name[0] == 'U') &&
173 (name[1] == 'n' || name[1] == 'N') && 181 (name[1] == 'n' || name[1] == 'N') &&
...@@ -204,7 +212,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name) ...@@ -204,7 +212,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
204 /* save the basename and dirname */ 212 /* save the basename and dirname */
205 /* FIXME: We may have to support imap "SELECT" 213 /* FIXME: We may have to support imap "SELECT"
206 * So we split the name. But this should probably be 214 * So we split the name. But this should probably be
207 * supported via "maildir:" 215 * supported via "maildir:" or the mailbox mgr.
208 */ 216 */
209 /* equivalent to strrchr (name, '/'); */ 217 /* equivalent to strrchr (name, '/'); */
210 for (i = name_len, sep = NULL; i >= 0; i--) 218 for (i = name_len, sep = NULL; i >= 0; i--)
...@@ -352,12 +360,14 @@ mailbox_unix_open (mailbox_t mbox, int flags) ...@@ -352,12 +360,14 @@ mailbox_unix_open (mailbox_t mbox, int flags)
352 if (flags & MU_MAILBOX_APPEND) 360 if (flags & MU_MAILBOX_APPEND)
353 flg |= O_APPEND; 361 flg |= O_APPEND;
354 362
355 /* FIXME: does not really work, but local folders 363 /* but local folders should not block since it is local disk ??? */
356 * should not block since it is local disk ???
357 */
358 if (flags & MU_MAILBOX_NONBLOCK) 364 if (flags & MU_MAILBOX_NONBLOCK)
359 flg |= O_NONBLOCK; 365 flg |= O_NONBLOCK;
360 366
367 /* Authentication prologues */
368 if (mbox->auth)
369 auth_prologue (mbox->auth);
370
361 /* handle CREAT with care, not to follow symlinks */ 371 /* handle CREAT with care, not to follow symlinks */
362 if (flags & MU_MAILBOX_CREAT) 372 if (flags & MU_MAILBOX_CREAT)
363 { 373 {
...@@ -376,21 +386,6 @@ mailbox_unix_open (mailbox_t mbox, int flags) ...@@ -376,21 +386,6 @@ mailbox_unix_open (mailbox_t mbox, int flags)
376 if (fd < 0) 386 if (fd < 0)
377 return errno; 387 return errno;
378 } 388 }
379 /*
380 * Set the owner ship, but should we return the errno
381 */
382 if (mbox->auth)
383 {
384 auth_t auth = mbox->auth;
385 gid_t g ; uid_t u; mode_t m;
386 g = u = -1; m = 0600;
387 /* FIXME: what to do when they failed */
388 auth_get_owner (auth, &u);
389 auth_get_group (auth, &g);
390 auth_get_mode (auth, &m);
391 (void)fchown (fd, u, g);
392 (void)fchmod (fd, m);
393 }
394 } 389 }
395 mailbox_unix_unlock (mbox); 390 mailbox_unix_unlock (mbox);
396 } 391 }
...@@ -401,6 +396,29 @@ mailbox_unix_open (mailbox_t mbox, int flags) ...@@ -401,6 +396,29 @@ mailbox_unix_open (mailbox_t mbox, int flags)
401 return errno; 396 return errno;
402 } 397 }
403 398
399 /* Authentication */
400 if (mbox->auth)
401 {
402 int status = auth_authenticate (mbox->auth);
403 if (status != 0)
404 return status;
405 }
406 else
407 {
408 /*
409 * Set the owner ship, but should we return the errno
410 */
411 gid_t g ; uid_t u; mode_t m;
412 g = u = -1; m = 0600;
413 /* FIXME: what to do when they failed */
414 (void)fchown (fd, u, g);
415 (void)fchmod (fd, m);
416 }
417
418 /* Authentication epilogues */
419 if (mbox->auth)
420 auth_epilogue (mbox->auth);
421
404 /* we use FILE * object */ 422 /* we use FILE * object */
405 if (flags & MU_MAILBOX_APPEND) 423 if (flags & MU_MAILBOX_APPEND)
406 mode = "a"; 424 mode = "a";
...@@ -673,7 +691,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount) ...@@ -673,7 +691,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
673 { 691 {
674 int over = strlen (buf); 692 int over = strlen (buf);
675 mum->body_end = ftell (mud->file); 693 mum->body_end = ftell (mud->file);
676 mum->body_end -= (over + 1); 694 mum->body_end -= (over);
677 body = 0; 695 body = 0;
678 mud->messages_count++; 696 mud->messages_count++;
679 /* reset the progress_counter */ 697 /* reset the progress_counter */
...@@ -993,7 +1011,7 @@ mailbox_unix_tmpfile () ...@@ -993,7 +1011,7 @@ mailbox_unix_tmpfile ()
993 { 1011 {
994 /*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/ 1012 /*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/
995 //return tmpfile (); 1013 //return tmpfile ();
996 return fopen ("/tmp/mymail", "w+"); 1014 return fopen ("/tmp/mumail", "w+");
997 } 1015 }
998 1016
999 static int 1017 static int
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
26 #include <stdio.h> 26 #include <stdio.h>
27 #include <stdlib.h> 27 #include <stdlib.h>
28 28
29 static int body_init (body_t *pbody, void *owner);
30 static void body_destroy (body_t *pbody, void *owner);
29 static int message_read (istream_t is, char *buf, size_t buflen, 31 static int message_read (istream_t is, char *buf, size_t buflen,
30 off_t off, ssize_t *pnread ); 32 off_t off, ssize_t *pnread );
31 static int message_write (ostream_t os, const char *buf, size_t buflen, 33 static int message_write (ostream_t os, const char *buf, size_t buflen,
...@@ -35,7 +37,6 @@ int ...@@ -35,7 +37,6 @@ int
35 message_clone (message_t msg) 37 message_clone (message_t msg)
36 { 38 {
37 int status; 39 int status;
38 FILE *file;
39 istream_t is; 40 istream_t is;
40 ostream_t os; 41 ostream_t os;
41 header_t header; 42 header_t header;
...@@ -70,13 +71,7 @@ message_clone (message_t msg) ...@@ -70,13 +71,7 @@ message_clone (message_t msg)
70 return status; 71 return status;
71 72
72 do { 73 do {
73 /* FIXME: can not afford to be non blocking here 74 status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
74 * so we busy spin. VERY VERY BAD
75 */
76 do {
77 status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
78 } while (status == EAGAIN);
79
80 if (status != 0) 75 if (status != 0)
81 { 76 {
82 free (pbuf); 77 free (pbuf);
...@@ -108,13 +103,14 @@ message_clone (message_t msg) ...@@ -108,13 +103,14 @@ message_clone (message_t msg)
108 103
109 /* retrieve the body */ 104 /* retrieve the body */
110 { 105 {
111 is = msg->is; 106 status = body_init (&body, msg);
112 file = tmpfile (); 107 if (status != 0)
113 if (file == NULL)
114 { 108 {
115 header_destroy (&header, msg); 109 header_destroy (&header, msg);
116 return errno; 110 return status;
117 } 111 }
112
113 is = msg->is;
118 offset = 0; 114 offset = 0;
119 do { 115 do {
120 do 116 do
...@@ -124,34 +120,28 @@ message_clone (message_t msg) ...@@ -124,34 +120,28 @@ message_clone (message_t msg)
124 if (status != 0) 120 if (status != 0)
125 { 121 {
126 header_destroy (&header, msg); 122 header_destroy (&header, msg);
123 body_destroy (&body, msg);
127 return status; 124 return status;
128 } 125 }
129 fwrite (buffer, sizeof (*buffer), nread, file); 126 fwrite (buffer, sizeof (*buffer), nread, body->file);
130 offset += nread; 127 offset += nread;
131 } while (nread > 0); 128 } while (nread > 0);
132 rewind (file); 129 rewind (body->file);
133 } 130 }
134 131
135 /* set the body with the streams */ 132 /* set the body with the streams */
136 body = calloc (1, sizeof (*body));
137 if (body == NULL)
138 {
139 fclose (file);
140 header_destroy (&header, msg);
141 return ENOMEM;
142 }
143 status = istream_init (&is, message_read, msg); 133 status = istream_init (&is, message_read, msg);
144 if (status != 0) 134 if (status != 0)
145 { 135 {
146 fclose (file);
147 header_destroy (&header, msg); 136 header_destroy (&header, msg);
137 body_destroy (&body, msg);
148 return status; 138 return status;
149 } 139 }
150 status = ostream_init (&os, message_write, msg); 140 status = ostream_init (&os, message_write, msg);
151 if (status != 0) 141 if (status != 0)
152 { 142 {
153 fclose (file);
154 header_destroy (&header, msg); 143 header_destroy (&header, msg);
144 body_destroy (&body, msg);
155 istream_destroy (&is, msg); 145 istream_destroy (&is, msg);
156 return status; 146 return status;
157 } 147 }
...@@ -160,8 +150,8 @@ message_clone (message_t msg) ...@@ -160,8 +150,8 @@ message_clone (message_t msg)
160 status = attribute_init (&attribute, msg); 150 status = attribute_init (&attribute, msg);
161 if (status != 0) 151 if (status != 0)
162 { 152 {
163 fclose (file);
164 header_destroy (&header, msg); 153 header_destroy (&header, msg);
154 body_destroy (&body, msg);
165 istream_destroy (&is, msg); 155 istream_destroy (&is, msg);
166 ostream_destroy (&os, msg); 156 ostream_destroy (&os, msg);
167 } 157 }
...@@ -174,7 +164,7 @@ message_clone (message_t msg) ...@@ -174,7 +164,7 @@ message_clone (message_t msg)
174 msg->os = os; 164 msg->os = os;
175 msg->body = body; 165 msg->body = body;
176 msg->size = offset; 166 msg->size = offset;
177 msg->ref_count = 1; 167 msg->ref_count++;
178 msg->owner = NULL; /* orphan */ 168 msg->owner = NULL; /* orphan */
179 return 0; 169 return 0;
180 } 170 }
...@@ -200,10 +190,21 @@ message_destroy (message_t *pmsg, void *owner) ...@@ -200,10 +190,21 @@ message_destroy (message_t *pmsg, void *owner)
200 if (pmsg && *pmsg) 190 if (pmsg && *pmsg)
201 { 191 {
202 message_t msg = *pmsg; 192 message_t msg = *pmsg;
193 int destroy = 0;
203 194
195 /* always decremente */
204 msg->ref_count--; 196 msg->ref_count--;
205 if ((msg->owner && msg->owner == owner) || 197
206 (msg->owner == NULL && msg->ref_count <= 0)) 198 if (msg->owner && msg->owner == owner)
199 destroy = 1;
200
201 if (msg->owner == NULL && msg->ref_count <= 0)
202 {
203 destroy = 1;
204 owner = msg;
205 }
206
207 if (destroy)
207 { 208 {
208 header_t header = msg->header; 209 header_t header = msg->header;
209 attribute_t attribute = msg->attribute; 210 attribute_t attribute = msg->attribute;
...@@ -227,11 +228,11 @@ message_destroy (message_t *pmsg, void *owner) ...@@ -227,11 +228,11 @@ message_destroy (message_t *pmsg, void *owner)
227 { 228 {
228 if (body->file) 229 if (body->file)
229 fclose (body->file); 230 fclose (body->file);
230 free (body->content);
231 free (body); 231 free (body);
232 } 232 }
233 /* notifications are done */ 233 /* notifications are done */
234 free (msg->event); 234 free (msg->event);
235
235 /* check again for resurrection before free()ing 236 /* check again for resurrection before free()ing
236 * the memory maybe it was clone, if yes we can not 237 * the memory maybe it was clone, if yes we can not
237 * free the pointer. 238 * free the pointer.
...@@ -251,6 +252,15 @@ message_get_header (message_t msg, header_t *phdr) ...@@ -251,6 +252,15 @@ message_get_header (message_t msg, header_t *phdr)
251 if (phdr == NULL || msg == NULL) 252 if (phdr == NULL || msg == NULL)
252 return EINVAL; 253 return EINVAL;
253 254
255 /* is it a floating mesg */
256 if (msg->header == NULL && msg->owner == NULL)
257 {
258 header_t header;
259 int status = header_init (&header, NULL, 0, msg);
260 if (status != 0)
261 return status;
262 msg->header = header;
263 }
254 *phdr = msg->header; 264 *phdr = msg->header;
255 return 0; 265 return 0;
256 } 266 }
...@@ -262,6 +272,8 @@ message_set_header (message_t msg, header_t hdr, void *owner) ...@@ -262,6 +272,8 @@ message_set_header (message_t msg, header_t hdr, void *owner)
262 return EINVAL; 272 return EINVAL;
263 if (msg->owner != owner) 273 if (msg->owner != owner)
264 return EACCES; 274 return EACCES;
275 /* make sure we destoy the old if it was own by the mesg */
276 header_destroy (&(msg->header), msg);
265 msg->header = hdr; 277 msg->header = hdr;
266 return 0; 278 return 0;
267 } 279 }
...@@ -271,6 +283,39 @@ message_get_istream (message_t msg, istream_t *pis) ...@@ -271,6 +283,39 @@ message_get_istream (message_t msg, istream_t *pis)
271 { 283 {
272 if (msg == NULL || pis == NULL) 284 if (msg == NULL || pis == NULL)
273 return EINVAL; 285 return EINVAL;
286
287 /* lazy floating message body creation */
288 if (msg->is == NULL && msg->owner == NULL)
289 {
290 body_t body;
291 istream_t is;
292 ostream_t os;
293 int status;
294 status = body_init (&body, msg);
295 if (status != 0 )
296 return status;
297 status = istream_init (&is, message_read, msg);
298 if (status != 0)
299 {
300 body_destroy (&body, msg);
301 return status;
302 }
303 status = ostream_init (&os, message_write, msg);
304 if (status != 0)
305 {
306 istream_destroy (&is, msg);
307 body_destroy (&body, msg);
308 return status;
309 }
310 /* make sure we've clean */
311 istream_destroy (&(msg->is), msg);
312 ostream_destroy (&(msg->os), msg);
313 body_destroy (&(msg->body), msg);
314 msg->is = is;
315 msg->os = os;
316 msg->body = body;
317 }
318
274 *pis = msg->is; 319 *pis = msg->is;
275 return 0; 320 return 0;
276 } 321 }
...@@ -282,6 +327,8 @@ message_set_istream (message_t msg, istream_t is, void *owner) ...@@ -282,6 +327,8 @@ message_set_istream (message_t msg, istream_t is, void *owner)
282 return EINVAL; 327 return EINVAL;
283 if (msg->owner != owner) 328 if (msg->owner != owner)
284 return EACCES; 329 return EACCES;
330 /* make sure we destroy the old one if it is own by the message */
331 istream_destroy (&(msg->is), msg);
285 msg->is = is; 332 msg->is = is;
286 return 0; 333 return 0;
287 } 334 }
...@@ -291,6 +338,39 @@ message_get_ostream (message_t msg, ostream_t *pos) ...@@ -291,6 +338,39 @@ message_get_ostream (message_t msg, ostream_t *pos)
291 { 338 {
292 if (msg == NULL || pos == NULL) 339 if (msg == NULL || pos == NULL)
293 return EINVAL; 340 return EINVAL;
341
342 /* lazy floating message body creation */
343 if (msg->os == NULL && msg->owner == NULL)
344 {
345 body_t body;
346 istream_t is;
347 ostream_t os;
348 int status;
349 status = body_init (&body, msg->owner);
350 if (status != 0 )
351 return status;
352 status = istream_init (&is, message_read, msg);
353 if (status != 0)
354 {
355 body_destroy (&body, msg->owner);
356 return status;
357 }
358 status = ostream_init (&os, message_write, msg);
359 if (status != 0)
360 {
361 istream_destroy (&is, msg);
362 body_destroy (&body, msg);
363 return status;
364 }
365 /* make sure we've clean */
366 istream_destroy (&(msg->is), msg);
367 ostream_destroy (&(msg->os), msg);
368 body_destroy (&(msg->body), msg);
369 msg->is = is;
370 msg->os = os;
371 msg->body = body;
372 }
373
294 *pos = msg->os; 374 *pos = msg->os;
295 return 0; 375 return 0;
296 } 376 }
...@@ -302,6 +382,8 @@ message_set_ostream (message_t msg, ostream_t os, void *owner) ...@@ -302,6 +382,8 @@ message_set_ostream (message_t msg, ostream_t os, void *owner)
302 return EINVAL; 382 return EINVAL;
303 if (msg->owner != owner) 383 if (msg->owner != owner)
304 return EACCES; 384 return EACCES;
385 /* make sure we destroy the old one if it is own by the message */
386 ostream_destroy (&(msg->os), msg);
305 msg->os = os; 387 msg->os = os;
306 return 0; 388 return 0;
307 } 389 }
...@@ -332,6 +414,14 @@ message_get_attribute (message_t msg, attribute_t *pattribute) ...@@ -332,6 +414,14 @@ message_get_attribute (message_t msg, attribute_t *pattribute)
332 { 414 {
333 if (msg == NULL || pattribute == NULL) 415 if (msg == NULL || pattribute == NULL)
334 return EINVAL; 416 return EINVAL;
417 if (msg->attribute == NULL && msg->owner == NULL)
418 {
419 attribute_t attribute;
420 int status = attribute_init (&attribute, msg);
421 if (status != 0)
422 return status;
423 msg->attribute = attribute;
424 }
335 *pattribute = msg->attribute; 425 *pattribute = msg->attribute;
336 return 0; 426 return 0;
337 } 427 }
...@@ -343,6 +433,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) ...@@ -343,6 +433,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
343 return EINVAL; 433 return EINVAL;
344 if (msg->owner != owner) 434 if (msg->owner != owner)
345 return EACCES; 435 return EACCES;
436 attribute_destroy (&(msg->attribute), msg);
346 msg->attribute = attribute; 437 msg->attribute = attribute;
347 return 0; 438 return 0;
348 } 439 }
...@@ -414,6 +505,61 @@ message_notification (message_t msg, size_t type) ...@@ -414,6 +505,61 @@ message_notification (message_t msg, size_t type)
414 } 505 }
415 } 506 }
416 507
508 /* We use the notion of body_t here */
509 static int
510 body_init (body_t *pbody, void *owner)
511 {
512 body_t body;
513 FILE *file;
514
515 if (pbody == NULL)
516 return EINVAL;
517
518 #ifdef HAVE_MKSTEMP
519 {
520 char tmpbuf[L_tmpnam + 1];
521 int fd;
522
523 if (tmpnam (tmpbuf) == NULL ||
524 (fd = mkstemp (tmpbuf)) == -1 ||
525 (file = fdopen(fd, "w+")) == NULL)
526 return errno;
527 (void)remove(tmpbuf);
528 }
529 #else
530 file = tmpfile ();
531 if (file == NULL)
532 return errno;
533 #endif
534
535 /* set the body with the streams */
536 body = calloc (1, sizeof (*body));
537 if (body == NULL)
538 {
539 fclose (file);
540 return ENOMEM;
541 }
542 body->file = file;
543 body->owner = owner;
544 *pbody = body;
545 return 0;
546 }
547
548 static void
549 body_destroy (body_t *pbody, void *owner)
550 {
551 if (pbody && *pbody)
552 {
553 body_t body = *pbody;
554 if (body->owner == owner)
555 {
556 if (body->file)
557 fclose (body->file);
558 }
559 *pbody = NULL;
560 }
561 }
562
417 static int 563 static int
418 message_read (istream_t is, char *buf, size_t buflen, 564 message_read (istream_t is, char *buf, size_t buflen,
419 off_t off, ssize_t *pnread ) 565 off_t off, ssize_t *pnread )
...@@ -445,22 +591,8 @@ message_read (istream_t is, char *buf, size_t buflen, ...@@ -445,22 +591,8 @@ message_read (istream_t is, char *buf, size_t buflen,
445 } 591 }
446 /* errno set by fread()/fseek() ? */ 592 /* errno set by fread()/fseek() ? */
447 } 593 }
448 else if (body->content)
449 {
450 off_t ln = body->content_len - off;
451 if (ln > 0)
452 {
453 nread = ((size_t)ln < buflen) ? ln : buflen;
454 memcpy (buf, body->content + off, nread);
455 }
456 else
457 nread = 0;
458 errno = 0;
459 }
460 else 594 else
461 { 595 return EINVAL;
462 return EINVAL;
463 }
464 } 596 }
465 597
466 if (pnread) 598 if (pnread)
...@@ -499,21 +631,8 @@ message_write (ostream_t os, const char *buf, size_t buflen, ...@@ -499,21 +631,8 @@ message_write (ostream_t os, const char *buf, size_t buflen,
499 } 631 }
500 /* errno set by fread()/fseek() ? */ 632 /* errno set by fread()/fseek() ? */
501 } 633 }
502 else if (body->content)
503 {
504 off_t ln = body->content_len - off;
505 if (ln > 0)
506 {
507 nwrite = ((size_t)ln < buflen) ? ln : buflen;
508 memcpy (body->content + off, buf, nwrite);
509 }
510 else
511 nwrite = 0;
512 }
513 else 634 else
514 { 635 return EINVAL;
515 return EINVAL;
516 }
517 } 636 }
518 637
519 if (pnwrite) 638 if (pnwrite)
......
...@@ -40,6 +40,14 @@ extern "C" { ...@@ -40,6 +40,14 @@ extern "C" {
40 struct _message; 40 struct _message;
41 typedef struct _message *message_t; 41 typedef struct _message *message_t;
42 42
43 /* A message is considered to be a container for:
44 * header_t, body_t, and its attribute_t.
45 * The notion of body_t is not visible/exported, since
46 * they are alway tied to a floating message, there was no
47 * need to create yet another object, getting the {i,o}stream_t
48 * was enough.
49 */
50
43 extern int message_init __P ((message_t *, void *owner)); 51 extern int message_init __P ((message_t *, void *owner));
44 extern void message_destroy __P ((message_t *, void *owner)); 52 extern void message_destroy __P ((message_t *, void *owner));
45 53
......
...@@ -39,11 +39,16 @@ extern "C" { ...@@ -39,11 +39,16 @@ extern "C" {
39 # endif 39 # endif
40 #endif /*__P */ 40 #endif /*__P */
41 41
42 /* The notion of body_t is not exported outside,
43 * there was no need for yet another object.
44 * since only floating messages need them. The functions
45 * that manipulate those objects are static to message.c
46 *
47 */
42 struct _body 48 struct _body
43 { 49 {
44 FILE *file; 50 FILE *file;
45 char *content; 51 void *owner;
46 size_t content_len;
47 }; 52 };
48 53
49 typedef struct _body * body_t; 54 typedef struct _body * body_t;
......