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
Showing
7 changed files
with
280 additions
and
195 deletions
... | @@ -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; | ... | ... |
-
Please register or sign in to post a comment