Commit 6c977a77 6c977a773bc4884d9651b7ae4908a968242a555f by Alain Magloire

* mailbox2/include/mailutils/mbox.h: New prototypes.

	* mailbox2/include/mailutils/sys/mbox.h: New prototypes.
	* mailbox2/mbox/*.c: Finish implementation.
	* mailbox2/attribute.c: Add user flags.
	* mailbox2/dattribute.c: Add user flags.

	To be compatible with the old mailbox, all stream read
	and write take an offset. Removed stream_seek () and add
	stream_is_seekable() instead.
	* mailbox2/stream.c: Likewised.
	* mailbox2/bstream.c: Likewised.
	* mailbox2/fdstream.c: Likewised.
	* mailbox2/fstream.c: Likewised.
	* mailbox2/mapstream.c: Likewised.
	* mailbox2/memstream.c: Likewised.
	* mailbox2/tcpstream.c: Likewised.

	* mailbox2/include/mailutils/error.h: Add EBADFD.
1 parent b7a718c6
Showing 71 changed files with 1373 additions and 631 deletions
...@@ -81,6 +81,42 @@ attribute_clear_flags (attribute_t attribute) ...@@ -81,6 +81,42 @@ attribute_clear_flags (attribute_t attribute)
81 return attribute->vtable->clear_flags (attribute); 81 return attribute->vtable->clear_flags (attribute);
82 } 82 }
83 83
84 int
85 attribute_get_userflags (attribute_t attribute, int *puserflags)
86 {
87 if (attribute == NULL || attribute->vtable == NULL
88 || attribute->vtable->get_userflags == NULL)
89 return MU_ERROR_NOT_SUPPORTED;
90 return attribute->vtable->get_userflags (attribute, puserflags);
91 }
92
93 int
94 attribute_set_userflags (attribute_t attribute, int userflags)
95 {
96 if (attribute == NULL || attribute->vtable == NULL
97 || attribute->vtable->set_userflags == NULL)
98 return MU_ERROR_NOT_SUPPORTED;
99 return attribute->vtable->set_userflags (attribute, userflags);
100 }
101
102 int
103 attribute_unset_userflags (attribute_t attribute, int userflags)
104 {
105 if (attribute == NULL || attribute->vtable == NULL
106 || attribute->vtable->unset_userflags == NULL)
107 return MU_ERROR_NOT_SUPPORTED;
108 return attribute->vtable->unset_userflags (attribute, userflags);
109 }
110
111 int
112 attribute_clear_userflags (attribute_t attribute)
113 {
114 if (attribute == NULL || attribute->vtable == NULL
115 || attribute->vtable->clear_userflags == NULL)
116 return MU_ERROR_NOT_SUPPORTED;
117 return attribute->vtable->clear_userflags (attribute);
118 }
119
84 120
85 /* Stub helpers for the wellknown flags. */ 121 /* Stub helpers for the wellknown flags. */
86 int 122 int
...@@ -149,6 +185,16 @@ attribute_set_modified (attribute_t attribute) ...@@ -149,6 +185,16 @@ attribute_set_modified (attribute_t attribute)
149 } 185 }
150 186
151 int 187 int
188 attribute_is_userflags (attribute_t attribute, int userflag)
189 {
190 int flags = 0;
191 if (attribute == NULL)
192 return 0;
193 attribute_get_userflags (attribute, &flags);
194 return flags & userflag;
195 }
196
197 int
152 attribute_is_seen (attribute_t attribute) 198 attribute_is_seen (attribute_t attribute)
153 { 199 {
154 int flags = 0; 200 int flags = 0;
......
...@@ -44,19 +44,20 @@ _stream_buffer_cleanup (void *arg) ...@@ -44,19 +44,20 @@ _stream_buffer_cleanup (void *arg)
44 } 44 }
45 45
46 static int 46 static int
47 refill (struct _stream_buffer *bs) 47 refill (struct _stream_buffer *bs, off_t offset)
48 { 48 {
49 int status; 49 int status;
50 if (bs->rbuffer.base == NULL) 50 if (bs->rbuffer.base == NULL)
51 { 51 {
52 bs->rbuffer.base = calloc (1, bs->rbuffer.bufsize); 52 bs->rbuffer.base = calloc (1, bs->rbuffer.bufsize);
53 if (bs->rbuffer.base == NULL) 53 if (bs->rbuffer.base == NULL)
54 return ENOMEM; 54 return MU_ERROR_NO_MEMORY;
55 } 55 }
56 bs->rbuffer.ptr = bs->rbuffer.base; 56 bs->rbuffer.ptr = bs->rbuffer.base;
57 bs->rbuffer.count = 0; 57 bs->rbuffer.count = 0;
58 bs->rbuffer.offset = offset;
58 status = stream_read (bs->stream, bs->rbuffer.ptr, bs->rbuffer.bufsize, 59 status = stream_read (bs->stream, bs->rbuffer.ptr, bs->rbuffer.bufsize,
59 (size_t *)&(bs->rbuffer.count)); 60 offset, (size_t *)&(bs->rbuffer.count));
60 return status; 61 return status;
61 } 62 }
62 63
...@@ -107,7 +108,8 @@ _stream_buffer_close (stream_t stream) ...@@ -107,7 +108,8 @@ _stream_buffer_close (stream_t stream)
107 networking. Lots of code between POP and IMAP can be share this way. 108 networking. Lots of code between POP and IMAP can be share this way.
108 The buffering is on the read only, the writes fall through. */ 109 The buffering is on the read only, the writes fall through. */
109 int 110 int
110 _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) 111 _stream_buffer_read (stream_t stream, void *buf, size_t count, off_t offset,
112 size_t *pnread)
111 { 113 {
112 int status = 0; 114 int status = 0;
113 struct _stream_buffer *bs = (struct _stream_buffer *)stream; 115 struct _stream_buffer *bs = (struct _stream_buffer *)stream;
...@@ -121,8 +123,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) ...@@ -121,8 +123,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
121 else if (bs->rbuffer.bufsize == 0) 123 else if (bs->rbuffer.bufsize == 0)
122 { 124 {
123 /* If rbuffer.bufsize == 0. It means they did not want the buffer 125 /* If rbuffer.bufsize == 0. It means they did not want the buffer
124 mechanism, then what are we doing here? */ 126 mechanism, ... what are we doing here? */
125 status = stream_read (bs->stream, buf, count, pnread); 127 status = stream_read (bs->stream, buf, count, offset, pnread);
126 } 128 }
127 else 129 else
128 { 130 {
...@@ -139,14 +141,17 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) ...@@ -139,14 +141,17 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
139 { 141 {
140 r = 0; 142 r = 0;
141 /* Drain our buffer first. */ 143 /* Drain our buffer first. */
142 if (bs->rbuffer.count > 0) 144 if (bs->rbuffer.count > 0 && offset == bs->rbuffer.offset)
143 { 145 {
144 memcpy(p, bs->rbuffer.ptr, bs->rbuffer.count); 146 memcpy(p, bs->rbuffer.ptr, bs->rbuffer.count);
147 bs->rbuffer.offset += bs->rbuffer.count;
145 residue -= bs->rbuffer.count; 148 residue -= bs->rbuffer.count;
146 p += bs->rbuffer.count; 149 p += bs->rbuffer.count;
150 offset += bs->rbuffer.count;
147 } 151 }
148 bs->rbuffer.count = 0; /* Signal we will need to refill. */ 152 bs->rbuffer.count = 0; /* Signal we will need to refill. */
149 status = stream_read (bs->stream, p, residue, &r); 153 status = stream_read (bs->stream, p, residue, offset, &r);
154 bs->rbuffer.offset += r;
150 residue -= r; 155 residue -= r;
151 if (pnread) 156 if (pnread)
152 *pnread = count - residue; 157 *pnread = count - residue;
...@@ -164,20 +169,22 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) ...@@ -164,20 +169,22 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
164 { 169 {
165 (void)memcpy (p, bs->rbuffer.ptr, (size_t)r); 170 (void)memcpy (p, bs->rbuffer.ptr, (size_t)r);
166 bs->rbuffer.ptr += r; 171 bs->rbuffer.ptr += r;
172 bs->rbuffer.offset += r;
167 /* bs->rbuffer.count = 0 ... done in refill */ 173 /* bs->rbuffer.count = 0 ... done in refill */
168 p += r; 174 p += r;
169 residue -= r; 175 residue -= r;
170 status = refill (bs); 176 status = refill (bs, bs->rbuffer.offset);
171 /* Did we reach the end. */ 177 /* Did we reach the end. */
172 if (status != 0 || bs->rbuffer.count == 0) 178 if (status != 0 || bs->rbuffer.count == 0)
173 { 179 {
174 /* We have something in the buffer return the error on the 180 /* We have something in the buffer return the error on the
175 next call . */ 181 next call. */
176 if (count != residue) 182 if (count != residue)
177 status = 0; 183 status = 0;
178 if (pnread) 184 if (pnread)
179 *pnread = count - residue; 185 *pnread = count - residue;
180 done = 1; 186 done = 1;
187 break;
181 } 188 }
182 } 189 }
183 if (!done) 190 if (!done)
...@@ -185,6 +192,7 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) ...@@ -185,6 +192,7 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
185 memcpy(p, bs->rbuffer.ptr, residue); 192 memcpy(p, bs->rbuffer.ptr, residue);
186 bs->rbuffer.count -= residue; 193 bs->rbuffer.count -= residue;
187 bs->rbuffer.ptr += residue; 194 bs->rbuffer.ptr += residue;
195 bs->rbuffer.offset += residue;
188 if (pnread) 196 if (pnread)
189 *pnread = count; 197 *pnread = count;
190 } 198 }
...@@ -200,7 +208,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread) ...@@ -200,7 +208,8 @@ _stream_buffer_read (stream_t stream, void *buf, size_t count, size_t *pnread)
200 * Stop when a newline has been read, or the count runs out. 208 * Stop when a newline has been read, or the count runs out.
201 */ 209 */
202 int 210 int
203 _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnread) 211 _stream_buffer_readline (stream_t stream, char *buf, size_t count,
212 off_t offset, size_t *pnread)
204 { 213 {
205 int status = 0; 214 int status = 0;
206 struct _stream_buffer *bs = (struct _stream_buffer *)stream; 215 struct _stream_buffer *bs = (struct _stream_buffer *)stream;
...@@ -214,7 +223,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea ...@@ -214,7 +223,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
214 else if (bs->rbuffer.bufsize == 0) 223 else if (bs->rbuffer.bufsize == 0)
215 { 224 {
216 /* Use the provided readline. */ 225 /* Use the provided readline. */
217 status = stream_readline (bs->stream, buf, count, pnread); 226 status = stream_readline (bs->stream, buf, count, offset, pnread);
218 } 227 }
219 else /* Buffered. */ 228 else /* Buffered. */
220 { 229 {
...@@ -234,7 +243,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea ...@@ -234,7 +243,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
234 len = bs->rbuffer.count; 243 len = bs->rbuffer.count;
235 if (len <= 0) 244 if (len <= 0)
236 { 245 {
237 status = refill (bs); 246 status = refill (bs, offset);
238 if (status != 0 || bs->rbuffer.count == 0) 247 if (status != 0 || bs->rbuffer.count == 0)
239 { 248 {
240 break; 249 break;
...@@ -255,6 +264,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea ...@@ -255,6 +264,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
255 len = ++nl - p; 264 len = ++nl - p;
256 bs->rbuffer.count -= len; 265 bs->rbuffer.count -= len;
257 bs->rbuffer.ptr = nl; 266 bs->rbuffer.ptr = nl;
267 bs->rbuffer.offset += len;
258 memcpy (s, p, len); 268 memcpy (s, p, len);
259 total += len; 269 total += len;
260 s += len; 270 s += len;
...@@ -262,6 +272,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea ...@@ -262,6 +272,7 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
262 } 272 }
263 bs->rbuffer.count -= len; 273 bs->rbuffer.count -= len;
264 bs->rbuffer.ptr += len; 274 bs->rbuffer.ptr += len;
275 bs->rbuffer.offset += len;
265 memcpy(s, p, len); 276 memcpy(s, p, len);
266 total += len; 277 total += len;
267 s += len; 278 s += len;
...@@ -279,10 +290,10 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea ...@@ -279,10 +290,10 @@ _stream_buffer_readline (stream_t stream, char *buf, size_t count, size_t *pnrea
279 290
280 int 291 int
281 _stream_buffer_write (stream_t stream, const void *buf, size_t count, 292 _stream_buffer_write (stream_t stream, const void *buf, size_t count,
282 size_t *pnwrite) 293 off_t offset, size_t *pnwrite)
283 { 294 {
284 struct _stream_buffer *bs = (struct _stream_buffer *)stream; 295 struct _stream_buffer *bs = (struct _stream_buffer *)stream;
285 return stream_write (bs->stream, buf, count, pnwrite); 296 return stream_write (bs->stream, buf, count, offset, pnwrite);
286 } 297 }
287 298
288 int 299 int
...@@ -328,10 +339,10 @@ _stream_buffer_get_state (stream_t stream, enum stream_state *pstate) ...@@ -328,10 +339,10 @@ _stream_buffer_get_state (stream_t stream, enum stream_state *pstate)
328 } 339 }
329 340
330 int 341 int
331 _stream_buffer_seek (stream_t stream, off_t off, enum stream_whence whence) 342 _stream_buffer_is_seekable (stream_t stream)
332 { 343 {
333 struct _stream_buffer *bs = (struct _stream_buffer *)stream; 344 struct _stream_buffer *bs = (struct _stream_buffer *)stream;
334 return stream_seek (bs->stream, off, whence); 345 return stream_is_seekable (bs->stream);
335 } 346 }
336 347
337 int 348 int
...@@ -390,7 +401,6 @@ static struct _stream_vtable _stream_buffer_vtable = ...@@ -390,7 +401,6 @@ static struct _stream_vtable _stream_buffer_vtable =
390 _stream_buffer_readline, 401 _stream_buffer_readline,
391 _stream_buffer_write, 402 _stream_buffer_write,
392 403
393 _stream_buffer_seek,
394 _stream_buffer_tell, 404 _stream_buffer_tell,
395 405
396 _stream_buffer_get_size, 406 _stream_buffer_get_size,
...@@ -401,6 +411,7 @@ static struct _stream_vtable _stream_buffer_vtable = ...@@ -401,6 +411,7 @@ static struct _stream_vtable _stream_buffer_vtable =
401 _stream_buffer_get_flags, 411 _stream_buffer_get_flags,
402 _stream_buffer_get_state, 412 _stream_buffer_get_state,
403 413
414 _stream_buffer_is_seekable,
404 _stream_buffer_is_readready, 415 _stream_buffer_is_readready,
405 _stream_buffer_is_writeready, 416 _stream_buffer_is_writeready,
406 _stream_buffer_is_exceptionpending, 417 _stream_buffer_is_exceptionpending,
...@@ -423,10 +434,14 @@ _stream_buffer_ctor (struct _stream_buffer *bs, stream_t stream, ...@@ -423,10 +434,14 @@ _stream_buffer_ctor (struct _stream_buffer *bs, stream_t stream,
423 } 434 }
424 435
425 void 436 void
426 _stream_buffer_dtor (struct _stream_buffer *bs) 437 _stream_buffer_dtor (stream_t stream)
427 { 438 {
439 struct _stream_buffer *bs = (struct _stream_buffer *)stream;
440 if (bs)
441 {
428 stream_destroy (&bs->stream); 442 stream_destroy (&bs->stream);
429 mu_refcount_destroy (&bs->refcount); 443 mu_refcount_destroy (&bs->refcount);
444 }
430 } 445 }
431 446
432 int 447 int
......
...@@ -92,6 +92,50 @@ _attribute_default_clear_flags (attribute_t attribute) ...@@ -92,6 +92,50 @@ _attribute_default_clear_flags (attribute_t attribute)
92 return 0; 92 return 0;
93 } 93 }
94 94
95 int
96 _attribute_default_get_userflags (attribute_t attribute, int *puserflags)
97 {
98 struct _attribute_default *da = (struct _attribute_default *)attribute;
99 mu_refcount_lock (da->refcount);
100 if (puserflags)
101 *puserflags = da->userflags;
102 mu_refcount_unlock (da->refcount);
103 return 0;
104 }
105
106 int
107 _attribute_default_set_userflags (attribute_t attribute, int userflags)
108 {
109 struct _attribute_default *da = (struct _attribute_default *)attribute;
110 mu_refcount_lock (da->refcount);
111 da->userflags |= (userflags | MU_ATTRIBUTE_MODIFIED);
112 mu_refcount_unlock (da->refcount);
113 return 0;
114 }
115
116 int
117 _attribute_default_unset_userflags (attribute_t attribute, int userflags)
118 {
119 struct _attribute_default *da = (struct _attribute_default *)attribute;
120 mu_refcount_lock (da->refcount);
121 da->userflags &= ~userflags;
122 /* If Modified was being unset do not reset it. */
123 if (!(userflags & MU_ATTRIBUTE_MODIFIED))
124 da->userflags |= MU_ATTRIBUTE_MODIFIED;
125 mu_refcount_unlock (da->refcount);
126 return 0;
127 }
128
129 int
130 _attribute_default_clear_userflags (attribute_t attribute)
131 {
132 struct _attribute_default *da = (struct _attribute_default *)attribute;
133 mu_refcount_lock (da->refcount);
134 da->userflags = 0;
135 mu_refcount_unlock (da->refcount);
136 return 0;
137 }
138
95 static struct _attribute_vtable _attribute_default_vtable = 139 static struct _attribute_vtable _attribute_default_vtable =
96 { 140 {
97 _attribute_default_ref, 141 _attribute_default_ref,
...@@ -100,7 +144,12 @@ static struct _attribute_vtable _attribute_default_vtable = ...@@ -100,7 +144,12 @@ static struct _attribute_vtable _attribute_default_vtable =
100 _attribute_default_get_flags, 144 _attribute_default_get_flags,
101 _attribute_default_set_flags, 145 _attribute_default_set_flags,
102 _attribute_default_unset_flags, 146 _attribute_default_unset_flags,
103 _attribute_default_clear_flags 147 _attribute_default_clear_flags,
148
149 _attribute_default_get_userflags,
150 _attribute_default_set_userflags,
151 _attribute_default_unset_userflags,
152 _attribute_default_clear_userflags
104 }; 153 };
105 154
106 int 155 int
...@@ -115,8 +164,10 @@ _attribute_default_ctor (struct _attribute_default *da) ...@@ -115,8 +164,10 @@ _attribute_default_ctor (struct _attribute_default *da)
115 } 164 }
116 165
117 void 166 void
118 _attribute_default_dtor (struct _attribute_default *da) 167 _attribute_default_dtor (attribute_t attribute)
119 { 168 {
169 struct _attribute_default *da = (struct _attribute_default *)attribute;
170 if (da)
120 mu_refcount_destroy (&da->refcount); 171 mu_refcount_destroy (&da->refcount);
121 } 172 }
122 173
...@@ -173,22 +224,36 @@ attribute_status_create (attribute_t *pattribute, const char *field) ...@@ -173,22 +224,36 @@ attribute_status_create (attribute_t *pattribute, const char *field)
173 { 224 {
174 switch (*field) 225 switch (*field)
175 { 226 {
176 case 'r':
177 case 'R':
178 attribute_set_read (*pattribute);
179 break;
180 case 'O': 227 case 'O':
181 case 'o': 228 case 'o':
182 attribute_set_seen (*pattribute); 229 attribute_set_seen (*pattribute);
183 break; 230 break;
231
232 case 'r':
233 case 'R':
234 attribute_set_read (*pattribute);
235 break;
236
184 case 'a': 237 case 'a':
185 case 'A': 238 case 'A':
186 attribute_set_answered (*pattribute); 239 attribute_set_answered (*pattribute);
187 break; 240 break;
241
188 case 'd': 242 case 'd':
189 case 'D': 243 case 'D':
190 attribute_set_deleted (*pattribute); 244 attribute_set_deleted (*pattribute);
191 break; 245 break;
246
247 case 't':
248 case 'T':
249 attribute_set_draft (*pattribute);
250 break;
251
252 case 'f':
253 case 'F':
254 attribute_set_flagged (*pattribute);
255 break;
256
192 } 257 }
193 } 258 }
194 attribute_unset_modified (*pattribute); 259 attribute_unset_modified (*pattribute);
......
...@@ -242,11 +242,15 @@ _lockfile_dotlock_ctor (struct _lockfile_dotlock *dotlock, ...@@ -242,11 +242,15 @@ _lockfile_dotlock_ctor (struct _lockfile_dotlock *dotlock,
242 } 242 }
243 243
244 void 244 void
245 _lockfile_dotlock_dtor (struct _lockfile_dotlock *dotlock) 245 _lockfile_dotlock_dtor (lockfile_t lockfile)
246 { 246 {
247 struct _lockfile_dotlock *dotlock = (struct _lockfile_dotlock *)lockfile;
248 if (dotlock)
249 {
247 mu_refcount_destroy (&dotlock->refcount); 250 mu_refcount_destroy (&dotlock->refcount);
248 if (dotlock->fname) 251 if (dotlock->fname)
249 free (dotlock->fname); 252 free (dotlock->fname);
253 }
250 } 254 }
251 255
252 int 256 int
......
...@@ -93,7 +93,7 @@ _stream_fd_get_fd (stream_t stream, int *fd) ...@@ -93,7 +93,7 @@ _stream_fd_get_fd (stream_t stream, int *fd)
93 { 93 {
94 struct _stream_fd *fds = (struct _stream_fd *)stream; 94 struct _stream_fd *fds = (struct _stream_fd *)stream;
95 95
96 if (fd == NULL || fds->fd == -1) 96 if (fd == NULL)
97 return MU_ERROR_INVALID_PARAMETER; 97 return MU_ERROR_INVALID_PARAMETER;
98 98
99 *fd = fds->fd; 99 *fd = fds->fd;
...@@ -101,26 +101,44 @@ _stream_fd_get_fd (stream_t stream, int *fd) ...@@ -101,26 +101,44 @@ _stream_fd_get_fd (stream_t stream, int *fd)
101 } 101 }
102 102
103 int 103 int
104 _stream_fd_read (stream_t stream, void *buf, size_t buf_size, size_t *br) 104 _stream_fd_read (stream_t stream, void *buf, size_t buf_size, off_t offset,
105 size_t *br)
105 { 106 {
106 struct _stream_fd *fds = (struct _stream_fd *)stream; 107 struct _stream_fd *fds = (struct _stream_fd *)stream;
107 int bytes = 0; 108 int bytes = 0;
108 int status = 0; 109 int status = 0;
109 110
111 if (fds->fd < 0)
112 {
113 if (br)
114 *br = 0;
115 return MU_ERROR_BAD_FILE_DESCRIPTOR;
116 }
117
110 fds->state = MU_STREAM_STATE_READ; 118 fds->state = MU_STREAM_STATE_READ;
119 if (fds->offset != offset)
120 {
121 lseek (fds->fd, offset, SEEK_SET);
122 fds->offset = offset;
123 }
124
111 bytes = read (fds->fd, buf, buf_size); 125 bytes = read (fds->fd, buf, buf_size);
112 if (bytes == -1) 126 if (bytes == -1)
113 { 127 {
114 bytes = 0; 128 bytes = 0;
115 status = errno; 129 status = errno;
116 } 130 }
131 else
132 fds->offset += bytes;
133
117 if (br) 134 if (br)
118 *br = bytes; 135 *br = bytes;
119 return status; 136 return status;
120 } 137 }
121 138
122 int 139 int
123 _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br) 140 _stream_fd_readline (stream_t stream, char *buf, size_t buflen,
141 off_t offset, size_t *br)
124 { 142 {
125 struct _stream_fd *fds = (struct _stream_fd *)stream; 143 struct _stream_fd *fds = (struct _stream_fd *)stream;
126 int status = 0; 144 int status = 0;
...@@ -128,9 +146,22 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br) ...@@ -128,9 +146,22 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
128 int nr = 0; 146 int nr = 0;
129 char c; 147 char c;
130 148
149 if (fds->fd < 0)
150 {
151 if (br)
152 *br = 0;
153 return MU_ERROR_BAD_FILE_DESCRIPTOR;
154 }
155
131 fds->state = MU_STREAM_STATE_READ; 156 fds->state = MU_STREAM_STATE_READ;
157 if (fds->offset != offset)
158 {
159 lseek (fds->fd, offset, SEEK_SET);
160 fds->offset = offset;
161 }
162
132 /* Grossly inefficient hopefully they override this */ 163 /* Grossly inefficient hopefully they override this */
133 for (n = 1; n < buf_size; n++) 164 for (n = 1; n < buflen; n++)
134 { 165 {
135 nr = read (fds->fd, &c, 1); 166 nr = read (fds->fd, &c, 1);
136 if (nr == -1) /* Error. */ 167 if (nr == -1) /* Error. */
...@@ -151,20 +182,38 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br) ...@@ -151,20 +182,38 @@ _stream_fd_readline (stream_t stream, char *buf, size_t buf_size, size_t *br)
151 break; /* EOF, some data was read. */ 182 break; /* EOF, some data was read. */
152 } 183 }
153 } 184 }
185
186 if (buf)
154 *buf = '\0'; 187 *buf = '\0';
188 fds->offset = (n == buflen) ? n - 1: n;
189
155 if (br) 190 if (br)
156 *br = (n == buf_size) ? n - 1: n; 191 *br = (n == buflen) ? n - 1: n;
157 return status; 192 return status;
158 } 193 }
159 194
160 int 195 int
161 _stream_fd_write (stream_t stream, const void *buf, size_t buf_size, size_t *bw) 196 _stream_fd_write (stream_t stream, const void *buf, size_t buf_size,
197 off_t offset, size_t *bw)
162 { 198 {
163 struct _stream_fd *fds = (struct _stream_fd *)stream; 199 struct _stream_fd *fds = (struct _stream_fd *)stream;
164 int bytes = 0; 200 int bytes = 0;
165 int status = 0; 201 int status = 0;
166 202
203 if (fds->fd < 0)
204 {
205 if (bw)
206 *bw = 0;
207 return MU_ERROR_BAD_FILE_DESCRIPTOR;
208 }
209
167 fds->state = MU_STREAM_STATE_WRITE; 210 fds->state = MU_STREAM_STATE_WRITE;
211 if (fds->offset != offset)
212 {
213 lseek (fds->fd, offset, SEEK_SET);
214 fds->offset = offset;
215 }
216
168 bytes = write (fds->fd, buf, buf_size); 217 bytes = write (fds->fd, buf, buf_size);
169 if (bytes == -1) 218 if (bytes == -1)
170 { 219 {
...@@ -177,38 +226,24 @@ _stream_fd_write (stream_t stream, const void *buf, size_t buf_size, size_t *bw) ...@@ -177,38 +226,24 @@ _stream_fd_write (stream_t stream, const void *buf, size_t buf_size, size_t *bw)
177 } 226 }
178 227
179 int 228 int
180 _stream_fd_seek (stream_t stream, off_t off, enum stream_whence whence) 229 _stream_fd_is_seekable (stream_t stream)
181 { 230 {
182 struct _stream_fd *fds = (struct _stream_fd *)stream; 231 off_t off;
183 int err = 0; 232 return _stream_fd_tell (stream, &off) == 0;
184 if (fds->fd)
185 {
186 if (whence == MU_STREAM_WHENCE_SET)
187 off = lseek (fds->fd, off, SEEK_SET);
188 else if (whence == MU_STREAM_WHENCE_CUR)
189 off = lseek (fds->fd, off, SEEK_CUR);
190 else if (whence == MU_STREAM_WHENCE_END)
191 off = lseek (fds->fd, off, SEEK_END);
192 else
193 err = MU_ERROR_INVALID_PARAMETER;
194 if (err == -1)
195 err = errno;
196 }
197 return err;
198 } 233 }
199 234
200 int 235 int
201 _stream_fd_tell (stream_t stream, off_t *off) 236 _stream_fd_tell (stream_t stream, off_t *poff)
202 { 237 {
203 struct _stream_fd *fds = (struct _stream_fd *)stream; 238 struct _stream_fd *fds = (struct _stream_fd *)stream;
204 int err = 0; 239 int err = 0;
205 if (off) 240 if (poff)
206 { 241 {
207 *off = lseek (fds->fd, 0, SEEK_CUR); 242 *poff = lseek (fds->fd, 0, SEEK_CUR);
208 if (*off == -1) 243 if (*poff == -1)
209 { 244 {
210 err = errno; 245 err = errno;
211 *off = 0; 246 *poff = 0;
212 } 247 }
213 } 248 }
214 return err; 249 return err;
...@@ -356,7 +391,6 @@ static struct _stream_vtable _stream_fd_vtable = ...@@ -356,7 +391,6 @@ static struct _stream_vtable _stream_fd_vtable =
356 _stream_fd_readline, 391 _stream_fd_readline,
357 _stream_fd_write, 392 _stream_fd_write,
358 393
359 _stream_fd_seek,
360 _stream_fd_tell, 394 _stream_fd_tell,
361 395
362 _stream_fd_get_size, 396 _stream_fd_get_size,
...@@ -367,6 +401,7 @@ static struct _stream_vtable _stream_fd_vtable = ...@@ -367,6 +401,7 @@ static struct _stream_vtable _stream_fd_vtable =
367 _stream_fd_get_flags, 401 _stream_fd_get_flags,
368 _stream_fd_get_state, 402 _stream_fd_get_state,
369 403
404 _stream_fd_is_seekable,
370 _stream_fd_is_readready, 405 _stream_fd_is_readready,
371 _stream_fd_is_writeready, 406 _stream_fd_is_writeready,
372 _stream_fd_is_exceptionpending, 407 _stream_fd_is_exceptionpending,
...@@ -387,8 +422,10 @@ _stream_fd_ctor (struct _stream_fd *fds, int fd) ...@@ -387,8 +422,10 @@ _stream_fd_ctor (struct _stream_fd *fds, int fd)
387 } 422 }
388 423
389 void 424 void
390 _stream_fd_dtor (struct _stream_fd *fds) 425 _stream_fd_dtor (stream_t stream)
391 { 426 {
427 struct _stream_fd *fds = (struct _stream_fd *)stream;
428 if (fds)
392 mu_refcount_destroy (&fds->refcount); 429 mu_refcount_destroy (&fds->refcount);
393 } 430 }
394 431
......
...@@ -53,21 +53,33 @@ _stream_stdio_destroy (stream_t *pstream) ...@@ -53,21 +53,33 @@ _stream_stdio_destroy (stream_t *pstream)
53 } 53 }
54 54
55 int 55 int
56 _stream_stdio_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) 56 _stream_stdio_read (stream_t stream, void *optr, size_t osize,
57 off_t offset,size_t *nbytes)
57 { 58 {
58 struct _stream_stdio *fs = (struct _stream_stdio *)stream; 59 struct _stream_stdio *fs = (struct _stream_stdio *)stream;
59 size_t n = 0; 60 size_t n = 0;
60 int err = 0; 61 int err = 0;
61 62
62 if (fs->file) 63 if (!fs->file)
63 { 64 {
65 if (nbytes)
66 *nbytes = 0;
67 return MU_ERROR_BAD_FILE_DESCRIPTOR;
68 }
69
70 if (fs->offset != offset)
71 {
72 if (fseek (fs->file, offset, SEEK_SET) != 0)
73 return errno;
74 fs->offset = offset;
75 }
76
64 n = fread (optr, 1, osize, fs->file); 77 n = fread (optr, 1, osize, fs->file);
65 if (n == 0) 78 if (n == 0)
66 { 79 {
67 if (ferror(fs->file)) 80 if (ferror(fs->file))
68 err = MU_ERROR_IO; 81 err = MU_ERROR_IO;
69 } 82 }
70 }
71 83
72 if (nbytes) 84 if (nbytes)
73 *nbytes = n; 85 *nbytes = n;
...@@ -75,24 +87,41 @@ _stream_stdio_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) ...@@ -75,24 +87,41 @@ _stream_stdio_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
75 } 87 }
76 88
77 int 89 int
78 _stream_stdio_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes) 90 _stream_stdio_readline (stream_t stream, char *optr, size_t osize,
91 off_t offset, size_t *nbytes)
79 { 92 {
80 struct _stream_stdio *fs = (struct _stream_stdio *)stream; 93 struct _stream_stdio *fs = (struct _stream_stdio *)stream;
81 size_t n = 0; 94 size_t n = 0;
82 int err = 0; 95 int err = 0;
83 96
84 if (fs->file) 97 if (!fs->file)
85 { 98 {
99 if (nbytes)
100 *nbytes = 0;
101 return MU_ERROR_BAD_FILE_DESCRIPTOR;
102 }
103
104 if (fs->offset != offset)
105 {
106 if (fseek (fs->file, offset, SEEK_SET) != 0)
107 return errno;
108 fs->offset = offset;
109 }
110
86 if (fgets (optr, osize, fs->file) != NULL) 111 if (fgets (optr, osize, fs->file) != NULL)
87 { 112 {
88 n = strlen (optr); 113 n = strlen (optr);
114 /* Oh My!! */
115 if (n == 0)
116 n++;
117 else
118 fs->offset += n;
89 } 119 }
90 else 120 else
91 { 121 {
92 if (ferror (fs->file)) 122 if (ferror (fs->file))
93 err = MU_ERROR_IO; 123 err = MU_ERROR_IO;
94 } 124 }
95 }
96 125
97 if (nbytes) 126 if (nbytes)
98 *nbytes = n; 127 *nbytes = n;
...@@ -100,14 +129,27 @@ _stream_stdio_readline (stream_t stream, char *optr, size_t osize, size_t *nbyte ...@@ -100,14 +129,27 @@ _stream_stdio_readline (stream_t stream, char *optr, size_t osize, size_t *nbyte
100 } 129 }
101 130
102 int 131 int
103 _stream_stdio_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes) 132 _stream_stdio_write (stream_t stream, const void *iptr, size_t isize,
133 off_t offset, size_t *nbytes)
104 { 134 {
105 struct _stream_stdio *fs = (struct _stream_stdio *)stream; 135 struct _stream_stdio *fs = (struct _stream_stdio *)stream;
106 size_t n = 0; 136 size_t n = 0;
107 int err = 0; 137 int err = 0;
108 138
109 if (fs->file) 139 if (!fs->file)
140 {
141 if (nbytes)
142 *nbytes = 0;
143 return MU_ERROR_BAD_FILE_DESCRIPTOR;
144 }
145
146 if (fs->offset != offset)
110 { 147 {
148 if (fseek (fs->file, offset, SEEK_SET) != 0)
149 return errno;
150 fs->offset = offset;
151 }
152
111 n = fwrite (iptr, 1, isize, fs->file); 153 n = fwrite (iptr, 1, isize, fs->file);
112 if (n != isize) 154 if (n != isize)
113 { 155 {
...@@ -116,7 +158,8 @@ _stream_stdio_write (stream_t stream, const void *iptr, size_t isize, size_t *nb ...@@ -116,7 +158,8 @@ _stream_stdio_write (stream_t stream, const void *iptr, size_t isize, size_t *nb
116 clearerr(fs->file); 158 clearerr(fs->file);
117 n = 0; 159 n = 0;
118 } 160 }
119 } 161 else
162 fs->offset += n;
120 163
121 if (nbytes) 164 if (nbytes)
122 *nbytes = n; 165 *nbytes = n;
...@@ -168,40 +211,37 @@ _stream_stdio_get_fd (stream_t stream, int *pfd) ...@@ -168,40 +211,37 @@ _stream_stdio_get_fd (stream_t stream, int *pfd)
168 if (fs->file) 211 if (fs->file)
169 *pfd = fileno (fs->file); 212 *pfd = fileno (fs->file);
170 else 213 else
171 status = MU_ERROR_INVALID_PARAMETER; 214 status = MU_ERROR_BAD_FILE_DESCRIPTOR;
172 } 215 }
173 return status; 216 return status;
174 } 217 }
175 218
176 int 219 int
177 _stream_stdio_seek (stream_t stream, off_t off, enum stream_whence whence) 220 _stream_stdio_is_seekable (stream_t stream)
178 { 221 {
179 struct _stream_stdio *fs = (struct _stream_stdio *)stream; 222 off_t off;
180 int err = 0; 223 return _stream_stdio_tell (stream, &off) == 0;
181 if (fs->file)
182 {
183 if (whence == MU_STREAM_WHENCE_SET)
184 err = fseek (fs->file, off, SEEK_SET);
185 else if (whence == MU_STREAM_WHENCE_CUR)
186 err = fseek (fs->file, off, SEEK_CUR);
187 else if (whence == MU_STREAM_WHENCE_END)
188 err = fseek (fs->file, off, SEEK_END);
189 else
190 err = MU_ERROR_INVALID_PARAMETER;
191 if (err == -1)
192 err = errno;
193 }
194 return err;
195 } 224 }
196 225
197 int 226 int
198 _stream_stdio_tell (stream_t stream, off_t *off) 227 _stream_stdio_tell (stream_t stream, off_t *off)
199 { 228 {
200 struct _stream_stdio *fs = (struct _stream_stdio *)stream; 229 struct _stream_stdio *fs = (struct _stream_stdio *)stream;
230 int status = 0;
201 if (off == NULL) 231 if (off == NULL)
202 return MU_ERROR_INVALID_PARAMETER; 232 return MU_ERROR_INVALID_PARAMETER;
203 *off = (fs->file) ? ftell (fs->file) : 0; 233 if (fs->file)
204 return 0; 234 {
235 *off = ftell (fs->file);
236 if (*off == -1)
237 {
238 *off = 0;
239 status = errno;
240 }
241 }
242 else
243 status = MU_ERROR_BAD_FILE_DESCRIPTOR;
244 return status;
205 } 245 }
206 246
207 int 247 int
...@@ -380,7 +420,6 @@ static struct _stream_vtable _stream_stdio_vtable = ...@@ -380,7 +420,6 @@ static struct _stream_vtable _stream_stdio_vtable =
380 _stream_stdio_readline, 420 _stream_stdio_readline,
381 _stream_stdio_write, 421 _stream_stdio_write,
382 422
383 _stream_stdio_seek,
384 _stream_stdio_tell, 423 _stream_stdio_tell,
385 424
386 _stream_stdio_get_size, 425 _stream_stdio_get_size,
...@@ -391,6 +430,7 @@ static struct _stream_vtable _stream_stdio_vtable = ...@@ -391,6 +430,7 @@ static struct _stream_vtable _stream_stdio_vtable =
391 _stream_stdio_get_flags, 430 _stream_stdio_get_flags,
392 _stream_stdio_get_state, 431 _stream_stdio_get_state,
393 432
433 _stream_stdio_is_seekable,
394 _stream_stdio_is_readready, 434 _stream_stdio_is_readready,
395 _stream_stdio_is_writeready, 435 _stream_stdio_is_writeready,
396 _stream_stdio_is_exceptionpending, 436 _stream_stdio_is_exceptionpending,
...@@ -411,11 +451,15 @@ _stream_stdio_ctor (struct _stream_stdio *fs, FILE *fp) ...@@ -411,11 +451,15 @@ _stream_stdio_ctor (struct _stream_stdio *fs, FILE *fp)
411 } 451 }
412 452
413 void 453 void
414 _stream_stdio_dtor (struct _stream_stdio *fs) 454 _stream_stdio_dtor (stream_t stream)
415 { 455 {
456 struct _stream_stdio *fs = (struct _stream_stdio *)stream;
457 if (fs)
458 {
416 mu_refcount_destroy (&fs->refcount); 459 mu_refcount_destroy (&fs->refcount);
417 /* We may leak if they did not close the FILE * */ 460 /* We may leak if they did not close the FILE * */
418 fs->file = NULL; 461 fs->file = NULL;
462 }
419 } 463 }
420 464
421 int 465 int
......
...@@ -33,14 +33,14 @@ extern "C" { ...@@ -33,14 +33,14 @@ extern "C" {
33 struct _attribute; 33 struct _attribute;
34 typedef struct _attribute * attribute_t; 34 typedef struct _attribute * attribute_t;
35 35
36 #define MU_ATTRIBUTE_ANSWERED 0x00001 36 #define MU_ATTRIBUTE_ANSWERED 0x000001
37 #define MU_ATTRIBUTE_FLAGGED 0x00002 37 #define MU_ATTRIBUTE_FLAGGED 0x000002
38 #define MU_ATTRIBUTE_DELETED 0x00004 38 #define MU_ATTRIBUTE_DELETED 0x000004
39 #define MU_ATTRIBUTE_DRAFT 0x00008 39 #define MU_ATTRIBUTE_DRAFT 0x000008
40 #define MU_ATTRIBUTE_SEEN 0x00010 40 #define MU_ATTRIBUTE_SEEN 0x000010
41 #define MU_ATTRIBUTE_READ 0x00020 41 #define MU_ATTRIBUTE_READ 0x000020
42 #define MU_ATTRIBUTE_MODIFIED 0x10000 42 #define MU_ATTRIBUTE_MODIFIED 0x100000
43 #define MU_ATTRIBUTE_RECENT 0x00000 43 #define MU_ATTRIBUTE_RECENT 0x000000
44 44
45 extern int attribute_ref __P ((attribute_t)); 45 extern int attribute_ref __P ((attribute_t));
46 extern void attribute_destroy __P ((attribute_t *)); 46 extern void attribute_destroy __P ((attribute_t *));
...@@ -72,6 +72,12 @@ extern int attribute_unset_recent __P ((attribute_t)); ...@@ -72,6 +72,12 @@ extern int attribute_unset_recent __P ((attribute_t));
72 extern int attribute_unset_read __P ((attribute_t)); 72 extern int attribute_unset_read __P ((attribute_t));
73 extern int attribute_unset_modified __P ((attribute_t)); 73 extern int attribute_unset_modified __P ((attribute_t));
74 74
75 extern int attribute_is_userflags __P ((attribute_t, int));
76 extern int attribute_set_userflags __P ((attribute_t, int));
77 extern int attribute_unset_userflags __P ((attribute_t, int));
78 extern int attribute_get_userflags __P ((attribute_t, int *));
79 extern int attribute_clear_userflags __P ((attribute_t));
80
75 81
76 extern int attribute_get_flags __P ((attribute_t, int *)); 82 extern int attribute_get_flags __P ((attribute_t, int *));
77 extern int attribute_set_flags __P ((attribute_t, int)); 83 extern int attribute_set_flags __P ((attribute_t, int));
......
...@@ -142,6 +142,11 @@ extern "C" { ...@@ -142,6 +142,11 @@ extern "C" {
142 # define MU_ERROR_NO_DIRECTORY (MU_ERROR_RANGE + 17) 142 # define MU_ERROR_NO_DIRECTORY (MU_ERROR_RANGE + 17)
143 #endif 143 #endif
144 144
145 #if defined (EBADFD)
146 # define MU_ERROR_BAD_FILE_DESCRIPTOR EBADFD
147 #else
148 # define MU_ERROR_BAD_FILE_DESCRIPTOR (MU_ERROR_RANGE + 18)
149 #endif
145 150
146 #ifdef __cplusplus 151 #ifdef __cplusplus
147 } 152 }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
20 20
21 #include <mailutils/stream.h> 21 #include <mailutils/stream.h>
22 #include <mailutils/attribute.h> 22 #include <mailutils/attribute.h>
23 #include <mailutils/debug.h>
23 24
24 #ifdef __cplusplus 25 #ifdef __cplusplus
25 extern "C" { 26 extern "C" {
...@@ -46,12 +47,6 @@ extern int mbox_get_uidnext __P ((mbox_t, unsigned long *)); ...@@ -46,12 +47,6 @@ extern int mbox_get_uidnext __P ((mbox_t, unsigned long *));
46 extern int mbox_open __P ((mbox_t, const char *, int)); 47 extern int mbox_open __P ((mbox_t, const char *, int));
47 extern int mbox_close __P ((mbox_t)); 48 extern int mbox_close __P ((mbox_t));
48 49
49 extern int mbox_get_attribute __P ((mbox_t, unsigned int, attribute_t *));
50 extern int mbox_get_uid __P ((mbox_t, unsigned int, unsigned long *));
51
52 extern int mbox_get_separator __P ((mbox_t, unsigned int, char **));
53 extern int mbox_set_separator __P ((mbox_t, unsigned int, const char *));
54
55 extern int mbox_get_hstream __P ((mbox_t, unsigned int, stream_t *)); 50 extern int mbox_get_hstream __P ((mbox_t, unsigned int, stream_t *));
56 extern int mbox_set_hstream __P ((mbox_t, unsigned int, stream_t)); 51 extern int mbox_set_hstream __P ((mbox_t, unsigned int, stream_t));
57 extern int mbox_get_hsize __P ((mbox_t, unsigned int, unsigned int *)); 52 extern int mbox_get_hsize __P ((mbox_t, unsigned int, unsigned int *));
...@@ -62,44 +57,42 @@ extern int mbox_set_bstream __P ((mbox_t, unsigned int, stream_t)); ...@@ -62,44 +57,42 @@ extern int mbox_set_bstream __P ((mbox_t, unsigned int, stream_t));
62 extern int mbox_get_bsize __P ((mbox_t, unsigned int, unsigned int *)); 57 extern int mbox_get_bsize __P ((mbox_t, unsigned int, unsigned int *));
63 extern int mbox_get_blines __P ((mbox_t, unsigned int, unsigned int *)); 58 extern int mbox_get_blines __P ((mbox_t, unsigned int, unsigned int *));
64 59
60 extern int mbox_get_attribute __P ((mbox_t, unsigned int, attribute_t *));
61 extern int mbox_get_uid __P ((mbox_t, unsigned int, unsigned long *));
65 extern int mbox_get_size __P ((mbox_t, off_t *)); 62 extern int mbox_get_size __P ((mbox_t, off_t *));
63 extern int mbox_get_separator __P ((mbox_t, unsigned int, char **));
64 extern int mbox_set_separator __P ((mbox_t, unsigned int, const char *));
66 65
67 extern int mbox_save_attributes __P ((mbox_t));
68 extern int mbox_expunge __P ((mbox_t, int)); 66 extern int mbox_expunge __P ((mbox_t, int));
69 extern int mbox_has_newmail __P ((mbox_t)); 67 extern int mbox_has_newmail __P ((mbox_t));
70 68
71 extern int mbox_set_progress_cb 69 extern int mbox_set_progress_cb __P ((mbox_t,
72 __P ((mbox_t, int (*) __P ((int, void *)), void *)); 70 int (*) __P ((int, void *)), void *));
73 extern int mbox_set_newmsg_cb 71 extern int mbox_set_newmsg_cb __P ((mbox_t,
74 __P ((mbox_t, int (*) __P ((int, void *)), void *)); 72 int (*) __P ((int, void *)), void *));
75 extern int mbox_newmsg_cb __P ((mbox_t, int)); 73 extern int mbox_set_error_cb __P ((mbox_t,
76 extern int mbox_progress_cb __P ((mbox_t, int)); 74 int (*) __P ((int, void *)), void *));
77 75
78 extern int mbox_scan __P ((mbox_t, unsigned int, unsigned int *, int)); 76 extern int mbox_scan __P ((mbox_t, unsigned int,
79 extern int mbox_messages_count __P ((mbox_t, unsigned int *)); 77 unsigned int *, int));
80 78
81 extern int mbox_append __P ((mbox_t, const char *, attribute_t, stream_t)); 79 extern int mbox_append __P ((mbox_t, const char *, attribute_t,
82 extern int mbox_append_hb 80 stream_t));
83 __P ((mbox_t, const char *, attribute_t, stream_t, stream_t)); 81 extern int mbox_append_hb __P ((mbox_t, const char *, attribute_t,
84 extern int mbox_append_hb0 82 stream_t, stream_t));
85 __P ((mbox_t, const char *, attribute_t, int, stream_t, stream_t));
86 83
87 extern int mbox_get_carrier __P ((mbox_t, stream_t *)); 84 extern int mbox_get_carrier __P ((mbox_t, stream_t *));
88 extern int mbox_set_carrier __P ((mbox_t, stream_t)); 85 extern int mbox_set_carrier __P ((mbox_t, stream_t));
89 86
90 extern int mbox_set_hcache __P ((mbox_t, const char **, size_t)); 87 extern int mbox_set_hcache __P ((mbox_t, const char **, size_t));
91 extern int mbox_set_hcache_default __P ((mbox_t)); 88 extern int mbox_add_hcache __P ((mbox_t, const char **, size_t));
92 extern void mbox_hcache_free __P ((mbox_t, unsigned int));
93 extern int mbox_hcache_append __P ((mbox_t, unsigned int, const char *,
94 const char *));
95 89
96 extern int mbox_header_get_value __P ((mbox_t, unsigned int, const char *, 90 extern int mbox_value_hcache __P ((mbox_t, unsigned int, const char *,
97 char *, size_t, size_t *)); 91 char *, size_t, size_t *));
98 92
99 extern int stream_mbox_create __P ((stream_t *, mbox_t, unsigned int, int)); 93 extern int mbox_get_debug __P ((mbox_t, mu_debug_t *));
100 extern int attribute_mbox_create __P ((attribute_t *, mbox_t, unsigned int)); 94 extern int mbox_set_debug __P ((mbox_t, mu_debug_t));
101 extern int mbox_attribute_to_status 95
102 __P ((attribute_t, char *, size_t, size_t *));
103 96
104 #ifdef __cplusplus 97 #ifdef __cplusplus
105 } 98 }
......
...@@ -32,13 +32,6 @@ extern "C" { ...@@ -32,13 +32,6 @@ extern "C" {
32 #define MU_STREAM_CREAT 0x00000008 32 #define MU_STREAM_CREAT 0x00000008
33 #define MU_STREAM_NONBLOCK 0x00000010 33 #define MU_STREAM_NONBLOCK 0x00000010
34 34
35 enum stream_whence
36 {
37 MU_STREAM_WHENCE_SET,
38 MU_STREAM_WHENCE_CUR,
39 MU_STREAM_WHENCE_END
40 };
41
42 enum stream_state 35 enum stream_state
43 { 36 {
44 MU_STREAM_NO_STATE, 37 MU_STREAM_NO_STATE,
...@@ -57,11 +50,10 @@ extern void stream_destroy __P ((stream_t *)); ...@@ -57,11 +50,10 @@ extern void stream_destroy __P ((stream_t *));
57 extern int stream_open __P ((stream_t, const char *, int, int)); 50 extern int stream_open __P ((stream_t, const char *, int, int));
58 extern int stream_close __P ((stream_t)); 51 extern int stream_close __P ((stream_t));
59 52
60 extern int stream_read __P ((stream_t, void *, size_t, size_t *)); 53 extern int stream_read __P ((stream_t, void *, size_t, off_t, size_t *));
61 extern int stream_readline __P ((stream_t, char *, size_t, size_t *)); 54 extern int stream_readline __P ((stream_t, char *, size_t, off_t, size_t *));
62 extern int stream_write __P ((stream_t, const void *, size_t, size_t*)); 55 extern int stream_write __P ((stream_t, const void *, size_t, off_t, size_t*));
63 56
64 extern int stream_seek __P ((stream_t, off_t, enum stream_whence));
65 extern int stream_tell __P ((stream_t, off_t *)); 57 extern int stream_tell __P ((stream_t, off_t *));
66 58
67 extern int stream_get_size __P ((stream_t, off_t *)); 59 extern int stream_get_size __P ((stream_t, off_t *));
...@@ -72,6 +64,7 @@ extern int stream_get_fd __P ((stream_t , int *)); ...@@ -72,6 +64,7 @@ extern int stream_get_fd __P ((stream_t , int *));
72 extern int stream_get_flags __P ((stream_t, int *)); 64 extern int stream_get_flags __P ((stream_t, int *));
73 extern int stream_get_state __P ((stream_t, enum stream_state *)); 65 extern int stream_get_state __P ((stream_t, enum stream_state *));
74 66
67 extern int stream_is_seekable __P ((stream_t));
75 extern int stream_is_readready __P ((stream_t, int)); 68 extern int stream_is_readready __P ((stream_t, int));
76 extern int stream_is_writeready __P ((stream_t, int)); 69 extern int stream_is_writeready __P ((stream_t, int));
77 extern int stream_is_exceptionpending __P ((stream_t, int)); 70 extern int stream_is_exceptionpending __P ((stream_t, int));
......
...@@ -45,6 +45,11 @@ struct _attribute_vtable ...@@ -45,6 +45,11 @@ struct _attribute_vtable
45 int (*set_flags) __P ((attribute_t, int)); 45 int (*set_flags) __P ((attribute_t, int));
46 int (*unset_flags) __P ((attribute_t, int)); 46 int (*unset_flags) __P ((attribute_t, int));
47 int (*clear_flags) __P ((attribute_t)); 47 int (*clear_flags) __P ((attribute_t));
48
49 int (*get_userflags) __P ((attribute_t, int *));
50 int (*set_userflags) __P ((attribute_t, int));
51 int (*unset_userflags) __P ((attribute_t, int));
52 int (*clear_userflags) __P ((attribute_t));
48 }; 53 };
49 54
50 struct _attribute 55 struct _attribute
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef MAILUTILS_SYS_BSTREAM_H 18 #ifndef MAILUTILS_SYS_BSTREAM_H
19 #define MAILUTILS_SYS_BSTREAM_H 19 #define MAILUTILS_SYS_BSTREAM_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/sys/stream.h> 25 #include <mailutils/sys/stream.h>
22 #include <mailutils/refcount.h> 26 #include <mailutils/refcount.h>
23 27
...@@ -31,6 +35,7 @@ struct _rbuffer ...@@ -31,6 +35,7 @@ struct _rbuffer
31 char *base; 35 char *base;
32 char *ptr; 36 char *ptr;
33 int count; 37 int count;
38 off_t offset;
34 size_t bufsize; 39 size_t bufsize;
35 }; 40 };
36 41
...@@ -43,22 +48,22 @@ struct _stream_buffer ...@@ -43,22 +48,22 @@ struct _stream_buffer
43 }; 48 };
44 49
45 extern int _stream_buffer_ctor __P ((struct _stream_buffer *, stream_t, size_t)); 50 extern int _stream_buffer_ctor __P ((struct _stream_buffer *, stream_t, size_t));
46 extern void _stream_buffer_dtor __P ((struct _stream_buffer *)); 51 extern void _stream_buffer_dtor __P ((stream_t));
47 extern int _stream_buffer_ref __P ((stream_t)); 52 extern int _stream_buffer_ref __P ((stream_t));
48 extern void _stream_buffer_destroy __P ((stream_t *)); 53 extern void _stream_buffer_destroy __P ((stream_t *));
49 extern int _stream_buffer_open __P ((stream_t, const char *, int, int)); 54 extern int _stream_buffer_open __P ((stream_t, const char *, int, int));
50 extern int _stream_buffer_close __P ((stream_t)); 55 extern int _stream_buffer_close __P ((stream_t));
51 extern int _stream_buffer_read __P ((stream_t, void *, size_t, size_t *)); 56 extern int _stream_buffer_read __P ((stream_t, void *, size_t, off_t, size_t *));
52 extern int _stream_buffer_readline __P ((stream_t, char *, size_t, size_t *)); 57 extern int _stream_buffer_readline __P ((stream_t, char *, size_t, off_t, size_t *));
53 extern int _stream_buffer_write __P ((stream_t, const void *, size_t, size_t *)); 58 extern int _stream_buffer_write __P ((stream_t, const void *, size_t, off_t, size_t *));
54 extern int _stream_buffer_get_fd __P ((stream_t, int *)); 59 extern int _stream_buffer_get_fd __P ((stream_t, int *));
55 extern int _stream_buffer_get_flags __P ((stream_t, int *)); 60 extern int _stream_buffer_get_flags __P ((stream_t, int *));
56 extern int _stream_buffer_get_size __P ((stream_t, off_t *)); 61 extern int _stream_buffer_get_size __P ((stream_t, off_t *));
57 extern int _stream_buffer_truncate __P ((stream_t, off_t)); 62 extern int _stream_buffer_truncate __P ((stream_t, off_t));
58 extern int _stream_buffer_flush __P ((stream_t)); 63 extern int _stream_buffer_flush __P ((stream_t));
59 extern int _stream_buffer_get_state __P ((stream_t, enum stream_state *)); 64 extern int _stream_buffer_get_state __P ((stream_t, enum stream_state *));
60 extern int _stream_buffer_seek __P ((stream_t, off_t, enum stream_whence));
61 extern int _stream_buffer_tell __P ((stream_t, off_t *)); 65 extern int _stream_buffer_tell __P ((stream_t, off_t *));
66 extern int _stream_buffer_is_seekable __P ((stream_t));
62 extern int _stream_buffer_is_readready __P ((stream_t, int )); 67 extern int _stream_buffer_is_readready __P ((stream_t, int ));
63 extern int _stream_buffer_is_writeready __P ((stream_t, int)); 68 extern int _stream_buffer_is_writeready __P ((stream_t, int));
64 extern int _stream_buffer_is_exceptionpending __P ((stream_t, int)); 69 extern int _stream_buffer_is_exceptionpending __P ((stream_t, int));
......
...@@ -35,10 +35,11 @@ struct _attribute_default ...@@ -35,10 +35,11 @@ struct _attribute_default
35 struct _attribute base; 35 struct _attribute base;
36 mu_refcount_t refcount; 36 mu_refcount_t refcount;
37 int flags; 37 int flags;
38 int userflags;
38 }; 39 };
39 40
40 extern int _attribute_default_ctor __P ((struct _attribute_default *)); 41 extern int _attribute_default_ctor __P ((struct _attribute_default *));
41 extern void _attribute_default_dtor __P ((struct _attribute_default *)); 42 extern void _attribute_default_dtor __P ((attribute_t));
42 extern int _attribute_default_ref __P ((attribute_t)); 43 extern int _attribute_default_ref __P ((attribute_t));
43 extern void _attribute_default_destroy __P ((attribute_t *)); 44 extern void _attribute_default_destroy __P ((attribute_t *));
44 45
...@@ -47,6 +48,11 @@ extern int _attribute_default_set_flags __P ((attribute_t, int)); ...@@ -47,6 +48,11 @@ extern int _attribute_default_set_flags __P ((attribute_t, int));
47 extern int _attribute_default_unset_flags __P ((attribute_t, int)); 48 extern int _attribute_default_unset_flags __P ((attribute_t, int));
48 extern int _attribute_default_clear_flags __P ((attribute_t)); 49 extern int _attribute_default_clear_flags __P ((attribute_t));
49 50
51 extern int _attribute_default_get_userflags __P ((attribute_t, int *));
52 extern int _attribute_default_set_userflags __P ((attribute_t, int));
53 extern int _attribute_default_unset_userflags __P ((attribute_t, int));
54 extern int _attribute_default_clear_userflags __P ((attribute_t));
55
50 #ifdef __cplusplus 56 #ifdef __cplusplus
51 } 57 }
52 #endif 58 #endif
......
...@@ -49,7 +49,7 @@ struct _lockfile_dotlock ...@@ -49,7 +49,7 @@ struct _lockfile_dotlock
49 }; 49 };
50 50
51 extern int _lockfile_dotlock_ctor __P ((struct _lockfile_dotlock *, const char *)); 51 extern int _lockfile_dotlock_ctor __P ((struct _lockfile_dotlock *, const char *));
52 extern void _lockfile_dotlock_dtor __P ((struct _lockfile_dotlock *)); 52 extern void _lockfile_dotlock_dtor __P ((lockfile_t));
53 extern int _lockfile_dotlock_ref __P ((lockfile_t)); 53 extern int _lockfile_dotlock_ref __P ((lockfile_t));
54 extern void _lockfile_dotlock_destroy __P ((lockfile_t *)); 54 extern void _lockfile_dotlock_destroy __P ((lockfile_t *));
55 55
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef MAILUTILS_SYS_FDSTREAM_H 18 #ifndef MAILUTILS_SYS_FDSTREAM_H
19 #define MAILUTILS_SYS_FDSTREAM_H 19 #define MAILUTILS_SYS_FDSTREAM_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/refcount.h> 25 #include <mailutils/refcount.h>
22 #include <mailutils/sys/stream.h> 26 #include <mailutils/sys/stream.h>
23 27
...@@ -32,27 +36,28 @@ struct _stream_fd ...@@ -32,27 +36,28 @@ struct _stream_fd
32 int fd; 36 int fd;
33 int state; 37 int state;
34 int flags; 38 int flags;
39 off_t offset;
35 }; 40 };
36 41
37 int _stream_fd_ctor __P ((struct _stream_fd *, int)); 42 int _stream_fd_ctor __P ((struct _stream_fd *, int));
38 void _stream_fd_dtor __P ((struct _stream_fd *)); 43 void _stream_fd_dtor __P ((stream_t));
39 44
40 int _stream_fd_ref __P ((stream_t)); 45 int _stream_fd_ref __P ((stream_t));
41 void _stream_fd_destroy __P ((stream_t *)); 46 void _stream_fd_destroy __P ((stream_t *));
42 int _stream_fd_open __P ((stream_t, const char *, int, int)); 47 int _stream_fd_open __P ((stream_t, const char *, int, int));
43 int _stream_fd_close __P ((stream_t)); 48 int _stream_fd_close __P ((stream_t));
44 int _stream_fd_read __P ((stream_t, void *, size_t, size_t *)); 49 int _stream_fd_read __P ((stream_t, void *, size_t, off_t, size_t *));
45 int _stream_fd_readline __P ((stream_t, char *, size_t, size_t *)); 50 int _stream_fd_readline __P ((stream_t, char *, size_t, off_t, size_t *));
46 int _stream_fd_write __P ((stream_t, const void *, size_t, size_t *)); 51 int _stream_fd_write __P ((stream_t, const void *, size_t, off_t, size_t *));
47 int _stream_fd_get_fd __P ((stream_t, int *)); 52 int _stream_fd_get_fd __P ((stream_t, int *));
48 int _stream_fd_get_flags __P ((stream_t, int *)); 53 int _stream_fd_get_flags __P ((stream_t, int *));
49 int _stream_fd_get_size __P ((stream_t, off_t *)); 54 int _stream_fd_get_size __P ((stream_t, off_t *));
50 int _stream_fd_truncate __P ((stream_t, off_t)); 55 int _stream_fd_truncate __P ((stream_t, off_t));
51 int _stream_fd_flush __P ((stream_t)); 56 int _stream_fd_flush __P ((stream_t));
52 int _stream_fd_get_state __P ((stream_t, enum stream_state *)); 57 int _stream_fd_get_state __P ((stream_t, enum stream_state *));
53 int _stream_fd_seek __P ((stream_t, off_t, enum stream_whence));
54 int _stream_fd_tell __P ((stream_t, off_t *)); 58 int _stream_fd_tell __P ((stream_t, off_t *));
55 int _stream_fd_is_readready __P ((stream_t, int )); 59 int _stream_fd_is_seekable __P ((stream_t));
60 int _stream_fd_is_readready __P ((stream_t, int));
56 int _stream_fd_is_writeready __P ((stream_t, int)); 61 int _stream_fd_is_writeready __P ((stream_t, int));
57 int _stream_fd_is_exceptionpending __P ((stream_t, int)); 62 int _stream_fd_is_exceptionpending __P ((stream_t, int));
58 int _stream_fd_is_open __P ((stream_t)); 63 int _stream_fd_is_open __P ((stream_t));
......
...@@ -18,8 +18,11 @@ ...@@ -18,8 +18,11 @@
18 #ifndef _MAILUTILS_SYS_FOLDER_H 18 #ifndef _MAILUTILS_SYS_FOLDER_H
19 #define _MAILUTILS_SYS_FOLDER_H 19 #define _MAILUTILS_SYS_FOLDER_H
20 20
21 #include <mailutils/folder.h> 21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
22 24
25 #include <mailutils/folder.h>
23 26
24 #ifdef __cplusplus 27 #ifdef __cplusplus
25 extern "C" { 28 extern "C" {
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef MAILUTILS_SYS_FSTREAM_H 18 #ifndef MAILUTILS_SYS_FSTREAM_H
19 #define MAILUTILS_SYS_FSTREAM_H 19 #define MAILUTILS_SYS_FSTREAM_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/sys/stream.h> 25 #include <mailutils/sys/stream.h>
22 #include <mailutils/refcount.h> 26 #include <mailutils/refcount.h>
23 27
...@@ -30,27 +34,28 @@ struct _stream_stdio ...@@ -30,27 +34,28 @@ struct _stream_stdio
30 struct _stream base; 34 struct _stream base;
31 mu_refcount_t refcount; 35 mu_refcount_t refcount;
32 int flags; 36 int flags;
37 off_t offset;
33 FILE *file; 38 FILE *file;
34 }; 39 };
35 40
36 extern int _stream_stdio_ctor __P ((struct _stream_stdio *, FILE *)); 41 extern int _stream_stdio_ctor __P ((struct _stream_stdio *, FILE *));
37 extern void _stream_stdio_dtor __P ((struct _stream_stdio *)); 42 extern void _stream_stdio_dtor __P ((stream_t));
38 extern int _stream_stdio_ref __P ((stream_t)); 43 extern int _stream_stdio_ref __P ((stream_t));
39 extern void _stream_stdio_destroy __P ((stream_t *)); 44 extern void _stream_stdio_destroy __P ((stream_t *));
40 extern int _stream_stdio_open __P ((stream_t, const char *, int, int)); 45 extern int _stream_stdio_open __P ((stream_t, const char *, int, int));
41 extern int _stream_stdio_close __P ((stream_t)); 46 extern int _stream_stdio_close __P ((stream_t));
42 extern int _stream_stdio_read __P ((stream_t, void *, size_t, size_t *)); 47 extern int _stream_stdio_read __P ((stream_t, void *, size_t, off_t, size_t *));
43 extern int _stream_stdio_readline __P ((stream_t, char *, size_t, size_t *)); 48 extern int _stream_stdio_readline __P ((stream_t, char *, size_t, off_t, size_t *));
44 extern int _stream_stdio_write __P ((stream_t, const void *, size_t, size_t *)); 49 extern int _stream_stdio_write __P ((stream_t, const void *, size_t, off_t, size_t *));
45 extern int _stream_stdio_get_fd __P ((stream_t, int *)); 50 extern int _stream_stdio_get_fd __P ((stream_t, int *));
46 extern int _stream_stdio_get_flags __P ((stream_t, int *)); 51 extern int _stream_stdio_get_flags __P ((stream_t, int *));
47 extern int _stream_stdio_get_size __P ((stream_t, off_t *)); 52 extern int _stream_stdio_get_size __P ((stream_t, off_t *));
48 extern int _stream_stdio_truncate __P ((stream_t, off_t)); 53 extern int _stream_stdio_truncate __P ((stream_t, off_t));
49 extern int _stream_stdio_flush __P ((stream_t)); 54 extern int _stream_stdio_flush __P ((stream_t));
50 extern int _stream_stdio_get_state __P ((stream_t, enum stream_state *)); 55 extern int _stream_stdio_get_state __P ((stream_t, enum stream_state *));
51 extern int _stream_stdio_seek __P ((stream_t, off_t, enum stream_whence));
52 extern int _stream_stdio_tell __P ((stream_t, off_t *)); 56 extern int _stream_stdio_tell __P ((stream_t, off_t *));
53 extern int _stream_stdio_is_readready __P ((stream_t, int )); 57 extern int _stream_stdio_is_seekable __P ((stream_t));
58 extern int _stream_stdio_is_readready __P ((stream_t, int));
54 extern int _stream_stdio_is_writeready __P ((stream_t, int)); 59 extern int _stream_stdio_is_writeready __P ((stream_t, int));
55 extern int _stream_stdio_is_exceptionpending __P ((stream_t, int)); 60 extern int _stream_stdio_is_exceptionpending __P ((stream_t, int));
56 extern int _stream_stdio_is_open __P ((stream_t)); 61 extern int _stream_stdio_is_open __P ((stream_t));
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_HEADER_H 18 #ifndef _MAILUTILS_SYS_HEADER_H
19 #define _MAILUTILS_SYS_HEADER_H 19 #define _MAILUTILS_SYS_HEADER_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/header.h> 25 #include <mailutils/header.h>
22 26
23 #ifndef __P 27 #ifndef __P
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_ITERATOR_H 18 #ifndef _MAILUTILS_SYS_ITERATOR_H
19 #define _MAILUTILS_SYS_ITERATOR_H 19 #define _MAILUTILS_SYS_ITERATOR_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/iterator.h> 25 #include <mailutils/iterator.h>
22 26
23 #ifdef __cplusplus 27 #ifdef __cplusplus
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_MAILBOX_H 18 #ifndef _MAILUTILS_SYS_MAILBOX_H
19 #define _MAILUTILS_SYS_MAILBOX_H 19 #define _MAILUTILS_SYS_MAILBOX_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/mailbox.h> 25 #include <mailutils/mailbox.h>
22 26
23 #ifdef __cplusplus 27 #ifdef __cplusplus
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
20 20
21 #include <unistd.h> 21 #include <unistd.h>
22 22
23 #ifdef DMALLOC
24 # include <dmalloc.h>
25 #endif
26
23 #include <mailutils/sys/stream.h> 27 #include <mailutils/sys/stream.h>
24 #include <mailutils/refcount.h> 28 #include <mailutils/refcount.h>
25 29
...@@ -38,27 +42,26 @@ struct _stream_mmap ...@@ -38,27 +42,26 @@ struct _stream_mmap
38 int mflags; 42 int mflags;
39 char *ptr; 43 char *ptr;
40 size_t size; 44 size_t size;
41 off_t offset;
42 }; 45 };
43 46
44 extern int _stream_mmap_ctor __P ((struct _stream_mmap *)); 47 extern int _stream_mmap_ctor __P ((struct _stream_mmap *));
45 extern void _stream_mmap_dtor __P ((struct _stream_mmap *)); 48 extern void _stream_mmap_dtor __P ((stream_t));
46 extern int _stream_mmap_ref __P ((stream_t)); 49 extern int _stream_mmap_ref __P ((stream_t));
47 extern void _stream_mmap_destroy __P ((stream_t *)); 50 extern void _stream_mmap_destroy __P ((stream_t *));
48 extern int _stream_mmap_open __P ((stream_t, const char *, int, int)); 51 extern int _stream_mmap_open __P ((stream_t, const char *, int, int));
49 extern int _stream_mmap_close __P ((stream_t)); 52 extern int _stream_mmap_close __P ((stream_t));
50 extern int _stream_mmap_read __P ((stream_t, void *, size_t, size_t *)); 53 extern int _stream_mmap_read __P ((stream_t, void *, size_t, off_t, size_t *));
51 extern int _stream_mmap_readline __P ((stream_t, char *, size_t, size_t *)); 54 extern int _stream_mmap_readline __P ((stream_t, char *, size_t, off_t, size_t *));
52 extern int _stream_mmap_write __P ((stream_t, const void *, size_t, size_t *)); 55 extern int _stream_mmap_write __P ((stream_t, const void *, size_t, off_t, size_t *));
53 extern int _stream_mmap_get_fd __P ((stream_t, int *)); 56 extern int _stream_mmap_get_fd __P ((stream_t, int *));
54 extern int _stream_mmap_get_flags __P ((stream_t, int *)); 57 extern int _stream_mmap_get_flags __P ((stream_t, int *));
55 extern int _stream_mmap_get_size __P ((stream_t, off_t *)); 58 extern int _stream_mmap_get_size __P ((stream_t, off_t *));
56 extern int _stream_mmap_truncate __P ((stream_t, off_t)); 59 extern int _stream_mmap_truncate __P ((stream_t, off_t));
57 extern int _stream_mmap_flush __P ((stream_t)); 60 extern int _stream_mmap_flush __P ((stream_t));
58 extern int _stream_mmap_get_state __P ((stream_t, enum stream_state *)); 61 extern int _stream_mmap_get_state __P ((stream_t, enum stream_state *));
59 extern int _stream_mmap_seek __P ((stream_t, off_t, enum stream_whence));
60 extern int _stream_mmap_tell __P ((stream_t, off_t *)); 62 extern int _stream_mmap_tell __P ((stream_t, off_t *));
61 extern int _stream_mmap_is_readready __P ((stream_t, int )); 63 extern int _stream_mmap_is_seekable __P ((stream_t));
64 extern int _stream_mmap_is_readready __P ((stream_t, int));
62 extern int _stream_mmap_is_writeready __P ((stream_t, int)); 65 extern int _stream_mmap_is_writeready __P ((stream_t, int));
63 extern int _stream_mmap_is_exceptionpending __P ((stream_t, int)); 66 extern int _stream_mmap_is_exceptionpending __P ((stream_t, int));
64 extern int _stream_mmap_is_open __P ((stream_t)); 67 extern int _stream_mmap_is_open __P ((stream_t));
......
...@@ -19,9 +19,18 @@ ...@@ -19,9 +19,18 @@
19 #define _MAILUTILS_SYS_MBOX_H 19 #define _MAILUTILS_SYS_MBOX_H
20 20
21 #include <time.h> 21 #include <time.h>
22 #include <stdarg.h>
23
24 #ifdef DMALLOC
25 # include <dmalloc.h>
26 #endif
27
22 #include <mailutils/lockfile.h> 28 #include <mailutils/lockfile.h>
23 #include <mailutils/mbox.h> 29 #include <mailutils/mbox.h>
24 30
31 #define MU_MBOX_HSTREAM_SET 0x010000
32 #define MU_MBOX_BSTREAM_SET 0x001000
33
25 #ifdef __cplusplus 34 #ifdef __cplusplus
26 extern "C" { 35 extern "C" {
27 #endif 36 #endif
...@@ -49,6 +58,7 @@ struct _mbox ...@@ -49,6 +58,7 @@ struct _mbox
49 stream_t carrier; /* File stream. */ 58 stream_t carrier; /* File stream. */
50 59
51 off_t size; /* Size of the mailbox. */ 60 off_t size; /* Size of the mailbox. */
61 mu_debug_t debug;
52 unsigned long uidvalidity; 62 unsigned long uidvalidity;
53 unsigned long uidnext; 63 unsigned long uidnext;
54 char *filename; 64 char *filename;
...@@ -69,7 +79,10 @@ struct _mbox ...@@ -69,7 +79,10 @@ struct _mbox
69 { 79 {
70 int (*cb) __P ((int, void *)); 80 int (*cb) __P ((int, void *));
71 void *arg; 81 void *arg;
72 } newmsg, progress, corrupt; 82 } newmsg, progress, error;
83
84 /* Hold the offset of the stream when appending. */
85 off_t roffset, woffset;
73 }; 86 };
74 87
75 /* Keep the file positions of where the headers and bodies start and end. 88 /* Keep the file positions of where the headers and bodies start and end.
...@@ -96,9 +109,40 @@ struct _mbox_message ...@@ -96,9 +109,40 @@ struct _mbox_message
96 /* UID i.e. see IMAP */ 109 /* UID i.e. see IMAP */
97 unsigned long uid; 110 unsigned long uid;
98 unsigned int attr_flags; 111 unsigned int attr_flags;
112 unsigned int attr_userflags;
99 attribute_t attribute; /* The attr_flags contains the "Status:" attribute */ 113 attribute_t attribute; /* The attr_flags contains the "Status:" attribute */
100 }; 114 };
101 115
116 extern int mbox_newmsg_cb __P ((mbox_t, int));
117 extern int mbox_progress_cb __P ((mbox_t, int));
118 extern int mbox_error_cb __P ((mbox_t, int));
119
120 extern int mbox_append_hb0 __P ((mbox_t, const char *, attribute_t,
121 stream_t, stream_t, int, unsigned long));
122
123 extern void mbox_release_hcache __P ((mbox_t, unsigned int));
124 extern int mbox_append_hcache __P ((mbox_t, unsigned int, const char *,
125 const char *));
126 extern int mbox_set_default_hcache __P ((mbox_t));
127
128 extern int mbox_debug_print __P ((mbox_t, const char *, ...));
129
130 extern int stream_mbox_create __P ((stream_t *, mbox_t, unsigned int, int));
131 extern int stream_mbox_msgno __P ((stream_t, unsigned int));
132 extern void _stream_mbox_dtor __P ((stream_t));
133
134 extern int attribute_mbox_create __P ((attribute_t *, mbox_t, unsigned int));
135 extern int attribute_mbox_msgno __P ((attribute_t, unsigned int));
136 extern int mbox_attribute_to_status __P ((attribute_t, char *, size_t,
137 size_t *));
138 extern void _attribute_mbox_dtor __P ((attribute_t));
139
140 extern void mbox_release_separator __P ((mbox_t, unsigned int));
141 extern void mbox_release_attribute __P ((mbox_t, unsigned int));
142 extern void mbox_release_hstream __P ((mbox_t, unsigned int));
143 extern void mbox_release_bstream __P ((mbox_t, unsigned int));
144 extern void mbox_release_msg __P ((mbox_t, unsigned int));
145
102 #ifdef __cplusplus 146 #ifdef __cplusplus
103 } 147 }
104 #endif 148 #endif
......
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
20 20
21 #include <sys/types.h> 21 #include <sys/types.h>
22 22
23 #ifdef DMALLOC
24 # include <dmalloc.h>
25 #endif
26
23 #include <mailutils/refcount.h> 27 #include <mailutils/refcount.h>
24 #include <mailutils/sys/stream.h> 28 #include <mailutils/sys/stream.h>
25 29
...@@ -38,27 +42,26 @@ struct _stream_memory ...@@ -38,27 +42,26 @@ struct _stream_memory
38 char *ptr; 42 char *ptr;
39 size_t capacity; 43 size_t capacity;
40 size_t size; 44 size_t size;
41 off_t offset;
42 int flags; 45 int flags;
43 }; 46 };
44 47
45 extern int _stream_memory_ctor __P ((struct _stream_memory *, size_t)); 48 extern int _stream_memory_ctor __P ((struct _stream_memory *, size_t));
46 extern void _stream_memory_dtor __P ((struct _stream_memory *)); 49 extern void _stream_memory_dtor __P ((stream_t));
47 extern int _stream_memory_ref __P ((stream_t)); 50 extern int _stream_memory_ref __P ((stream_t));
48 extern void _stream_memory_destroy __P ((stream_t *)); 51 extern void _stream_memory_destroy __P ((stream_t *));
49 extern int _stream_memory_open __P ((stream_t, const char *, int, int)); 52 extern int _stream_memory_open __P ((stream_t, const char *, int, int));
50 extern int _stream_memory_close __P ((stream_t)); 53 extern int _stream_memory_close __P ((stream_t));
51 extern int _stream_memory_read __P ((stream_t, void *, size_t, size_t *)); 54 extern int _stream_memory_read __P ((stream_t, void *, size_t, off_t, size_t *));
52 extern int _stream_memory_readline __P ((stream_t, char *, size_t, size_t *)); 55 extern int _stream_memory_readline __P ((stream_t, char *, size_t, off_t, size_t *));
53 extern int _stream_memory_write __P ((stream_t, const void *, size_t, size_t *)); 56 extern int _stream_memory_write __P ((stream_t, const void *, size_t, off_t, size_t *));
54 extern int _stream_memory_get_fd __P ((stream_t, int *)); 57 extern int _stream_memory_get_fd __P ((stream_t, int *));
55 extern int _stream_memory_get_flags __P ((stream_t, int *)); 58 extern int _stream_memory_get_flags __P ((stream_t, int *));
56 extern int _stream_memory_get_size __P ((stream_t, off_t *)); 59 extern int _stream_memory_get_size __P ((stream_t, off_t *));
57 extern int _stream_memory_truncate __P ((stream_t, off_t)); 60 extern int _stream_memory_truncate __P ((stream_t, off_t));
58 extern int _stream_memory_flush __P ((stream_t)); 61 extern int _stream_memory_flush __P ((stream_t));
59 extern int _stream_memory_get_state __P ((stream_t, enum stream_state *)); 62 extern int _stream_memory_get_state __P ((stream_t, enum stream_state *));
60 extern int _stream_memory_seek __P ((stream_t, off_t, enum stream_whence));
61 extern int _stream_memory_tell __P ((stream_t, off_t *)); 63 extern int _stream_memory_tell __P ((stream_t, off_t *));
64 extern int _stream_memory_is_seekable __P ((stream_t));
62 extern int _stream_memory_is_readready __P ((stream_t, int )); 65 extern int _stream_memory_is_readready __P ((stream_t, int ));
63 extern int _stream_memory_is_writeready __P ((stream_t, int)); 66 extern int _stream_memory_is_writeready __P ((stream_t, int));
64 extern int _stream_memory_is_exceptionpending __P ((stream_t, int)); 67 extern int _stream_memory_is_exceptionpending __P ((stream_t, int));
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_MESSAGE_H 18 #ifndef _MAILUTILS_SYS_MESSAGE_H
19 #define _MAILUTILS_SYS_MESSAGE_H 19 #define _MAILUTILS_SYS_MESSAGE_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/message.h> 25 #include <mailutils/message.h>
22 26
23 #ifndef __P 27 #ifndef __P
......
...@@ -102,6 +102,7 @@ struct _pop3 ...@@ -102,6 +102,7 @@ struct _pop3
102 102
103 enum pop3_state state; 103 enum pop3_state state;
104 stream_t carrier; /* TCP Connection. */ 104 stream_t carrier; /* TCP Connection. */
105 off_t offset; /* To synchronise with the buffering. */
105 mu_debug_t debug; /* Send the debug info. */ 106 mu_debug_t debug; /* Send the debug info. */
106 }; 107 };
107 108
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_PTICKET_H 18 #ifndef _MAILUTILS_SYS_PTICKET_H
19 #define _MAILUTILS_SYS_PTICKET_H 19 #define _MAILUTILS_SYS_PTICKET_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/sys/ticket.h> 25 #include <mailutils/sys/ticket.h>
22 26
23 #ifdef __cplusplus 27 #ifdef __cplusplus
...@@ -31,7 +35,7 @@ struct _ticket_prompt ...@@ -31,7 +35,7 @@ struct _ticket_prompt
31 }; 35 };
32 36
33 extern int _ticket_prompt_ctor __P ((struct _ticket_prompt *)); 37 extern int _ticket_prompt_ctor __P ((struct _ticket_prompt *));
34 extern void _ticket_prompt_dtor __P ((struct _ticket_prompt *)); 38 extern void _ticket_prompt_dtor __P ((ticket_t));
35 extern int _ticket_prompt_ref __P ((ticket_t)); 39 extern int _ticket_prompt_ref __P ((ticket_t));
36 extern void _ticket_prompt_destroy __P ((ticket_t *)); 40 extern void _ticket_prompt_destroy __P ((ticket_t *));
37 extern int _ticket_prompt_pop __P ((ticket_t, const char *, char **)); 41 extern int _ticket_prompt_pop __P ((ticket_t, const char *, char **));
......
...@@ -34,12 +34,13 @@ struct _mu_debug_stream ...@@ -34,12 +34,13 @@ struct _mu_debug_stream
34 struct _mu_debug base; 34 struct _mu_debug base;
35 mu_refcount_t refcount; 35 mu_refcount_t refcount;
36 int level; 36 int level;
37 off_t offset;
37 stream_t stream; 38 stream_t stream;
38 int close_on_destroy; 39 int close_on_destroy;
39 }; 40 };
40 41
41 int _mu_debug_stream_ctor __P ((struct _mu_debug_stream *)); 42 int _mu_debug_stream_ctor __P ((struct _mu_debug_stream *));
42 int _mu_debug_stream_dtor __P ((struct _mu_debug_stream *)); 43 int _mu_debug_stream_dtor __P ((mu_debug_t));
43 int _mu_debug_stream_ref __P ((mu_debug_t)); 44 int _mu_debug_stream_ref __P ((mu_debug_t));
44 void _mu_debug_stream_destroy __P ((mu_debug_t *)); 45 void _mu_debug_stream_destroy __P ((mu_debug_t *));
45 int _mu_debug_stream_set_level __P ((mu_debug_t, size_t)); 46 int _mu_debug_stream_set_level __P ((mu_debug_t, size_t));
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef _MAILUTILS_SYS_STREAM_H 18 #ifndef _MAILUTILS_SYS_STREAM_H
19 #define _MAILUTILS_SYS_STREAM_H 19 #define _MAILUTILS_SYS_STREAM_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/stream.h> 25 #include <mailutils/stream.h>
22 26
23 #ifdef __cplusplus 27 #ifdef __cplusplus
...@@ -32,11 +36,10 @@ struct _stream_vtable ...@@ -32,11 +36,10 @@ struct _stream_vtable
32 int (*open) __P ((stream_t, const char *, int, int)); 36 int (*open) __P ((stream_t, const char *, int, int));
33 int (*close) __P ((stream_t)); 37 int (*close) __P ((stream_t));
34 38
35 int (*read) __P ((stream_t, void *, size_t, size_t *)); 39 int (*read) __P ((stream_t, void *, size_t, off_t, size_t *));
36 int (*readline) __P ((stream_t, char *, size_t, size_t *)); 40 int (*readline) __P ((stream_t, char *, size_t, off_t, size_t *));
37 int (*write) __P ((stream_t, const void *, size_t, size_t *)); 41 int (*write) __P ((stream_t, const void *, size_t, off_t, size_t *));
38 42
39 int (*seek) __P ((stream_t, off_t, enum stream_whence));
40 int (*tell) __P ((stream_t, off_t *)); 43 int (*tell) __P ((stream_t, off_t *));
41 44
42 int (*get_size) __P ((stream_t, off_t *)); 45 int (*get_size) __P ((stream_t, off_t *));
...@@ -47,6 +50,7 @@ struct _stream_vtable ...@@ -47,6 +50,7 @@ struct _stream_vtable
47 int (*get_flags) __P ((stream_t, int *)); 50 int (*get_flags) __P ((stream_t, int *));
48 int (*get_state) __P ((stream_t, enum stream_state *)); 51 int (*get_state) __P ((stream_t, enum stream_state *));
49 52
53 int (*is_seekable) __P ((stream_t));
50 int (*is_readready) __P ((stream_t, int)); 54 int (*is_readready) __P ((stream_t, int));
51 int (*is_writeready) __P ((stream_t, int)); 55 int (*is_writeready) __P ((stream_t, int));
52 int (*is_exceptionpending) __P ((stream_t, int)); 56 int (*is_exceptionpending) __P ((stream_t, int));
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
18 #ifndef MAILUTILS_SYS_TCP_H 18 #ifndef MAILUTILS_SYS_TCP_H
19 #define MAILUTILS_SYS_TCP_H 19 #define MAILUTILS_SYS_TCP_H
20 20
21 #ifdef DMALLOC
22 # include <dmalloc.h>
23 #endif
24
21 #include <mailutils/refcount.h> 25 #include <mailutils/refcount.h>
22 #include <mailutils/sys/fdstream.h> 26 #include <mailutils/sys/fdstream.h>
23 27
......
...@@ -171,7 +171,7 @@ mu_list_remove (mu_list_t list, void *item) ...@@ -171,7 +171,7 @@ mu_list_remove (mu_list_t list, void *item)
171 } 171 }
172 172
173 int 173 int
174 mu_list_get (mu_list_t list, size_t index, void **pitem) 174 mu_list_get (mu_list_t list, size_t indx, void **pitem)
175 { 175 {
176 struct mu_list_data *current; 176 struct mu_list_data *current;
177 size_t count; 177 size_t count;
...@@ -182,7 +182,7 @@ mu_list_get (mu_list_t list, size_t index, void **pitem) ...@@ -182,7 +182,7 @@ mu_list_get (mu_list_t list, size_t index, void **pitem)
182 for (current = list->head.next, count = 0; current != &(list->head); 182 for (current = list->head.next, count = 0; current != &(list->head);
183 current = current->next, count++) 183 current = current->next, count++)
184 { 184 {
185 if (count == index) 185 if (count == indx)
186 { 186 {
187 *pitem = current->item; 187 *pitem = current->item;
188 status = 0; 188 status = 0;
......
...@@ -59,7 +59,8 @@ _stream_mmap_destroy (stream_t *pstream) ...@@ -59,7 +59,8 @@ _stream_mmap_destroy (stream_t *pstream)
59 } 59 }
60 60
61 int 61 int
62 _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) 62 _stream_mmap_read (stream_t stream, void *optr, size_t osize,
63 off_t offset, size_t *nbytes)
63 { 64 {
64 struct _stream_mmap *ms = (struct _stream_mmap *)stream; 65 struct _stream_mmap *ms = (struct _stream_mmap *)stream;
65 size_t n = 0; 66 size_t n = 0;
...@@ -67,12 +68,10 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) ...@@ -67,12 +68,10 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
67 mu_refcount_lock (ms->refcount); 68 mu_refcount_lock (ms->refcount);
68 if (ms->ptr != MAP_FAILED && ms->ptr) 69 if (ms->ptr != MAP_FAILED && ms->ptr)
69 { 70 {
70 if (ms->offset < (off_t)ms->size) 71 if (offset < (off_t)ms->size)
71 { 72 {
72 n = ((ms->offset + osize) > ms->size) ? 73 n = ((offset + osize) > ms->size) ? ms->size - offset : osize;
73 ms->size - ms->offset : osize; 74 memcpy (optr, ms->ptr + offset, n);
74 memcpy (optr, ms->ptr + ms->offset, n);
75 ms->offset += n;
76 } 75 }
77 } 76 }
78 mu_refcount_unlock (ms->refcount); 77 mu_refcount_unlock (ms->refcount);
...@@ -83,7 +82,8 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) ...@@ -83,7 +82,8 @@ _stream_mmap_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
83 } 82 }
84 83
85 int 84 int
86 _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes) 85 _stream_mmap_readline (stream_t stream, char *optr, size_t osize,
86 off_t offset, size_t *nbytes)
87 { 87 {
88 struct _stream_mmap *ms = (struct _stream_mmap *)stream; 88 struct _stream_mmap *ms = (struct _stream_mmap *)stream;
89 size_t n = 0; 89 size_t n = 0;
...@@ -91,17 +91,17 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes ...@@ -91,17 +91,17 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes
91 mu_refcount_lock (ms->refcount); 91 mu_refcount_lock (ms->refcount);
92 if (ms->ptr != MAP_FAILED && ms->ptr) 92 if (ms->ptr != MAP_FAILED && ms->ptr)
93 { 93 {
94 if (ms->offset < (off_t)ms->size) 94 if (offset < (off_t)ms->size)
95 { 95 {
96 /* Save space for the null byte. */ 96 /* Save space for the null byte. */
97 char *nl; 97 char *nl;
98 osize--; 98 osize--;
99 nl = memchr (ms->ptr + ms->offset, '\n', ms->size - ms->offset); 99 nl = memchr (ms->ptr + offset, '\n', ms->size - offset);
100 n = (nl) ? nl - (ms->ptr + ms->offset) + 1 : ms->size - ms->offset; 100 n = (nl) ? (size_t)(nl - (ms->ptr + offset) + 1) : ms->size - offset;
101 n = (n > osize) ? osize : n; 101 n = (n > osize) ? osize : n;
102 memcpy (optr, ms->ptr + ms->offset, n); 102 memcpy (optr, ms->ptr + offset, n);
103 optr[n] = '\0'; 103 optr[n] = '\0';
104 ms->offset += n; 104 offset += n;
105 } 105 }
106 } 106 }
107 mu_refcount_unlock (ms->refcount); 107 mu_refcount_unlock (ms->refcount);
...@@ -112,7 +112,8 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes ...@@ -112,7 +112,8 @@ _stream_mmap_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes
112 } 112 }
113 113
114 int 114 int
115 _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nbytes) 115 _stream_mmap_write (stream_t stream, const void *iptr, size_t isize,
116 off_t offset, size_t *nbytes)
116 { 117 {
117 struct _stream_mmap *ms = (struct _stream_mmap *)stream; 118 struct _stream_mmap *ms = (struct _stream_mmap *)stream;
118 int err = 0; 119 int err = 0;
...@@ -122,17 +123,17 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby ...@@ -122,17 +123,17 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby
122 if (ms->mflags & PROT_WRITE) 123 if (ms->mflags & PROT_WRITE)
123 { 124 {
124 /* Bigger we have to remmap. */ 125 /* Bigger we have to remmap. */
125 if (ms->size < (ms->offset + isize)) 126 if (ms->size < (offset + isize))
126 { 127 {
127 if (ms->ptr != MAP_FAILED && munmap (ms->ptr, ms->size) == 0) 128 if (ms->ptr != MAP_FAILED && munmap (ms->ptr, ms->size) == 0)
128 { 129 {
129 ms->ptr = MAP_FAILED; 130 ms->ptr = MAP_FAILED;
130 if (ftruncate (ms->fd, ms->offset + isize) == 0) 131 if (ftruncate (ms->fd, offset + isize) == 0)
131 { 132 {
132 ms->ptr = mmap (0, ms->offset + isize, ms->mflags, 133 ms->ptr = mmap (0, offset + isize, ms->mflags,
133 MAP_SHARED, ms->fd, 0); 134 MAP_SHARED, ms->fd, 0);
134 if (ms->ptr != MAP_FAILED) 135 if (ms->ptr != MAP_FAILED)
135 ms->size = ms->offset + isize; 136 ms->size = offset + isize;
136 } 137 }
137 } 138 }
138 } 139 }
...@@ -140,8 +141,7 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby ...@@ -140,8 +141,7 @@ _stream_mmap_write (stream_t stream, const void *iptr, size_t isize, size_t *nby
140 if (ms->ptr != MAP_FAILED) 141 if (ms->ptr != MAP_FAILED)
141 { 142 {
142 if (isize > 0) 143 if (isize > 0)
143 memcpy (ms->ptr + ms->offset, iptr, isize); 144 memcpy (ms->ptr + offset, iptr, isize);
144 ms->offset += isize;
145 n = isize; 145 n = isize;
146 } 146 }
147 else 147 else
...@@ -274,38 +274,26 @@ _stream_mmap_get_state (stream_t stream, enum stream_state *state) ...@@ -274,38 +274,26 @@ _stream_mmap_get_state (stream_t stream, enum stream_state *state)
274 } 274 }
275 275
276 int 276 int
277 _stream_mmap_seek (stream_t stream, off_t off, enum stream_whence whence) 277 _stream_mmap_is_seekable (stream_t stream)
278 { 278 {
279 struct _stream_mmap *ms = (struct _stream_mmap *)stream; 279 off_t off;
280 off_t noff = ms->offset; 280 return _stream_mmap_tell (stream, &off) == 0;
281 int err = 0;
282 if (whence == MU_STREAM_WHENCE_SET)
283 noff = off;
284 else if (whence == MU_STREAM_WHENCE_CUR)
285 noff += off;
286 else if (whence == MU_STREAM_WHENCE_END)
287 noff = ms->size + off;
288 else
289 noff = -1; /* error. */
290 if (noff >= 0)
291 {
292 if (noff > ms->offset)
293 _stream_mmap_truncate (stream, noff);
294 ms->offset = noff;
295 }
296 else
297 err = MU_ERROR_INVALID_PARAMETER;
298 return err;
299 } 281 }
300 282
301 int 283 int
302 _stream_mmap_tell (stream_t stream, off_t *off) 284 _stream_mmap_tell (stream_t stream, off_t *off)
303 { 285 {
304 struct _stream_mmap *ms = (struct _stream_mmap *)stream; 286 struct _stream_mmap *ms = (struct _stream_mmap *)stream;
287 int status = 0;
305 if (off == NULL) 288 if (off == NULL)
306 return MU_ERROR_INVALID_PARAMETER; 289 return MU_ERROR_INVALID_PARAMETER;
307 *off = ms->offset; 290 *off = lseek (ms->fd, 0, SEEK_SET);
308 return 0; 291 if (*off == -1)
292 {
293 status = errno;
294 *off = 0;
295 }
296 return status;
309 } 297 }
310 298
311 int 299 int
...@@ -451,7 +439,6 @@ static struct _stream_vtable _stream_mmap_vtable = ...@@ -451,7 +439,6 @@ static struct _stream_vtable _stream_mmap_vtable =
451 _stream_mmap_readline, 439 _stream_mmap_readline,
452 _stream_mmap_write, 440 _stream_mmap_write,
453 441
454 _stream_mmap_seek,
455 _stream_mmap_tell, 442 _stream_mmap_tell,
456 443
457 _stream_mmap_get_size, 444 _stream_mmap_get_size,
...@@ -462,6 +449,7 @@ static struct _stream_vtable _stream_mmap_vtable = ...@@ -462,6 +449,7 @@ static struct _stream_vtable _stream_mmap_vtable =
462 _stream_mmap_get_flags, 449 _stream_mmap_get_flags,
463 _stream_mmap_get_state, 450 _stream_mmap_get_state,
464 451
452 _stream_mmap_is_seekable,
465 _stream_mmap_is_readready, 453 _stream_mmap_is_readready,
466 _stream_mmap_is_writeready, 454 _stream_mmap_is_writeready,
467 _stream_mmap_is_exceptionpending, 455 _stream_mmap_is_exceptionpending,
...@@ -476,7 +464,6 @@ _stream_mmap_ctor (struct _stream_mmap *ms) ...@@ -476,7 +464,6 @@ _stream_mmap_ctor (struct _stream_mmap *ms)
476 if (ms->refcount == NULL) 464 if (ms->refcount == NULL)
477 return MU_ERROR_NO_MEMORY; 465 return MU_ERROR_NO_MEMORY;
478 ms->fd = -1; 466 ms->fd = -1;
479 ms->offset = -1;
480 ms->flags = 0; 467 ms->flags = 0;
481 ms->mflags = 0; 468 ms->mflags = 0;
482 ms->base.vtable = &_stream_mmap_vtable; 469 ms->base.vtable = &_stream_mmap_vtable;
...@@ -484,13 +471,16 @@ _stream_mmap_ctor (struct _stream_mmap *ms) ...@@ -484,13 +471,16 @@ _stream_mmap_ctor (struct _stream_mmap *ms)
484 } 471 }
485 472
486 void 473 void
487 _stream_mmap_dtor (struct _stream_mmap *ms) 474 _stream_mmap_dtor (stream_t stream)
488 { 475 {
476 struct _stream_mmap *ms = (struct _stream_mmap *)stream;
477 if (ms)
478 {
489 mu_refcount_destroy (&ms->refcount); 479 mu_refcount_destroy (&ms->refcount);
490 ms->fd = -1; 480 ms->fd = -1;
491 ms->offset = -1;
492 ms->mflags = 0; 481 ms->mflags = 0;
493 ms->ptr = MAP_FAILED; 482 ms->ptr = MAP_FAILED;
483 }
494 } 484 }
495 485
496 #endif /* _POSIX_MAPPED_FILES */ 486 #endif /* _POSIX_MAPPED_FILES */
......
...@@ -16,15 +16,16 @@ libmbox_la_SOURCES = \ ...@@ -16,15 +16,16 @@ libmbox_la_SOURCES = \
16 mbox_bstream.c \ 16 mbox_bstream.c \
17 mbox_carrier.c \ 17 mbox_carrier.c \
18 mbox_cb.c \ 18 mbox_cb.c \
19 mbox_newmail.c \
20 mbox_close.c \ 19 mbox_close.c \
21 mbox_create.c \ 20 mbox_create.c \
21 mbox_debug.c \
22 mbox_destroy.c \ 22 mbox_destroy.c \
23 mbox_expunge.c \ 23 mbox_expunge.c \
24 mbox_hcache.c \ 24 mbox_hcache.c \
25 mbox_hlines.c \ 25 mbox_hlines.c \
26 mbox_hsize.c \ 26 mbox_hsize.c \
27 mbox_hstream.c \ 27 mbox_hstream.c \
28 mbox_newmail.c \
28 mbox_open.c \ 29 mbox_open.c \
29 mbox_scan.c \ 30 mbox_scan.c \
30 mbox_separator.c \ 31 mbox_separator.c \
......
...@@ -94,7 +94,10 @@ ...@@ -94,7 +94,10 @@
94 - Refuse to append if the mailbox is change on disk. 94 - Refuse to append if the mailbox is change on disk.
95 */ 95 */
96 96
97 /* Assuming that the file is lock. */ 97 /* Assuming that the file is lock:
98 Add the unix separtor the form is:
99 From user cdate_format\n
100 */
98 static int 101 static int
99 mbox_append_separator (mbox_t mbox, const char *sep) 102 mbox_append_separator (mbox_t mbox, const char *sep)
100 { 103 {
...@@ -123,93 +126,102 @@ mbox_append_separator (mbox_t mbox, const char *sep) ...@@ -123,93 +126,102 @@ mbox_append_separator (mbox_t mbox, const char *sep)
123 len = strlen (sep); 126 len = strlen (sep);
124 127
125 /* Write the separator. */ 128 /* Write the separator. */
126 status = stream_write (mbox->carrier, sep, len, NULL); 129 status = stream_write (mbox->carrier, sep, len, mbox->woffset, &len);
127 if (status != 0) 130 if (status != 0)
128 return status; 131 return status;
132 mbox->woffset += len;
129 133
130 /* Add the trailing newline. */ 134 /* Add the trailing newline. */
131 if (len && sep[len - 1] != '\n') 135 if (len && sep[len - 1] != '\n')
132 status = stream_write (mbox->carrier, &nl, 1, NULL); 136 {
137 status = stream_write (mbox->carrier, &nl, 1, mbox->woffset, &len);
138 if (status != 0)
139 return status;
140 mbox->woffset += len;
141 }
133 return status; 142 return status;
134 } 143 }
135 144
136 /* Assuming that the file is lock. */ 145 /* Assuming that the file is lock.
146 Strip away Content-Length in the header add add the separating
147 newline between the header and the body.
148 */
137 static int 149 static int
138 mbox_append_header (mbox_t mbox, attribute_t attribute, int save_uidvalidity, 150 mbox_append_header (mbox_t mbox, attribute_t attribute, stream_t hstream,
139 stream_t hstream) 151 int save_uidvalidity, unsigned long uid)
140 { 152 {
141 char buffer[1024]; 153 char buf[1024];
154 size_t n = 0;
142 size_t nread = 0; 155 size_t nread = 0;
143 int status = 0; 156 int status = 0;
144 const char nl = '\n'; 157 const char nl = '\n';
145 158
146 do 159 do
147 { 160 {
148 status = stream_readline (hstream, buffer, sizeof buffer, &nread); 161 status = stream_readline (hstream, buf, sizeof buf, mbox->roffset, &nread);
149 if (status != 0) 162 if (status != 0)
150 return status; 163 return status;
151 164
165 mbox->roffset += nread;
166
152 /* A newline means the start of the body. */ 167 /* A newline means the start of the body. */
153 if (*buffer == '\n') 168 if (*buf == '\n')
154 break; 169 break;
155 170
156 if (IS_X_IMAPBASE (buffer)) 171 /* Skip X-IMAPBase it has special meaning for us. */
157 { 172 /* Skip X-UID. A new one will be provided. */
158 /* Skip the X-IMAPBase it has special meaning for us. */ 173 /* Skip Status, use the attribute. */
174 /* Skip Content-Length, too often bad. */
175 if (IS_X_IMAPBASE (buf) || IS_X_UID (buf)
176 || IS_STATUS (buf) || IS_CONTENT_LENGTH (buf))
159 continue; 177 continue;
160 }
161 else if (IS_X_UID (buffer))
162 {
163 /* Skip the X-UID. A new one will be provided. */
164 continue;
165 }
166 else if (IS_STATUS (buffer))
167 {
168 /* Skip, use the attribute. */
169 continue;
170 }
171 else if (IS_CONTENT_LENGTH (buffer))
172 {
173 /* Ignore this, too often bad. */
174 continue;
175 }
176 178
177 status = stream_write (mbox->carrier, buffer, nread, NULL); 179 status = stream_write (mbox->carrier, buf, nread, mbox->woffset, &n);
178 if (status != 0) 180 if (status != 0)
179 return status; 181 return status;
182 mbox->woffset += n;
180 } 183 }
181 while (nread > 0); 184 while (nread > 0);
182 185
183 /* Rewrite the X-IMAPbase marker If necesary. */ 186 /* Rewrite the X-IMAPbase, if necesary, and only for the first msg. */
184 if (mbox->uidnext < 2 && save_uidvalidity) 187 if (mbox->uidnext < 2 && save_uidvalidity)
185 { 188 {
186 nread = snprintf (buffer, sizeof buffer, "X-IMAPbase: %lu %lu\n", 189 n = snprintf (buf, sizeof buf, "X-IMAPbase: %lu %lu\n",
187 mbox->uidvalidity, mbox->uidnext); 190 mbox->uidvalidity, mbox->uidnext);
188 status = stream_write (mbox->carrier, buffer, nread, NULL); 191 status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
189 if (status != 0) 192 if (status != 0)
190 return status; 193 return status;
194 mbox->woffset += n;
191 } 195 }
192 196
193 /* Rewrite the Status for the attribute. */ 197 /* Rewrite the Status for the attribute. */
194 if (attribute) 198 if (attribute)
195 { 199 {
196 mbox_attribute_to_status (attribute, buffer, sizeof buffer, &nread); 200 mbox_attribute_to_status (attribute, buf, sizeof buf, &n);
197 status = stream_write (mbox->carrier, buffer, nread, NULL); 201 status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
198 if (status != 0) 202 if (status != 0)
199 return status; 203 return status;
204 mbox->woffset += n;
200 } 205 }
201 206
202 /* Rewrite the X-UID marker . */ 207 /* Rewrite the X-UID marker . */
203 nread = snprintf (buffer, sizeof buffer, "X-UID: %lu\n", mbox->uidnext); 208 n = snprintf (buf, sizeof buf, "X-UID: %lu\n", (uid) ? uid : mbox->uidnext);
204 status = stream_write (mbox->carrier, buffer, nread, NULL); 209 status = stream_write (mbox->carrier, buf, n, mbox->woffset, &n);
205 if (status != 0) 210 if (status != 0)
206 return status; 211 return status;
212 mbox->woffset += n;
207 213
208 /* New line separator of the Header. */ 214 /* New line separator of the Header. */
209 return stream_write (mbox->carrier, &nl , 1, NULL); 215 status = stream_write (mbox->carrier, &nl , 1, mbox->woffset, &n);
216 if (status != 0)
217 return status;
218 mbox->woffset += n;
219 return status;
210 } 220 }
211 221
212 /* Assuming that the file is lock. */ 222 /* Assuming that the file is lock.
223 Do the mangling, line startin with "From " is mangle to ">From "
224 */
213 static int 225 static int
214 mbox_append_body (mbox_t mbox, stream_t bstream) 226 mbox_append_body (mbox_t mbox, stream_t bstream)
215 { 227 {
...@@ -219,6 +231,7 @@ mbox_append_body (mbox_t mbox, stream_t bstream) ...@@ -219,6 +231,7 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
219 size_t nread = 0; 231 size_t nread = 0;
220 const char nl = '\n'; 232 const char nl = '\n';
221 int status; 233 int status;
234 size_t n = 0;
222 235
223 /* For "From " mangling. */ 236 /* For "From " mangling. */
224 *buffer = '>'; 237 *buffer = '>';
...@@ -226,9 +239,11 @@ mbox_append_body (mbox_t mbox, stream_t bstream) ...@@ -226,9 +239,11 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
226 do 239 do
227 { 240 {
228 buf = buffer + 1; 241 buf = buffer + 1;
229 status = stream_readline (bstream, buf, sizeof (buffer) - 1, &nread); 242 status = stream_readline (bstream, buf, sizeof (buffer) - 1,
243 mbox->roffset, &nread);
230 if (status != 0) 244 if (status != 0)
231 return status; 245 return status;
246 mbox->roffset += nread;
232 247
233 /* Unix Mbox: 248 /* Unix Mbox:
234 Since it's possibpe for a message to contain lines that looks 249 Since it's possibpe for a message to contain lines that looks
...@@ -252,9 +267,10 @@ mbox_append_body (mbox_t mbox, stream_t bstream) ...@@ -252,9 +267,10 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
252 nread++; 267 nread++;
253 } 268 }
254 } 269 }
255 status = stream_write (mbox->carrier, buf, nread, NULL); 270 status = stream_write (mbox->carrier, buf, nread, mbox->woffset, &n);
256 if (status != 0) 271 if (status != 0)
257 return status ; 272 return status ;
273 mbox->woffset += n;
258 274
259 /* Register if we read a complete line. */ 275 /* Register if we read a complete line. */
260 was_complete_line = (nread && buf[nread - 1] == '\n') ? 1 : 0; 276 was_complete_line = (nread && buf[nread - 1] == '\n') ? 1 : 0;
...@@ -262,15 +278,22 @@ mbox_append_body (mbox_t mbox, stream_t bstream) ...@@ -262,15 +278,22 @@ mbox_append_body (mbox_t mbox, stream_t bstream)
262 while (nread > 0); 278 while (nread > 0);
263 279
264 /* New line separator for the next message. */ 280 /* New line separator for the next message. */
265 return stream_write (mbox->carrier, &nl, 1, NULL); 281 status = stream_write (mbox->carrier, &nl, 1, mbox->woffset, &n);
282 if (status != 0)
283 return status;
284 mbox->woffset += n;
285 return status;
266 } 286 }
267 287
268 int 288 int
269 mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, 289 mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
270 int save_uidvalidity, stream_t hstream, stream_t bstream) 290 stream_t hstream, stream_t bstream,
291 int save_uidvalidity, unsigned long uid)
271 { 292 {
272 int status = 0; 293 int status = 0;
273 294
295 mbox_debug_print (mbox, "append_hb0(uid=%lu)", uid);
296
274 if (mbox == NULL || hstream == NULL || bstream == NULL) 297 if (mbox == NULL || hstream == NULL || bstream == NULL)
275 return MU_ERROR_INVALID_PARAMETER; 298 return MU_ERROR_INVALID_PARAMETER;
276 299
...@@ -278,7 +301,6 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -278,7 +301,6 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
278 { 301 {
279 case MU_MBOX_NO_STATE: 302 case MU_MBOX_NO_STATE:
280 { 303 {
281 off_t size = 0;
282 unsigned long uidvalidity; 304 unsigned long uidvalidity;
283 unsigned long uidnext; 305 unsigned long uidnext;
284 306
...@@ -291,10 +313,10 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -291,10 +313,10 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
291 if (status != 0) 313 if (status != 0)
292 break; 314 break;
293 315
316 mbox->woffset = mbox->roffset = 0;
294 /* Move to the end of the stream. */ 317 /* Move to the end of the stream. */
295 if ((status = stream_get_size (mbox->carrier, &size)) != 0 318 status = stream_get_size (mbox->carrier, &mbox->woffset);
296 || (status = stream_seek (mbox->carrier, size, 319 if (status != 0)
297 MU_STREAM_WHENCE_SET) != 0))
298 break; 320 break;
299 mbox->state = MU_MBOX_STATE_APPEND_SEPARATOR; 321 mbox->state = MU_MBOX_STATE_APPEND_SEPARATOR;
300 } 322 }
...@@ -309,7 +331,8 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -309,7 +331,8 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
309 331
310 case MU_MBOX_STATE_APPEND_HEADER: 332 case MU_MBOX_STATE_APPEND_HEADER:
311 { 333 {
312 status = mbox_append_header (mbox, attribute, save_uidvalidity, hstream); 334 status = mbox_append_header (mbox, attribute, hstream,
335 save_uidvalidity, uid);
313 if (status != 0) 336 if (status != 0)
314 break; 337 break;
315 mbox->state = MU_MBOX_STATE_APPEND_BODY; 338 mbox->state = MU_MBOX_STATE_APPEND_BODY;
...@@ -317,6 +340,9 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -317,6 +340,9 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
317 340
318 case MU_MBOX_STATE_APPEND_BODY: 341 case MU_MBOX_STATE_APPEND_BODY:
319 { 342 {
343 /* Hack it the same stream. do not reset the mbox->roffset. */
344 if (hstream != bstream)
345 mbox->roffset = 0;
320 status = mbox_append_body (mbox, bstream); 346 status = mbox_append_body (mbox, bstream);
321 if (status != 0) 347 if (status != 0)
322 break; 348 break;
...@@ -324,6 +350,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -324,6 +350,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
324 } 350 }
325 351
326 default: 352 default:
353 mbox->woffset = mbox->roffset = 0;
327 break; 354 break;
328 } 355 }
329 356
...@@ -333,6 +360,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -333,6 +360,7 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
333 if (status != MU_ERROR_TRY_AGAIN) 360 if (status != MU_ERROR_TRY_AGAIN)
334 { 361 {
335 mbox->state = MU_MBOX_NO_STATE; 362 mbox->state = MU_MBOX_NO_STATE;
363 mbox->woffset = mbox->roffset = 0;
336 lockfile_unlock (mbox->lockfile); 364 lockfile_unlock (mbox->lockfile);
337 } 365 }
338 } 366 }
...@@ -347,15 +375,15 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute, ...@@ -347,15 +375,15 @@ mbox_append_hb0 (mbox_t mbox, const char *sep, attribute_t attribute,
347 } 375 }
348 376
349 int 377 int
350 mbox_append (mbox_t mbox, const char *sep, attribute_t attribute, 378 mbox_append_hb (mbox_t mbox, const char *sep, attribute_t attribute,
351 stream_t stream) 379 stream_t hstream, stream_t bstream)
352 { 380 {
353 return mbox_append_hb (mbox, sep, attribute, stream, stream); 381 return mbox_append_hb0 (mbox, sep, attribute, hstream, bstream, 1, 0);
354 } 382 }
355 383
356 int 384 int
357 mbox_append_hb (mbox_t mbox, const char *sep, attribute_t attribute, 385 mbox_append (mbox_t mbox, const char *sep, attribute_t attribute,
358 stream_t hstream, stream_t bstream) 386 stream_t stream)
359 { 387 {
360 return mbox_append_hb0 (mbox, sep, attribute, 1, hstream, bstream); 388 return mbox_append_hb (mbox, sep, attribute, stream, stream);
361 } 389 }
......
...@@ -48,14 +48,15 @@ _attribute_mbox_destroy (attribute_t *pattribute) ...@@ -48,14 +48,15 @@ _attribute_mbox_destroy (attribute_t *pattribute)
48 struct _attribute_mbox *ma = (struct _attribute_mbox *)*pattribute; 48 struct _attribute_mbox *ma = (struct _attribute_mbox *)*pattribute;
49 if (mu_refcount_dec (ma->refcount) == 0) 49 if (mu_refcount_dec (ma->refcount) == 0)
50 { 50 {
51 mu_refcount_destroy (&ma->refcount);
51 if (ma->msgno <= ma->mbox->messages_count) 52 if (ma->msgno <= ma->mbox->messages_count)
52 { 53 {
53 /* If it is the attribute save in the mailbox structure. */ 54 /* If it is the attribute save in the mailbox structure. */
54 if (ma == (struct _attribute_mbox *)(ma->mbox->umessages[ma->msgno - 1]->attribute)) 55 if (ma == (struct _attribute_mbox *)
56 (ma->mbox->umessages[ma->msgno - 1]->attribute))
55 ma->mbox->umessages[ma->msgno - 1]->attribute = NULL; 57 ma->mbox->umessages[ma->msgno - 1]->attribute = NULL;
56 mu_refcount_destroy (&ma->refcount);
57 free (ma);
58 } 58 }
59 free (ma);
59 } 60 }
60 } 61 }
61 62
...@@ -66,10 +67,8 @@ _attribute_mbox_get_flags (attribute_t attribute, int *pflags) ...@@ -66,10 +67,8 @@ _attribute_mbox_get_flags (attribute_t attribute, int *pflags)
66 if (pflags) 67 if (pflags)
67 { 68 {
68 if (ma->msgno <= ma->mbox->messages_count) 69 if (ma->msgno <= ma->mbox->messages_count)
69 {
70 *pflags = ma->mbox->umessages[ma->msgno - 1]->attr_flags; 70 *pflags = ma->mbox->umessages[ma->msgno - 1]->attr_flags;
71 } 71 }
72 }
73 return 0; 72 return 0;
74 } 73 }
75 74
...@@ -78,9 +77,8 @@ _attribute_mbox_set_flags (attribute_t attribute, int flags) ...@@ -78,9 +77,8 @@ _attribute_mbox_set_flags (attribute_t attribute, int flags)
78 { 77 {
79 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute; 78 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
80 if (ma->msgno <= ma->mbox->messages_count) 79 if (ma->msgno <= ma->mbox->messages_count)
81 { 80 ma->mbox->umessages[ma->msgno - 1]->attr_flags |=
82 ma->mbox->umessages[ma->msgno - 1]->attr_flags |= (flags | MU_ATTRIBUTE_MODIFIED); 81 (flags | MU_ATTRIBUTE_MODIFIED);
83 }
84 return 0; 82 return 0;
85 } 83 }
86 84
...@@ -93,7 +91,8 @@ _attribute_mbox_unset_flags (attribute_t attribute, int flags) ...@@ -93,7 +91,8 @@ _attribute_mbox_unset_flags (attribute_t attribute, int flags)
93 ma->mbox->umessages[ma->msgno - 1]->attr_flags &= ~flags; 91 ma->mbox->umessages[ma->msgno - 1]->attr_flags &= ~flags;
94 /* If Modified was being unset do not reset it. */ 92 /* If Modified was being unset do not reset it. */
95 if (!(flags & MU_ATTRIBUTE_MODIFIED)) 93 if (!(flags & MU_ATTRIBUTE_MODIFIED))
96 ma->mbox->umessages[ma->msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED; 94 ma->mbox->umessages[ma->msgno - 1]->attr_flags |=
95 MU_ATTRIBUTE_MODIFIED;
97 } 96 }
98 return 0; 97 return 0;
99 } 98 }
...@@ -103,12 +102,56 @@ _attribute_mbox_clear_flags (attribute_t attribute) ...@@ -103,12 +102,56 @@ _attribute_mbox_clear_flags (attribute_t attribute)
103 { 102 {
104 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute; 103 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
105 if (ma->msgno <= ma->mbox->messages_count) 104 if (ma->msgno <= ma->mbox->messages_count)
106 {
107 ma->mbox->umessages[ma->msgno - 1]->attr_flags = 0; 105 ma->mbox->umessages[ma->msgno - 1]->attr_flags = 0;
106 return 0;
107 }
108
109 static int
110 _attribute_mbox_get_userflags (attribute_t attribute, int *puserflags)
111 {
112 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
113 if (puserflags)
114 {
115 if (ma->msgno <= ma->mbox->messages_count)
116 *puserflags = ma->mbox->umessages[ma->msgno - 1]->attr_userflags;
108 } 117 }
109 return 0; 118 return 0;
110 } 119 }
111 120
121 static int
122 _attribute_mbox_set_userflags (attribute_t attribute, int userflags)
123 {
124 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
125 if (ma->msgno <= ma->mbox->messages_count)
126 ma->mbox->umessages[ma->msgno - 1]->attr_userflags |=
127 (userflags | MU_ATTRIBUTE_MODIFIED);
128 return 0;
129 }
130
131 static int
132 _attribute_mbox_unset_userflags (attribute_t attribute, int userflags)
133 {
134 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
135 if (ma->msgno <= ma->mbox->messages_count)
136 {
137 ma->mbox->umessages[ma->msgno - 1]->attr_userflags &= ~userflags;
138 /* If Modified was being unset do not reset it. */
139 if (!(userflags & MU_ATTRIBUTE_MODIFIED))
140 ma->mbox->umessages[ma->msgno - 1]->attr_userflags |=
141 MU_ATTRIBUTE_MODIFIED;
142 }
143 return 0;
144 }
145
146 static int
147 _attribute_mbox_clear_userflags (attribute_t attribute)
148 {
149 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
150 if (ma->msgno <= ma->mbox->messages_count)
151 ma->mbox->umessages[ma->msgno - 1]->attr_userflags = 0;
152 return 0;
153 }
154
112 static struct _attribute_vtable _attribute_mbox_vtable = 155 static struct _attribute_vtable _attribute_mbox_vtable =
113 { 156 {
114 _attribute_mbox_ref, 157 _attribute_mbox_ref,
...@@ -117,7 +160,12 @@ static struct _attribute_vtable _attribute_mbox_vtable = ...@@ -117,7 +160,12 @@ static struct _attribute_vtable _attribute_mbox_vtable =
117 _attribute_mbox_get_flags, 160 _attribute_mbox_get_flags,
118 _attribute_mbox_set_flags, 161 _attribute_mbox_set_flags,
119 _attribute_mbox_unset_flags, 162 _attribute_mbox_unset_flags,
120 _attribute_mbox_clear_flags 163 _attribute_mbox_clear_flags,
164
165 _attribute_mbox_get_userflags,
166 _attribute_mbox_set_userflags,
167 _attribute_mbox_unset_userflags,
168 _attribute_mbox_clear_userflags
121 }; 169 };
122 170
123 static int 171 static int
...@@ -133,12 +181,19 @@ _attribute_mbox_ctor (struct _attribute_mbox *ma, mbox_t mbox, ...@@ -133,12 +181,19 @@ _attribute_mbox_ctor (struct _attribute_mbox *ma, mbox_t mbox,
133 return 0; 181 return 0;
134 } 182 }
135 183
136 /* 184 void
137 static int 185 _attribute_mbox_dtor (attribute_t attribute)
138 _attribute_mbox_dtor (struct _attribute_mbox *ma)
139 { 186 {
187 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
188 mu_refcount_destroy (&ma->refcount);
189 if (ma->msgno <= ma->mbox->messages_count)
190 {
191 /* If it is the attribute save in the mailbox structure. */
192 if (ma == (struct _attribute_mbox *)
193 (ma->mbox->umessages[ma->msgno - 1]->attribute))
194 ma->mbox->umessages[ma->msgno - 1]->attribute = NULL;
195 }
140 } 196 }
141 */
142 197
143 int 198 int
144 attribute_mbox_create (attribute_t *pattribute, mbox_t mbox, 199 attribute_mbox_create (attribute_t *pattribute, mbox_t mbox,
...@@ -162,9 +217,21 @@ attribute_mbox_create (attribute_t *pattribute, mbox_t mbox, ...@@ -162,9 +217,21 @@ attribute_mbox_create (attribute_t *pattribute, mbox_t mbox,
162 } 217 }
163 218
164 int 219 int
220 attribute_mbox_msgno (attribute_t attribute, unsigned int msgno)
221 {
222 struct _attribute_mbox *ma = (struct _attribute_mbox *)attribute;
223 if (ma)
224 ma->msgno = msgno;
225 return 0;
226 }
227
228 int
165 mbox_get_attribute (mbox_t mbox, unsigned int msgno, attribute_t *pattribute) 229 mbox_get_attribute (mbox_t mbox, unsigned int msgno, attribute_t *pattribute)
166 { 230 {
167 int status = 0; 231 int status = 0;
232
233 mbox_debug_print (mbox, "attribute(%d)", msgno);
234
168 if (mbox == NULL || msgno == 0 || pattribute == NULL) 235 if (mbox == NULL || msgno == 0 || pattribute == NULL)
169 return MU_ERROR_INVALID_PARAMETER; 236 return MU_ERROR_INVALID_PARAMETER;
170 237
...@@ -198,16 +265,18 @@ mbox_attribute_to_status (attribute_t attribute, char *buf, size_t buflen, ...@@ -198,16 +265,18 @@ mbox_attribute_to_status (attribute_t attribute, char *buf, size_t buflen,
198 265
199 if (attribute) 266 if (attribute)
200 { 267 {
201 if (attribute_is_read (attribute))
202 strcat (a, "R");
203 if (attribute_is_seen (attribute)) 268 if (attribute_is_seen (attribute))
204 strcat (a, "O"); 269 strcat (a, "O");
270 if (attribute_is_read (attribute))
271 strcat (a, "R");
205 if (attribute_is_answered (attribute)) 272 if (attribute_is_answered (attribute))
206 strcat (a, "A"); 273 strcat (a, "A");
207 if (attribute_is_deleted (attribute)) 274 if (attribute_is_deleted (attribute))
208 strcat (a, "d"); 275 strcat (a, "d");
209 if (attribute_is_flagged (attribute)) 276 if (attribute_is_flagged (attribute))
210 strcat (a, "F"); 277 strcat (a, "F");
278 if (attribute_is_draft (attribute))
279 strcat (a, "T");
211 } 280 }
212 281
213 if (*a != '\0') 282 if (*a != '\0')
......
...@@ -27,6 +27,7 @@ int ...@@ -27,6 +27,7 @@ int
27 mbox_get_blines (mbox_t mbox, unsigned int msgno, unsigned int *plines) 27 mbox_get_blines (mbox_t mbox, unsigned int msgno, unsigned int *plines)
28 { 28 {
29 unsigned int lines = 0; 29 unsigned int lines = 0;
30 mbox_debug_print (mbox, "get_blines(%u)", msgno);
30 if (mbox && msgno) 31 if (mbox && msgno)
31 { 32 {
32 msgno--; 33 msgno--;
......
...@@ -27,6 +27,7 @@ int ...@@ -27,6 +27,7 @@ int
27 mbox_get_bsize (mbox_t mbox, unsigned int msgno, unsigned int *psize) 27 mbox_get_bsize (mbox_t mbox, unsigned int msgno, unsigned int *psize)
28 { 28 {
29 unsigned int size = 0; 29 unsigned int size = 0;
30 mbox_debug_print (mbox, "get_bsize(%u)", msgno);
30 if (mbox && msgno) 31 if (mbox && msgno)
31 { 32 {
32 msgno--; 33 msgno--;
......
...@@ -28,6 +28,8 @@ int ...@@ -28,6 +28,8 @@ int
28 mbox_get_bstream (mbox_t mbox, unsigned int msgno, stream_t *pstream) 28 mbox_get_bstream (mbox_t mbox, unsigned int msgno, stream_t *pstream)
29 { 29 {
30 int status = 0; 30 int status = 0;
31
32 mbox_debug_print (mbox, "get_bstream(%u)", msgno);
31 if (mbox == NULL || msgno == 0 || pstream == NULL) 33 if (mbox == NULL || msgno == 0 || pstream == NULL)
32 return MU_ERROR_INVALID_PARAMETER; 34 return MU_ERROR_INVALID_PARAMETER;
33 35
...@@ -58,10 +60,11 @@ mbox_set_bstream (mbox_t mbox, unsigned int msgno, stream_t stream) ...@@ -58,10 +60,11 @@ mbox_set_bstream (mbox_t mbox, unsigned int msgno, stream_t stream)
58 if (msgno > mbox->umessages_count) 60 if (msgno > mbox->umessages_count)
59 return MU_ERROR_INVALID_PARAMETER; 61 return MU_ERROR_INVALID_PARAMETER;
60 62
61 msgno--; 63 if (mbox->umessages[msgno - 1]->body.stream)
62 if (mbox->umessages[msgno]->body.stream) 64 mbox_release_bstream (mbox, msgno);
63 stream_destroy (&mbox->umessages[msgno]->body.stream);
64 65
65 mbox->umessages[msgno]->body.stream = stream; 66 mbox->umessages[msgno - 1]->attr_flags |= MU_MBOX_BSTREAM_SET;
67 mbox->umessages[msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
68 mbox->umessages[msgno - 1]->body.stream = stream;
66 return 0; 69 return 0;
67 } 70 }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
27 int 27 int
28 mbox_set_carrier (mbox_t mbox, stream_t carrier) 28 mbox_set_carrier (mbox_t mbox, stream_t carrier)
29 { 29 {
30 mbox_debug_print (mbox, "set_carrier");
30 if (mbox == NULL) 31 if (mbox == NULL)
31 return MU_ERROR_INVALID_PARAMETER; 32 return MU_ERROR_INVALID_PARAMETER;
32 33
...@@ -42,6 +43,7 @@ mbox_set_carrier (mbox_t mbox, stream_t carrier) ...@@ -42,6 +43,7 @@ mbox_set_carrier (mbox_t mbox, stream_t carrier)
42 int 43 int
43 mbox_get_carrier (mbox_t mbox, stream_t *pcarrier) 44 mbox_get_carrier (mbox_t mbox, stream_t *pcarrier)
44 { 45 {
46 mbox_debug_print (mbox, "get_carrier");
45 if (mbox == NULL || pcarrier == NULL) 47 if (mbox == NULL || pcarrier == NULL)
46 return MU_ERROR_INVALID_PARAMETER; 48 return MU_ERROR_INVALID_PARAMETER;
47 49
......
...@@ -43,6 +43,16 @@ mbox_set_newmsg_cb (mbox_t mbox, int (*cb) __P ((int, void *)), void *arg) ...@@ -43,6 +43,16 @@ mbox_set_newmsg_cb (mbox_t mbox, int (*cb) __P ((int, void *)), void *arg)
43 } 43 }
44 44
45 int 45 int
46 mbox_set_error_cb (mbox_t mbox, int (*cb) __P ((int, void *)), void *arg)
47 {
48 if (mbox)
49 return MU_ERROR_INVALID_PARAMETER;
50 mbox->error.cb = cb;
51 mbox->error.arg = arg;
52 return 0;
53 }
54
55 int
46 mbox_newmsg_cb (mbox_t mbox, int info) 56 mbox_newmsg_cb (mbox_t mbox, int info)
47 { 57 {
48 if (mbox) 58 if (mbox)
...@@ -61,3 +71,13 @@ mbox_progress_cb (mbox_t mbox, int info) ...@@ -61,3 +71,13 @@ mbox_progress_cb (mbox_t mbox, int info)
61 return mbox->progress.cb (info, mbox->progress.arg); 71 return mbox->progress.cb (info, mbox->progress.arg);
62 return 0; 72 return 0;
63 } 73 }
74
75 int
76 mbox_error_cb (mbox_t mbox, int info)
77 {
78 if (mbox)
79 return MU_ERROR_INVALID_PARAMETER;
80 if (mbox->error.cb)
81 return mbox->error.cb (info, mbox->error.arg);
82 return 0;
83 }
......
...@@ -29,6 +29,8 @@ mbox_close (mbox_t mbox) ...@@ -29,6 +29,8 @@ mbox_close (mbox_t mbox)
29 { 29 {
30 size_t i; 30 size_t i;
31 31
32 mbox_debug_print (mbox, "close");
33
32 if (mbox == NULL) 34 if (mbox == NULL)
33 return MU_ERROR_INVALID_PARAMETER; 35 return MU_ERROR_INVALID_PARAMETER;
34 36
...@@ -44,31 +46,21 @@ mbox_close (mbox_t mbox) ...@@ -44,31 +46,21 @@ mbox_close (mbox_t mbox)
44 - to prepare for another scan. */ 46 - to prepare for another scan. */
45 for (i = 0; i < mbox->umessages_count; i++) 47 for (i = 0; i < mbox->umessages_count; i++)
46 { 48 {
47 mbox_message_t mum = mbox->umessages[i]; 49 /* Destroy the attach streams and attribute. */
48 /* Destroy the attach messages. */ 50 if (mbox->umessages[i])
49 if (mum) 51 mbox_release_msg (mbox, i + 1);
50 {
51 mbox_hcache_free (mbox, i + 1);
52 if (mum->header.stream)
53 stream_destroy (&(mum->header.stream));
54 if (mum->body.stream)
55 stream_destroy (&(mum->body.stream));
56 if (mum->separator)
57 free (mum->separator);
58 if (mum->attribute)
59 attribute_destroy (&mum->attribute);
60 free (mum);
61 }
62 } 52 }
63 if (mbox->umessages) 53 if (mbox->umessages)
64 free (mbox->umessages); 54 free (mbox->umessages);
65 mbox->umessages = NULL; 55 mbox->umessages = NULL;
66 mbox->umessages_count = 0; 56 mbox->umessages_count = 0;
57 mbox->messages_count = 0;
67 mbox->size = 0; 58 mbox->size = 0;
68 mbox->uidvalidity = 0; 59 mbox->uidvalidity = 0;
69 mbox->uidnext = 0; 60 mbox->uidnext = 0;
70 if (mbox->filename) 61 if (mbox->filename)
71 free (mbox->filename); 62 free (mbox->filename);
72 mbox->filename = NULL; 63 mbox->filename = NULL;
64
73 return stream_close (mbox->carrier); 65 return stream_close (mbox->carrier);
74 } 66 }
......
1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <string.h>
23
24 #include <stdio.h>
25 #include <stdarg.h>
26 #include <mailutils/error.h>
27 #include <mailutils/sys/mbox.h>
28
29 int
30 mbox_get_debug (mbox_t mbox, mu_debug_t *pdebug)
31 {
32 if (mbox == NULL || pdebug == NULL)
33 return MU_ERROR_INVALID_PARAMETER;
34
35
36 if (mbox->debug == NULL)
37 {
38 stream_t stream;
39 int status = stream_stdio_create (&stream, stderr);
40 if (status == 0)
41 status = mu_debug_stream_create (&mbox->debug, stream, 0);
42 if (status != 0)
43 return status;
44 }
45 mu_debug_ref (mbox->debug);
46 *pdebug = mbox->debug;
47 return 0;
48 }
49
50 int
51 mbox_set_debug (mbox_t mbox, mu_debug_t debug)
52 {
53 if (mbox == NULL)
54 return MU_ERROR_INVALID_PARAMETER;
55
56 if (mbox->debug)
57 mu_debug_destroy (&mbox->debug);
58 mbox->debug = debug;
59 return 0;
60 }
61
62 int
63 mbox_debug_print (mbox_t mbox, const char *fmt, ...)
64 {
65 if (mbox && mbox->debug)
66 {
67 char buf[128];
68 va_list ap;
69 snprintf (buf, sizeof buf, "mbox(%s)_",
70 (mbox->filename) ? mbox->filename : "");
71 mu_debug_print (mbox->debug, MU_DEBUG_TRACE, buf);
72 if (fmt)
73 {
74 va_start (ap, fmt);
75 vsnprintf (buf, sizeof buf, fmt, ap);
76 va_end (ap);
77 }
78 mu_debug_print (mbox->debug, MU_DEBUG_TRACE, buf);
79 mu_debug_print (mbox->debug, MU_DEBUG_TRACE, "\n");
80 }
81 return 0;
82 }
...@@ -24,12 +24,109 @@ ...@@ -24,12 +24,109 @@
24 #include <mailutils/sys/mbox.h> 24 #include <mailutils/sys/mbox.h>
25 25
26 void 26 void
27 mbox_release_separator (mbox_t mbox, unsigned int msgno)
28 {
29 if (mbox == NULL || msgno == 0)
30 return;
31
32 if (msgno > mbox->umessages_count)
33 return;
34
35 if (mbox->umessages[msgno - 1]->separator)
36 free (mbox->umessages[msgno - 1]->separator);
37 mbox->umessages[msgno - 1]->separator = NULL;
38 }
39
40 void
41 mbox_release_attribute (mbox_t mbox, unsigned int msgno)
42 {
43 if (mbox == NULL || msgno == 0)
44 return;
45
46 if (msgno > mbox->umessages_count)
47 return;
48
49 if (mbox->umessages[msgno - 1]->attribute)
50 _attribute_mbox_dtor (mbox->umessages[msgno - 1]->attribute);
51 mbox->umessages[msgno - 1]->attribute = NULL;
52 }
53
54 void
55 mbox_release_hstream (mbox_t mbox, unsigned int msgno)
56 {
57 if (mbox == NULL || msgno == 0)
58 return;
59
60 if (msgno > mbox->umessages_count)
61 return;
62
63 if (mbox->umessages[msgno - 1]->header.stream)
64 {
65 if (mbox->umessages[msgno - 1]->attr_userflags & MU_MBOX_HSTREAM_SET)
66 {
67 stream_destroy (&mbox->umessages[msgno - 1]->header.stream);
68 mbox->umessages[msgno - 1]->attr_userflags &= ~MU_MBOX_HSTREAM_SET;
69 }
70 else
71 _stream_mbox_dtor (mbox->umessages[msgno - 1]->header.stream);
72 }
73 mbox->umessages[msgno - 1]->header.stream = NULL;
74 }
75
76 void
77 mbox_release_bstream (mbox_t mbox, unsigned int msgno)
78 {
79 if (mbox == NULL || msgno == 0)
80 return;
81
82 if (msgno > mbox->umessages_count)
83 return;
84
85 if (mbox->umessages[msgno - 1]->body.stream)
86 {
87 if (mbox->umessages[msgno - 1]->attr_userflags & MU_MBOX_BSTREAM_SET)
88 {
89 stream_destroy (&mbox->umessages[msgno - 1]->body.stream);
90 mbox->umessages[msgno - 1]->attr_userflags &= ~MU_MBOX_BSTREAM_SET;
91 }
92 else
93 _stream_mbox_dtor (mbox->umessages[msgno - 1]->body.stream);
94 }
95 mbox->umessages[msgno - 1]->body.stream = NULL;
96 }
97
98 void
99 mbox_release_msg (mbox_t mbox, unsigned int msgno)
100 {
101 if (mbox == NULL || msgno == 0)
102 return;
103
104 if (msgno > mbox->umessages_count)
105 return;
106
107 mbox_release_hcache (mbox, msgno);
108 mbox_release_separator (mbox, msgno);
109 mbox_release_attribute (mbox, msgno);
110 mbox_release_hstream (mbox, msgno);
111 mbox_release_bstream (mbox, msgno);
112 free (mbox->umessages[msgno - 1]);
113 mbox->umessages[msgno - 1] = NULL;
114 }
115
116 void
27 mbox_destroy (mbox_t *pmbox) 117 mbox_destroy (mbox_t *pmbox)
28 { 118 {
29 if (pmbox && *pmbox) 119 if (pmbox && *pmbox)
30 { 120 {
31 mbox_t mbox = *pmbox; 121 mbox_t mbox = *pmbox;
122 mbox_debug_print (mbox, "destroy");
123 /* _close will release all the messages. */
32 mbox_close (mbox); 124 mbox_close (mbox);
125 if (mbox->carrier)
126 stream_destroy (&mbox->carrier);
127 if (mbox->debug)
128 mu_debug_destroy (&mbox->debug);
129 mbox_release_hcache (mbox, 0);
33 free (mbox); 130 free (mbox);
34 } 131 }
35 } 132 }
......
...@@ -128,6 +128,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -128,6 +128,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
128 off_t tmp_size = 0; 128 off_t tmp_size = 0;
129 size_t save_uidvalidity = 0; /* uidvalidity is save in the first message. */ 129 size_t save_uidvalidity = 0; /* uidvalidity is save in the first message. */
130 130
131 mbox_debug_print (mbox, "expunge, r=%d", remove_deleted);
131 if (mbox == NULL) 132 if (mbox == NULL)
132 return MU_ERROR_INVALID_PARAMETER; 133 return MU_ERROR_INVALID_PARAMETER;
133 134
...@@ -154,7 +155,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -154,7 +155,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
154 { 155 {
155 if (tmp_name) 156 if (tmp_name)
156 free (tmp_name); 157 free (tmp_name);
157 /* mu_error ("Failed to create temporary file when expunging.\n"); */ 158 mbox_error_cb (mbox, errno);
158 return errno; 159 return errno;
159 } 160 }
160 161
...@@ -193,7 +194,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -193,7 +194,7 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
193 mbox_destroy (&tmp_mbox); 194 mbox_destroy (&tmp_mbox);
194 remove (tmp_name); 195 remove (tmp_name);
195 free (tmp_name); 196 free (tmp_name);
196 /* mu_error ("Failed to grab the lock\n"); */ 197 mbox_error_cb (mbox, status);
197 return status; 198 return status;
198 } 199 }
199 200
...@@ -232,32 +233,29 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -232,32 +233,29 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
232 stream_t hstream = NULL, bstream = NULL; 233 stream_t hstream = NULL, bstream = NULL;
233 attribute_t attribute = NULL; 234 attribute_t attribute = NULL;
234 char *sep = NULL; 235 char *sep = NULL;
235 /* The message was not instanciated, probably the dirty flag was 236 /* The message was not instanciated, create one here. */
236 set by mbox_scan(), create one here. */ 237 if (mum->separator == NULL || mum->attribute
237 if (mum->separator == NULL || mum->header.stream == NULL 238 || mum->header.stream == NULL || mum->body.stream == NULL)
238 || mum->body.stream == NULL || mum->attribute == NULL)
239 { 239 {
240 if (mbox_get_hstream (mbox, i + 1, &hstream) != 0 240 if ((status = mbox_get_separator (mbox, i + 1, &sep) != 0)
241 || mbox_get_bstream (mbox, i + 1, &bstream) != 0 241 || (status = mbox_get_attribute (mbox, i + 1, &attribute) != 0)
242 || mbox_get_separator (mbox, i + 1, &sep) != 0 242 || (status = mbox_get_hstream (mbox, i + 1, &hstream) != 0)
243 || mbox_get_attribute (mbox, i + 1, &attribute) != 0) 243 || (status = mbox_get_bstream (mbox, i + 1, &bstream) != 0))
244 { 244 {
245 /* mu_error ("Error expunge:%d", __LINE__); */ 245 mbox_error_cb (mbox, status);
246 goto bailout0; 246 goto bailout0;
247 } 247 }
248 } 248 }
249 status = mbox_append_hb0 (tmp_mbox, mum->separator, mum->attribute, 249 status = mbox_append_hb0 (tmp_mbox, mum->separator, mum->attribute,
250 save_uidvalidity, mum->header.stream, 250 mum->header.stream, mum->body.stream,
251 mum->body.stream); 251 save_uidvalidity, mum->uid);
252 if (sep)
253 free (sep); 252 free (sep);
253 attribute_destroy (&attribute);
254 stream_destroy (&hstream); 254 stream_destroy (&hstream);
255 stream_destroy (&bstream); 255 stream_destroy (&bstream);
256 attribute_destroy (&attribute);
257 if (status != 0) 256 if (status != 0)
258 { 257 {
259 /* mu_error ("Error expunge:%d: %s", __LINE__, 258 mbox_error_cb (mbox, status);
260 strerror (status)); */
261 goto bailout0; 259 goto bailout0;
262 } 260 }
263 /* Clear the dirty bits. */ 261 /* Clear the dirty bits. */
...@@ -266,10 +264,9 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -266,10 +264,9 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
266 } /* for (;;) */ 264 } /* for (;;) */
267 265
268 /* Get the real size of the mailbox. The size maintain in 266 /* Get the real size of the mailbox. The size maintain in
269 the struct _mailbox { off_t size; } the one return in 267 the struct _mailbox { off_t size; }(the one return in
270 mailbox_get_size() only return the size that mbox_scan() 268 mailbox_get_size()) only returns the size that mbox_scan()
271 is aware of not necessary the size of the file after 269 is aware of, not necessary the size of the file after an append. */
272 an append. */
273 stream_get_size (tmp_mbox->carrier, &tmp_size); 270 stream_get_size (tmp_mbox->carrier, &tmp_size);
274 271
275 /* Caution: before ftruncate()ing the file see 272 /* Caution: before ftruncate()ing the file see
...@@ -281,29 +278,28 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -281,29 +278,28 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
281 if (stream_get_size (mbox->carrier, &size) == 0) 278 if (stream_get_size (mbox->carrier, &size) == 0)
282 { 279 {
283 off_t len = size - mbox->size; 280 off_t len = size - mbox->size;
284 char buffer [1024]; 281 off_t offset = mbox->size;
282 char buf [1024];
285 size_t n = 0; 283 size_t n = 0;
286 if (len > 0) 284 if (len > 0)
287 { 285 {
288 stream_seek (mbox->carrier, mbox->size, MU_STREAM_WHENCE_SET); 286 while ((status = stream_read (mbox->carrier, buf, sizeof buf,
289 stream_seek (tmp_mbox->carrier, tmp_size, MU_STREAM_WHENCE_SET); 287 offset, &n)) == 0 && n > 0)
290 while ((status = stream_read (mbox->carrier, buffer,
291 sizeof buffer, &n)) == 0 && n > 0)
292 { 288 {
293 status = stream_write (tmp_mbox->carrier, buffer, n, NULL); 289 status = stream_write(tmp_mbox->carrier, buf, n, tmp_size, &n);
294 if (status != 0) 290 if (status != 0)
295 { 291 {
296 /* mu_error ("Error expunge:%d: %s", __LINE__, 292 mbox_error_cb (mbox, status);
297 strerror (status)); */
298 goto bailout0; 293 goto bailout0;
299 } 294 }
295 offset += n;
296 tmp_size += n;
300 } 297 }
301 } 298 }
302 else if (len < 0) 299 else if (len < 0)
303 { 300 {
304 /* Corrupted mailbox. */ 301 /* Corrupted mailbox. */
305 /* mu_error ("Error expunge:%d: %s", __LINE__, 302 mbox_error_cb (mbox, status);
306 strerror (status)); */
307 goto bailout0; 303 goto bailout0;
308 } 304 }
309 } 305 }
...@@ -312,32 +308,31 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -312,32 +308,31 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
312 /* Seek and rewrite it. */ 308 /* Seek and rewrite it. */
313 if (tmp_size > 0) 309 if (tmp_size > 0)
314 { 310 {
315 char buffer [1024]; 311 char buf [1024];
316 size_t n = 0; 312 size_t n = 0;
313 off_t tmp_off = 0;
314 off_t offset = marker;
317 315
318 stream_seek (mbox->carrier, marker, MU_STREAM_WHENCE_SET); 316 while ((status = stream_read (tmp_mbox->carrier, buf, sizeof buf,
319 stream_seek (tmp_mbox->carrier, 0, MU_STREAM_WHENCE_SET); 317 tmp_off, &n)) == 0 && n > 0)
320 while ((status = stream_read (tmp_mbox->carrier, buffer,
321 sizeof buffer, &n)) == 0 && n > 0)
322 { 318 {
323 status = stream_write (mbox->carrier, buffer, n, &n); 319 status = stream_write (mbox->carrier, buf, n, offset, &n);
324 if (status != 0) 320 if (status != 0)
325 { 321 {
326 /* mu_error ("Error expunge:%d: %s\n", __LINE__, 322 mbox_error_cb (mbox, status);
327 strerror (status)); */
328 goto bailout; 323 goto bailout;
329 } 324 }
325 tmp_off += n;
326 offset += n;
330 } 327 }
331 } 328 }
332 329
333 /* Flush/truncation. Need to flush before truncate. */ 330 /* Flush/truncation. Need to flush before truncate. */
334 stream_get_size (tmp_mbox->carrier, &tmp_size);
335 stream_flush (mbox->carrier); 331 stream_flush (mbox->carrier);
336 status = stream_truncate (mbox->carrier, tmp_size + marker); 332 status = stream_truncate (mbox->carrier, tmp_size + marker);
337 if (status != 0) 333 if (status != 0)
338 { 334 {
339 /* mu_error ("Error expunging:%d: %s\n", __LINE__, 335 mbox_error_cb (mbox, status);
340 strerror (status)); */
341 goto bailout; 336 goto bailout;
342 } 337 }
343 338
...@@ -346,7 +341,6 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -346,7 +341,6 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
346 remove (tmp_name); 341 remove (tmp_name);
347 342
348 bailout: 343 bailout:
349
350 free (tmp_name); 344 free (tmp_name);
351 /* Release the File lock. */ 345 /* Release the File lock. */
352 lockfile_unlock (mbox->lockfile); 346 lockfile_unlock (mbox->lockfile);
...@@ -366,47 +360,41 @@ mbox_expunge (mbox_t mbox, int remove_deleted) ...@@ -366,47 +360,41 @@ mbox_expunge (mbox_t mbox, int remove_deleted)
366 size_t dlast; 360 size_t dlast;
367 for (j = dirty, dlast = mbox->messages_count - 1; j <= dlast; j++) 361 for (j = dirty, dlast = mbox->messages_count - 1; j <= dlast; j++)
368 { 362 {
369 /* Clear all the references to streams. */
370 mum = mbox->umessages[j]; 363 mum = mbox->umessages[j];
364 /* Clear all the references to streams. */
371 if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags)) 365 if (remove_deleted && ATTRIBUTE_IS_DELETED (mum->attr_flags))
372 { 366 {
373 if (mum->separator) 367 mbox_release_msg (mbox, j + 1);
374 free (mum->separator);
375 mum->separator = NULL;
376 if (mum->attribute)
377 attribute_destroy (&mum->attribute);
378 if (mum->header.stream)
379 stream_destroy (&mum->header.stream);
380 if (mum->body.stream)
381 stream_destroy (&mum->body.stream);
382 mbox_hcache_free (mbox, i + 1);
383 /* memset (mum, 0, sizeof (*mum)); */
384
385 if ((j + 1) <= dlast) 368 if ((j + 1) <= dlast)
386 { 369 {
387 /* Move all the pointers up. So the message pointer 370 /* Move all the pointers up. So the message pointers
388 part of mum will be at the right position. */ 371 will be at the right position. */
389 memmove (mbox->umessages + j, mbox->umessages + j + 1, 372 memmove (mbox->umessages + j, mbox->umessages + j + 1,
390 (dlast - j) * sizeof (mum)); 373 (dlast - j) * sizeof mum);
391 #if 1
392 mum->from_ = mum->header.start = 0;
393 mum->body.start = mum->body.end = 0;
394 mum->header.lines = mum->body.lines = 0;
395 #endif
396 /* We are not free()ing the useless mum, but instead
397 we put it back in the pool, to be reuse. */
398 mbox->umessages[dlast] = mum;
399 dlast--; 374 dlast--;
400 /* Set mum to the new value after the memmove so it
401 gets cleared to. */
402 mum = mbox->umessages[j];
403 } 375 }
376 mbox->umessages_count--;
377 mbox->messages_count--;
404 } 378 }
379 else
380 {
381 /* Readjust the offsets and attach objects. */
405 mum->from_ = mum->header.start = 0; 382 mum->from_ = mum->header.start = 0;
406 mum->body.start = mum->body.end = 0; 383 mum->body.start = mum->body.end = 0;
407 mum->header.lines = mum->body.lines = 0; 384 mum->header.lines = mum->body.lines = 0;
385 stream_mbox_msgno (mum->header.stream, j + 1);
386 stream_mbox_msgno (mum->body.stream, j + 1);
387 attribute_mbox_msgno (mum->attribute, j + 1);
388 }
408 } 389 }
409 /* This is should reset the messages_count, the last argument 0 means 390
391 /* Must Realloc the right size before the scan. some slots
392 in the umessages may be NULL after remove_deleted. */
393 mbox->umessages = realloc (mbox->umessages,
394 mbox->umessages_count
395 * sizeof (*(mbox->umessages)));
396
397 /* This should reset the messages_count, the last argument 0 means
410 not to send event notification. */ 398 not to send event notification. */
411 mbox_scan (mbox, dirty, NULL, 0); 399 mbox_scan (mbox, dirty, NULL, 0);
412 } 400 }
......
...@@ -21,10 +21,15 @@ ...@@ -21,10 +21,15 @@
21 21
22 #include <stdlib.h> 22 #include <stdlib.h>
23 #include <string.h> 23 #include <string.h>
24 #include <ctype.h>
24 25
25 #include <mailutils/error.h> 26 #include <mailutils/error.h>
26 #include <mailutils/sys/mbox.h> 27 #include <mailutils/sys/mbox.h>
27 28
29 #undef min
30 #define min(a,b) ((a) < (b) ? (a) : (b))
31
32
28 static const char *hcache_default[] = 33 static const char *hcache_default[] =
29 { 34 {
30 "Bcc", 35 "Bcc",
...@@ -35,9 +40,10 @@ static const char *hcache_default[] = ...@@ -35,9 +40,10 @@ static const char *hcache_default[] =
35 "Date", 40 "Date",
36 "From", 41 "From",
37 "In-Reply-To", 42 "In-Reply-To",
43 "Mail-Followup-To",
38 "Message-ID", 44 "Message-ID",
39 "Reply-To", 45 "Reply-To",
40 "Reply-To", 46 "Return-Path",
41 "Sender", 47 "Sender",
42 "Subject", 48 "Subject",
43 "To", 49 "To",
...@@ -45,7 +51,7 @@ static const char *hcache_default[] = ...@@ -45,7 +51,7 @@ static const char *hcache_default[] =
45 }; 51 };
46 52
47 void 53 void
48 mbox_hcache_free (mbox_t mbox, unsigned int msgno) 54 mbox_release_hcache (mbox_t mbox, unsigned int msgno)
49 { 55 {
50 struct _hcache *hc; 56 struct _hcache *hc;
51 57
...@@ -76,36 +82,51 @@ mbox_hcache_free (mbox_t mbox, unsigned int msgno) ...@@ -76,36 +82,51 @@ mbox_hcache_free (mbox_t mbox, unsigned int msgno)
76 int 82 int
77 mbox_set_hcache (mbox_t mbox, const char **array, size_t len) 83 mbox_set_hcache (mbox_t mbox, const char **array, size_t len)
78 { 84 {
85 int status = 0;
86
79 if (mbox == NULL) 87 if (mbox == NULL)
80 return MU_ERROR_INVALID_PARAMETER; 88 return MU_ERROR_INVALID_PARAMETER;
81 89
82 mbox_hcache_free (mbox, 0); 90 mbox_release_hcache (mbox, 0);
83 91
84 if (array && len) 92 if (array && len)
85 { 93 status = mbox_add_hcache (mbox, array, len);
86 unsigned int i;
87 94
88 mbox->hcache.values = calloc (len, sizeof (*(mbox->hcache.values))); 95 return status;
96 }
89 97
90 if (mbox->hcache.values == NULL) 98 int
91 return MU_ERROR_NO_MEMORY; 99 mbox_add_hcache (mbox_t mbox, const char **array, size_t len)
100 {
101 size_t i;
102 int status = 0;
103
104 if (mbox == NULL || array == NULL || len == 0)
105 return MU_ERROR_INVALID_PARAMETER;
92 106
93 for (i = 0; i < len; i++) 107 for (i = 0; i < len; i++)
94 { 108 {
95 mbox->hcache.values[i] = strdup (array[i]); 109 char **values;
96 if (mbox->hcache.values[i] == NULL) 110 if (array[i] == NULL || array[i][0] == '\0')
111 continue;
112 values = realloc (mbox->hcache.values,
113 (mbox->hcache.size + 1) * sizeof (*values));
114 if (values == NULL)
97 { 115 {
98 mbox_set_hcache (mbox, NULL, 0); 116 status = MU_ERROR_NO_MEMORY;
99 return MU_ERROR_NO_MEMORY; 117 break;
100 } 118 }
119 mbox->hcache.values = values;
120 mbox->hcache.values[mbox->hcache.size] = strdup (array[i]);
121 mbox->hcache.values[mbox->hcache.size][0] =
122 toupper (mbox->hcache.values[mbox->hcache.size][0]);
101 mbox->hcache.size++; 123 mbox->hcache.size++;
102 } 124 }
103 } 125 return status;
104 return 0;
105 } 126 }
106 127
107 int 128 int
108 mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name, 129 mbox_append_hcache (mbox_t mbox, unsigned int msgno, const char *name,
109 const char *value) 130 const char *value)
110 { 131 {
111 struct _hcache *hc; 132 struct _hcache *hc;
...@@ -133,7 +154,9 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name, ...@@ -133,7 +154,9 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name,
133 154
134 for (i = 0; i < mbox->hcache.size; i++) 155 for (i = 0; i < mbox->hcache.size; i++)
135 { 156 {
136 if (strcasecmp (mbox->hcache.values[i], name) == 0) 157 if (mbox->hcache.values[i]
158 && toupper (*name) == mbox->hcache.values[i][0]
159 && strcasecmp (mbox->hcache.values[i], name) == 0)
137 { 160 {
138 if (value == NULL) 161 if (value == NULL)
139 { 162 {
...@@ -164,8 +187,52 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name, ...@@ -164,8 +187,52 @@ mbox_hcache_append (mbox_t mbox, unsigned int msgno, const char *name,
164 } 187 }
165 188
166 int 189 int
167 mbox_set_hcache_default (mbox_t mbox) 190 mbox_set_default_hcache (mbox_t mbox)
168 { 191 {
169 return mbox_set_hcache (mbox, hcache_default, 192 return mbox_set_hcache (mbox, hcache_default,
170 sizeof (hcache_default) / sizeof (*hcache_default)); 193 (sizeof hcache_default) / sizeof (*hcache_default));
194 }
195
196 int
197 mbox_value_hcache (mbox_t mbox, unsigned int msgno, const char *name,
198 char *buf, size_t buflen, size_t *pn)
199 {
200 mbox_message_t mum;
201 size_t i;
202 size_t n = 0;
203 int status = MU_ERROR_ENTRY_NOT_EXIST;
204
205 mbox_debug_print (mbox, "value_hcache(%d)", msgno);
206
207 if (mbox == NULL || msgno == 0 || name == NULL || *name == '\0')
208 return MU_ERROR_INVALID_PARAMETER;
209
210 if (msgno > mbox->umessages_count)
211 return MU_ERROR_INVALID_PARAMETER;
212
213 mum = mbox->umessages[msgno - 1];
214 for (i = 0; i < mbox->hcache.size; i++)
215 {
216 if (mbox->hcache.values[i]
217 && toupper (*name) == mbox->hcache.values[i][0]
218 && strcasecmp (mbox->hcache.values[i], name) == 0)
219 {
220 if (mum->hcache.size == mbox->hcache.size)
221 {
222 n = strlen (mum->hcache.values[i]);
223 if (buf && buflen)
224 {
225 buflen--;
226 n = min (buflen, n);
227 memcpy (buf, mum->hcache.values[i], n);
228 buf[n] = '\0';
229 }
230 status = 0;
231 }
232 }
233 }
234
235 if (pn)
236 *pn = n;
237 return status;
171 } 238 }
......
...@@ -27,6 +27,8 @@ int ...@@ -27,6 +27,8 @@ int
27 mbox_get_hlines (mbox_t mbox, unsigned int msgno, unsigned int *plines) 27 mbox_get_hlines (mbox_t mbox, unsigned int msgno, unsigned int *plines)
28 { 28 {
29 unsigned int lines = 0; 29 unsigned int lines = 0;
30
31 mbox_debug_print (mbox, "get_lines(%u)", msgno);
30 if (mbox && msgno) 32 if (mbox && msgno)
31 { 33 {
32 msgno--; 34 msgno--;
......
...@@ -27,6 +27,8 @@ int ...@@ -27,6 +27,8 @@ int
27 mbox_get_hsize (mbox_t mbox, unsigned int msgno, unsigned int *psize) 27 mbox_get_hsize (mbox_t mbox, unsigned int msgno, unsigned int *psize)
28 { 28 {
29 unsigned int size = 0; 29 unsigned int size = 0;
30
31 mbox_debug_print (mbox, "get_hsize(%d)", msgno);
30 if (mbox && msgno) 32 if (mbox && msgno)
31 { 33 {
32 msgno--; 34 msgno--;
......
...@@ -28,6 +28,8 @@ int ...@@ -28,6 +28,8 @@ int
28 mbox_get_hstream (mbox_t mbox, unsigned int msgno, stream_t *pstream) 28 mbox_get_hstream (mbox_t mbox, unsigned int msgno, stream_t *pstream)
29 { 29 {
30 int status = 0; 30 int status = 0;
31
32 mbox_debug_print (mbox, "get_hstream(%u)", msgno);
31 if (mbox == NULL || msgno == 0 || pstream == NULL) 33 if (mbox == NULL || msgno == 0 || pstream == NULL)
32 return MU_ERROR_INVALID_PARAMETER; 34 return MU_ERROR_INVALID_PARAMETER;
33 35
...@@ -58,10 +60,11 @@ mbox_set_hstream (mbox_t mbox, unsigned int msgno, stream_t stream) ...@@ -58,10 +60,11 @@ mbox_set_hstream (mbox_t mbox, unsigned int msgno, stream_t stream)
58 if (msgno > mbox->umessages_count) 60 if (msgno > mbox->umessages_count)
59 return MU_ERROR_INVALID_PARAMETER; 61 return MU_ERROR_INVALID_PARAMETER;
60 62
61 msgno--; 63 if (mbox->umessages[msgno - 1]->header.stream)
62 if (mbox->umessages[msgno]->header.stream) 64 mbox_release_hstream (mbox, msgno);
63 stream_destroy (&mbox->umessages[msgno]->header.stream);
64 65
65 mbox->umessages[msgno]->header.stream = stream; 66 mbox->umessages[msgno - 1]->attr_flags |= MU_MBOX_HSTREAM_SET;
67 mbox->umessages[msgno - 1]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
68 mbox->umessages[msgno - 1]->header.stream = stream;
66 return 0; 69 return 0;
67 } 70 }
......
...@@ -25,14 +25,16 @@ ...@@ -25,14 +25,16 @@
25 #include <mailutils/sys/mbox.h> 25 #include <mailutils/sys/mbox.h>
26 26
27 int 27 int
28 mbox_changed_on_disk (mbox_t mbox) 28 mbox_has_newmail (mbox_t mbox)
29 { 29 {
30 int changed = 0; 30 int newmail = 0;
31
32 mbox_debug_print (mbox, "has_newmail");
31 33
32 /* If the modification time is greater then the access time, the file has 34 /* If the modification time is greater then the access time, the file has
33 been modified since the last time it was accessed. This typically means 35 been modified since the last time it was accessed. This typically means
34 new mail or someone tempered with the mailbox. */ 36 new mail or someone tempered with the mailbox. */
35 if (mbox->carrier) 37 if (mbox && mbox->carrier)
36 { 38 {
37 int fd = -1; 39 int fd = -1;
38 if (stream_get_fd (mbox->carrier, &fd) == 0) 40 if (stream_get_fd (mbox->carrier, &fd) == 0)
...@@ -41,9 +43,9 @@ mbox_changed_on_disk (mbox_t mbox) ...@@ -41,9 +43,9 @@ mbox_changed_on_disk (mbox_t mbox)
41 if (fstat (fd, &statbuf) == 0) 43 if (fstat (fd, &statbuf) == 0)
42 { 44 {
43 if (difftime (statbuf.st_mtime, statbuf.st_atime) > 0) 45 if (difftime (statbuf.st_mtime, statbuf.st_atime) > 0)
44 changed = 1; 46 newmail = 1;
45 } 47 }
46 } 48 }
47 } 49 }
48 return changed; 50 return newmail;
49 } 51 }
......
...@@ -31,6 +31,8 @@ mbox_open (mbox_t mbox, const char *filename, int flags) ...@@ -31,6 +31,8 @@ mbox_open (mbox_t mbox, const char *filename, int flags)
31 char from[12]; 31 char from[12];
32 size_t n = 0; 32 size_t n = 0;
33 33
34 mbox_debug_print (mbox, "open(%s,%d)", (filename) ? filename : "", flags);
35
34 if (mbox == NULL) 36 if (mbox == NULL)
35 return MU_ERROR_INVALID_PARAMETER; 37 return MU_ERROR_INVALID_PARAMETER;
36 38
...@@ -49,12 +51,11 @@ mbox_open (mbox_t mbox, const char *filename, int flags) ...@@ -49,12 +51,11 @@ mbox_open (mbox_t mbox, const char *filename, int flags)
49 return status; 51 return status;
50 52
51 /* We need to be able to seek on the stream. */ 53 /* We need to be able to seek on the stream. */
52 status = stream_seek (mbox->carrier, 0, MU_STREAM_WHENCE_SET); 54 if (!stream_is_seekable (mbox->carrier))
53 if (status != 0) 55 return MU_ERROR_NOT_SUPPORTED;
54 return status;
55 56
56 /* Check if it is indeed a mbox format. */ 57 /* Check if it is indeed a mbox format. */
57 stream_readline (mbox->carrier, from, sizeof from, &n); 58 stream_readline (mbox->carrier, from, sizeof from, 0, &n);
58 if (status != 0) 59 if (status != 0)
59 return status; 60 return status;
60 61
......
...@@ -75,18 +75,32 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n) ...@@ -75,18 +75,32 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n)
75 case 'R': 75 case 'R':
76 mum->attr_flags |= MU_ATTRIBUTE_READ; 76 mum->attr_flags |= MU_ATTRIBUTE_READ;
77 break; 77 break;
78
78 case 'O': 79 case 'O':
79 case 'o': 80 case 'o':
80 mum->attr_flags |= MU_ATTRIBUTE_SEEN; 81 mum->attr_flags |= MU_ATTRIBUTE_SEEN;
81 break; 82 break;
83
82 case 'a': 84 case 'a':
83 case 'A': 85 case 'A':
84 mum->attr_flags |= MU_ATTRIBUTE_ANSWERED; 86 mum->attr_flags |= MU_ATTRIBUTE_ANSWERED;
85 break; 87 break;
88
86 case 'd': 89 case 'd':
87 case 'D': 90 case 'D':
88 mum->attr_flags |= MU_ATTRIBUTE_DELETED; 91 mum->attr_flags |= MU_ATTRIBUTE_DELETED;
89 break; 92 break;
93
94 case 't':
95 case 'T':
96 mum->attr_flags |= MU_ATTRIBUTE_DRAFT;
97 break;
98
99 case 'f':
100 case 'F':
101 mum->attr_flags |= MU_ATTRIBUTE_FLAGGED;
102 break;
103
90 } 104 }
91 } 105 }
92 } 106 }
...@@ -96,8 +110,6 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n) ...@@ -96,8 +110,6 @@ mbox_parse_status (mbox_message_t mum, char *buf, size_t n)
96 static int 110 static int
97 mbox_alloc_umessages (mbox_t mbox) 111 mbox_alloc_umessages (mbox_t mbox)
98 { 112 {
99 mbox_message_t mum;
100 unsigned int msgno = 0;
101 if (mbox->messages_count >= mbox->umessages_count) 113 if (mbox->messages_count >= mbox->umessages_count)
102 { 114 {
103 mbox_message_t *m; 115 mbox_message_t *m;
...@@ -115,11 +127,6 @@ mbox_alloc_umessages (mbox_t mbox) ...@@ -115,11 +127,6 @@ mbox_alloc_umessages (mbox_t mbox)
115 return MU_ERROR_NO_MEMORY; 127 return MU_ERROR_NO_MEMORY;
116 } 128 }
117 } 129 }
118 if (mum->separator)
119 free (mum->separator);
120 mum->separator = 0;
121
122 mbox_hcache_free (mbox, msgno + 1);
123 return 0; 130 return 0;
124 } 131 }
125 132
...@@ -148,6 +155,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -148,6 +155,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
148 int zn, isfrom = 0; 155 int zn, isfrom = 0;
149 char *temp; 156 char *temp;
150 157
158 mbox_debug_print (mbox, "scan(%u,%d)", msgno, do_notif);
159
151 if (mbox == NULL) 160 if (mbox == NULL)
152 return MU_ERROR_INVALID_PARAMETER; 161 return MU_ERROR_INVALID_PARAMETER;
153 162
...@@ -170,14 +179,18 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -170,14 +179,18 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
170 179
171 /* Move along, move along nothing to see. */ 180 /* Move along, move along nothing to see. */
172 if (!mbox_has_newmail (mbox) && mbox->size == file_size) 181 if (!mbox_has_newmail (mbox) && mbox->size == file_size)
182 {
183 if (pcount)
184 *pcount = mbox->messages_count;
173 return 0; 185 return 0;
186 }
174 187
175 /* Bailout early on error. */ 188 /* Bailout early on error. */
176 if (status != 0) 189 if (status != 0)
177 return status; 190 return status;
178 191
179 if (mbox->hcache.size == 0) 192 if (mbox->hcache.size == 0)
180 mbox_set_hcache_default (mbox); 193 mbox_set_default_hcache (mbox);
181 194
182 /* Lock the mbox before starting. */ 195 /* Lock the mbox before starting. */
183 /* FIXME: Check error.. */ 196 /* FIXME: Check error.. */
...@@ -199,15 +212,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -199,15 +212,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
199 errno = lines = inheader = inbody = 0; 212 errno = lines = inheader = inbody = 0;
200 mum = NULL; 213 mum = NULL;
201 214
202 status = stream_seek (mbox->carrier, total, MU_STREAM_WHENCE_SET); 215 while ((status = stream_readline (mbox->carrier, buf, sizeof buf,
203 if (status != 0) 216 total, &n)) == 0 && n > 0)
204 {
205 lockfile_unlock (mbox->lockfile);
206 return status;
207 }
208
209 while ((status = stream_readline (mbox->carrier, buf, sizeof buf, &n)) == 0
210 && n > 0)
211 { 217 {
212 int nl; 218 int nl;
213 total += n; 219 total += n;
...@@ -242,7 +248,6 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -242,7 +248,6 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
242 lockfile_unlock (mbox->lockfile); 248 lockfile_unlock (mbox->lockfile);
243 return status; 249 return status;
244 } 250 }
245 stream_seek (mbox->carrier, total, MU_STREAM_WHENCE_SET);
246 } 251 }
247 } 252 }
248 /* Allocate_msgs will initialize mum. */ 253 /* Allocate_msgs will initialize mum. */
...@@ -287,7 +292,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -287,7 +292,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
287 { 292 {
288 if (buf[n - 1] == '\n') 293 if (buf[n - 1] == '\n')
289 buf[n - 1] = 0; 294 buf[n - 1] = 0;
290 mbox_hcache_append (mbox, mbox->messages_count, sfield, buf); 295 mbox_append_hcache (mbox, mbox->messages_count, sfield, buf);
291 } 296 }
292 else 297 else
293 { 298 {
...@@ -299,9 +304,10 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -299,9 +304,10 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
299 { 304 {
300 *s = '\0'; 305 *s = '\0';
301 s++; 306 s++;
307 while (*s == ' ') s++;
302 if (buf[n - 1] == '\n') 308 if (buf[n - 1] == '\n')
303 buf[n - 1] = 0; 309 buf[n - 1] = 0;
304 mbox_hcache_append (mbox, mbox->messages_count, buf, s); 310 mbox_append_hcache (mbox, mbox->messages_count, buf, s);
305 sfield = strdup (buf); 311 sfield = strdup (buf);
306 } 312 }
307 } 313 }
...@@ -341,7 +347,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -341,7 +347,7 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
341 347
342 if (mum) 348 if (mum)
343 { 349 {
344 mum->body.end = total - newline; 350 mum->body.end = total;
345 mum->body.lines = lines - newline; 351 mum->body.lines = lines - newline;
346 if (do_notif) 352 if (do_notif)
347 mbox_newmsg_cb (mbox, mbox->messages_count); 353 mbox_newmsg_cb (mbox, mbox->messages_count);
...@@ -358,10 +364,12 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -358,10 +364,12 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
358 { 364 {
359 mbox->uidvalidity = (unsigned long)time (NULL); 365 mbox->uidvalidity = (unsigned long)time (NULL);
360 mbox->uidnext = mbox->messages_count + 1; 366 mbox->uidnext = mbox->messages_count + 1;
361 /* Tell that we have been modified for expunging. */ 367 /* The uidvalidity was not save, flag it to be save
368 when expunging. */
362 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; 369 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
363 } 370 }
364 } 371 }
372
365 /* Reset the IMAP uids, if necessary. UID according to IMAP RFC is a 32 bit 373 /* Reset the IMAP uids, if necessary. UID according to IMAP RFC is a 32 bit
366 ascending number for each messages */ 374 ascending number for each messages */
367 { 375 {
...@@ -376,7 +384,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -376,7 +384,8 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
376 { 384 {
377 uid = ouid + 1; 385 uid = ouid + 1;
378 mum->uid = ouid = uid; 386 mum->uid = ouid = uid;
379 /* Note that modification for when expunging. */ 387 /* UID was not ascentind, clear this when expunging by
388 setting modification flag. */
380 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; 389 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
381 } 390 }
382 else 391 else
...@@ -386,8 +395,26 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif) ...@@ -386,8 +395,26 @@ mbox_scan (mbox_t mbox, unsigned int msgno, unsigned int *pcount, int do_notif)
386 { 395 {
387 mum = mbox->umessages[0]; 396 mum = mbox->umessages[0];
388 mbox->uidnext = uid + 1; 397 mbox->uidnext = uid + 1;
398 /* The uidnext was wrong rewrite it when expunging. */
389 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED; 399 mum->attr_flags |= MU_ATTRIBUTE_MODIFIED;
390 } 400 }
391 } 401 }
402
403 /* If reserved more memory then scan messages, realloc not
404 to waste memory. */
405 if (mbox->messages_count && mbox->messages_count < mbox->umessages_count)
406 {
407 size_t i;
408 for (i = mbox->messages_count; i < mbox->umessages_count; i++)
409 {
410 if (mbox->umessages[i])
411 mbox_release_msg (mbox, i + 1);
412 }
413 mbox->umessages = realloc (mbox->umessages,
414 mbox->messages_count
415 * sizeof (*(mbox->umessages)));
416 mbox->umessages_count = mbox->messages_count;
417 }
418 lockfile_unlock (mbox->lockfile);
392 return status; 419 return status;
393 } 420 }
......
...@@ -32,6 +32,8 @@ int ...@@ -32,6 +32,8 @@ int
32 mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep) 32 mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
33 { 33 {
34 34
35 mbox_debug_print (mbox, "get_separator(%u)", msgno);
36
35 if (mbox == NULL || msgno == 0 || psep == NULL) 37 if (mbox == NULL || msgno == 0 || psep == NULL)
36 return MU_ERROR_INVALID_PARAMETER; 38 return MU_ERROR_INVALID_PARAMETER;
37 39
...@@ -48,6 +50,7 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep) ...@@ -48,6 +50,7 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
48 char *p = NULL; 50 char *p = NULL;
49 int len = 0 ; 51 int len = 0 ;
50 size_t n = 0; 52 size_t n = 0;
53 off_t offset = mbox->umessages[msgno]->from_;
51 54
52 len = 2; 55 len = 2;
53 p = malloc (len); 56 p = malloc (len);
...@@ -57,8 +60,6 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep) ...@@ -57,8 +60,6 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
57 do 60 do
58 { 61 {
59 char *s; 62 char *s;
60 stream_seek (mbox->carrier, mbox->umessages[msgno]->from_,
61 MU_STREAM_WHENCE_SET);
62 len += 128; 63 len += 128;
63 s = realloc (p, len); 64 s = realloc (p, len);
64 if (s == NULL) 65 if (s == NULL)
...@@ -67,7 +68,8 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep) ...@@ -67,7 +68,8 @@ mbox_get_separator (mbox_t mbox, unsigned int msgno, char **psep)
67 return MU_ERROR_NO_MEMORY; 68 return MU_ERROR_NO_MEMORY;
68 } 69 }
69 p = s ; 70 p = s ;
70 stream_readline (mbox->carrier, p + strlen (p), len, &n); 71 stream_readline (mbox->carrier, p + strlen (p), len, offset, &n);
72 offset += n;
71 n = strlen (p); 73 n = strlen (p);
72 } while (n && p[n - 1] != '\n'); 74 } while (n && p[n - 1] != '\n');
73 75
...@@ -95,5 +97,6 @@ mbox_set_separator (mbox_t mbox, unsigned int msgno, const char *sep) ...@@ -95,5 +97,6 @@ mbox_set_separator (mbox_t mbox, unsigned int msgno, const char *sep)
95 if (mbox->umessages[msgno]->separator) 97 if (mbox->umessages[msgno]->separator)
96 free (mbox->umessages[msgno]->separator); 98 free (mbox->umessages[msgno]->separator);
97 mbox->umessages[msgno]->separator = (sep) ? strdup (sep) : NULL; 99 mbox->umessages[msgno]->separator = (sep) ? strdup (sep) : NULL;
100 mbox->umessage[msgno]->attr_flags |= MU_ATTRIBUTE_MODIFIED;
98 return 0; 101 return 0;
99 } 102 }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
25 int 25 int
26 mbox_get_size (mbox_t mbox, off_t *size) 26 mbox_get_size (mbox_t mbox, off_t *size)
27 { 27 {
28 mbox_debug_print (mbox, "get_size");
28 if (mbox && size) 29 if (mbox && size)
29 *size = mbox->size; 30 *size = mbox->size;
30 return 0; 31 return 0;
......
...@@ -36,7 +36,6 @@ struct _stream_mbox ...@@ -36,7 +36,6 @@ struct _stream_mbox
36 mbox_t mbox; 36 mbox_t mbox;
37 unsigned int msgno; 37 unsigned int msgno;
38 int is_header; 38 int is_header;
39 off_t offset;
40 }; 39 };
41 40
42 static int 41 static int
...@@ -52,21 +51,23 @@ _stream_mbox_destroy (stream_t *pstream) ...@@ -52,21 +51,23 @@ _stream_mbox_destroy (stream_t *pstream)
52 struct _stream_mbox *ms = (struct _stream_mbox *)*pstream; 51 struct _stream_mbox *ms = (struct _stream_mbox *)*pstream;
53 if (mu_refcount_dec (ms->refcount) == 0) 52 if (mu_refcount_dec (ms->refcount) == 0)
54 { 53 {
55 if (ms->msgno <= ms->mbox->messages_count)
56 {
57 mu_refcount_destroy (&ms->refcount); 54 mu_refcount_destroy (&ms->refcount);
58 if (ms->is_header) 55 if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
56 {
57 /* Loose the reference only if it is the same that we saved
58 on the mailbox. */
59 if (ms->is_header && ms == (struct _stream_mbox *)
60 (ms->mbox->umessages[ms->msgno - 1]->header.stream))
59 { 61 {
60 if (ms == (struct _stream_mbox *)ms->mbox->umessages[ms->msgno - 1]->header.stream)
61 ms->mbox->umessages[ms->msgno - 1]->header.stream = NULL; 62 ms->mbox->umessages[ms->msgno - 1]->header.stream = NULL;
62 } 63 }
63 else 64 else if (ms == (struct _stream_mbox *)
65 (ms->mbox->umessages[ms->msgno - 1]->body.stream))
64 { 66 {
65 if (ms == (struct _stream_mbox *)ms->mbox->umessages[ms->msgno - 1]->body.stream)
66 ms->mbox->umessages[ms->msgno - 1]->body.stream = NULL; 67 ms->mbox->umessages[ms->msgno - 1]->body.stream = NULL;
67 } 68 }
68 free (ms);
69 } 69 }
70 free (ms);
70 } 71 }
71 } 72 }
72 73
...@@ -85,44 +86,59 @@ _stream_mbox_close (stream_t stream) ...@@ -85,44 +86,59 @@ _stream_mbox_close (stream_t stream)
85 } 86 }
86 87
87 static int 88 static int
88 _stream_mbox_read (stream_t stream, void *buf, size_t buflen, size_t *pnread) 89 _stream_mbox_read0 (stream_t carrier, void *buf, size_t buflen, off_t off,
90 size_t *pn, off_t start, off_t end)
91 {
92 off_t ln = end - (start + off);
93 int status = 0;
94 if (ln > 0)
95 {
96 size_t n = min ((size_t)ln, buflen);
97 status = stream_read (carrier, buf, n, start + off, pn);
98 }
99 return status;
100 }
101
102 static int
103 _stream_mbox_read (stream_t stream, void *buf, size_t buflen, off_t off,
104 size_t *pnread)
89 { 105 {
90 int status = 0; 106 int status = 0;
91 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 107 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
92 size_t nread = 0; 108 size_t n = 0;
93 109
94 if (buf && buflen) 110 if (buf && buflen)
95 { 111 {
96 if (ms->msgno <= ms->mbox->messages_count) 112 if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
97 { 113 {
98 off_t ln; 114 mbox_message_t mum = ms->mbox->umessages[ms->msgno - 1];
99 mbox_message_t umessage = ms->mbox->umessages[ms->msgno - 1];
100 if (ms->is_header) 115 if (ms->is_header)
101 ln = umessage->header.end - (umessage->header.start + ms->offset); 116 status = _stream_mbox_read0 (ms->mbox->carrier, buf, buflen, off,
117 &n, mum->header.start,
118 mum->header.end);
102 else 119 else
103 ln = umessage->body.end - (umessage->body.start + ms->offset); 120 status = _stream_mbox_read0 (ms->mbox->carrier, buf, buflen, off,
121 &n, mum->header.start,
122 mum->header.end);
123 }
124 }
104 125
126 if (pnread)
127 *pnread = n;
128 return status;
129 }
130
131 static int
132 _stream_mbox_readline0 (stream_t carrier, char *buf, size_t buflen, off_t off,
133 size_t *pn, off_t start, off_t end)
134 {
135 off_t ln = end - (start + off);
136 int status = 0;
105 if (ln > 0) 137 if (ln > 0)
106 { 138 {
107 size_t n = min ((size_t)ln, buflen); 139 size_t n = min ((size_t)ln, buflen);
108 /* Position the file pointer. */ 140 status = stream_readline (carrier, buf, n, start + off, pn);
109 if (ms->is_header)
110 status = stream_seek (ms->mbox->carrier, umessage->header.start
111 + ms->offset, MU_STREAM_WHENCE_SET);
112 else
113 status = stream_seek (ms->mbox->carrier, umessage->body.start
114 + ms->offset, MU_STREAM_WHENCE_SET);
115 if (status == 0)
116 {
117 status = stream_read (ms->mbox->carrier, buf, n, &nread);
118 ms->offset += nread;
119 } 141 }
120 }
121 }
122 }
123
124 if (pnread)
125 *pnread = nread;
126 return status; 142 return status;
127 } 143 }
128 144
...@@ -131,7 +147,7 @@ _stream_mbox_read (stream_t stream, void *buf, size_t buflen, size_t *pnread) ...@@ -131,7 +147,7 @@ _stream_mbox_read (stream_t stream, void *buf, size_t buflen, size_t *pnread)
131 * Stop when a newline has been read, or the count runs out. 147 * Stop when a newline has been read, or the count runs out.
132 */ 148 */
133 static int 149 static int
134 _stream_mbox_readline (stream_t stream, char *buf, size_t buflen, 150 _stream_mbox_readline (stream_t stream, char *buf, size_t buflen, off_t off,
135 size_t *pnread) 151 size_t *pnread)
136 { 152 {
137 int status = 0; 153 int status = 0;
...@@ -140,31 +156,17 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen, ...@@ -140,31 +156,17 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen,
140 156
141 if (buf && buflen) 157 if (buf && buflen)
142 { 158 {
143 if (ms->msgno <= ms->mbox->messages_count) 159 if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
144 { 160 {
145 off_t ln; 161 mbox_message_t mum = ms->mbox->umessages[ms->msgno - 1];
146 mbox_message_t umessage = ms->mbox->umessages[ms->msgno - 1];
147 if (ms->is_header) 162 if (ms->is_header)
148 ln = umessage->header.end - (umessage->header.start + ms->offset); 163 status = _stream_mbox_readline0 (ms->mbox->carrier, buf, buflen,
164 off, &nread, mum->header.start,
165 mum->header.end);
149 else 166 else
150 ln = umessage->body.end - (umessage->body.start + ms->offset); 167 status = _stream_mbox_readline0 (ms->mbox->carrier, buf, buflen,
151 168 off, &nread, mum->body.start,
152 if (ln > 0) 169 mum->body.end);
153 {
154 size_t n = min ((size_t)ln, buflen);
155 /* Position the stream. */
156 if (ms->is_header)
157 status = stream_seek (ms->mbox->carrier, umessage->header.start
158 + ms->offset, MU_STREAM_WHENCE_SET);
159 else
160 status = stream_seek (ms->mbox->carrier, umessage->body.start
161 + ms->offset, MU_STREAM_WHENCE_SET);
162 if (status == 0)
163 {
164 status = stream_readline (ms->mbox->carrier, buf, n, &nread);
165 ms->offset += nread;
166 }
167 }
168 } 170 }
169 } 171 }
170 172
...@@ -174,10 +176,10 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen, ...@@ -174,10 +176,10 @@ _stream_mbox_readline (stream_t stream, char *buf, size_t buflen,
174 } 176 }
175 177
176 static int 178 static int
177 _stream_mbox_write (stream_t stream, const void *buf, size_t count, 179 _stream_mbox_write (stream_t stream, const void *buf, size_t buflen, off_t off,
178 size_t *pnwrite) 180 size_t *pnwrite)
179 { 181 {
180 (void)stream; (void)buf; (void)count; (void)pnwrite; 182 (void)stream; (void)buf; (void)buflen; (void)off, (void)pnwrite;
181 return MU_ERROR_IO; 183 return MU_ERROR_IO;
182 } 184 }
183 185
...@@ -185,14 +187,18 @@ static int ...@@ -185,14 +187,18 @@ static int
185 _stream_mbox_get_fd (stream_t stream, int *pfd) 187 _stream_mbox_get_fd (stream_t stream, int *pfd)
186 { 188 {
187 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 189 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
190 if (ms->mbox)
188 return stream_get_fd (ms->mbox->carrier, pfd); 191 return stream_get_fd (ms->mbox->carrier, pfd);
192 return MU_ERROR_IO;
189 } 193 }
190 194
191 static int 195 static int
192 _stream_mbox_get_flags (stream_t stream, int *pfl) 196 _stream_mbox_get_flags (stream_t stream, int *pfl)
193 { 197 {
194 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 198 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
199 if (ms->mbox)
195 return stream_get_flags (ms->mbox->carrier, pfl); 200 return stream_get_flags (ms->mbox->carrier, pfl);
201 return MU_ERROR_IO;
196 } 202 }
197 203
198 static int 204 static int
...@@ -202,7 +208,7 @@ _stream_mbox_get_size (stream_t stream, off_t *psize) ...@@ -202,7 +208,7 @@ _stream_mbox_get_size (stream_t stream, off_t *psize)
202 208
203 if (psize) 209 if (psize)
204 { 210 {
205 if (ms->msgno <= ms->mbox->messages_count) 211 if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
206 { 212 {
207 if (ms->is_header) 213 if (ms->is_header)
208 *psize = ms->mbox->umessages[ms->msgno - 1]->header.end 214 *psize = ms->mbox->umessages[ms->msgno - 1]->header.end
...@@ -211,6 +217,8 @@ _stream_mbox_get_size (stream_t stream, off_t *psize) ...@@ -211,6 +217,8 @@ _stream_mbox_get_size (stream_t stream, off_t *psize)
211 *psize = ms->mbox->umessages[ms->msgno - 1]->body.end 217 *psize = ms->mbox->umessages[ms->msgno - 1]->body.end
212 - ms->mbox->umessages[ms->msgno - 1]->body.start; 218 - ms->mbox->umessages[ms->msgno - 1]->body.start;
213 } 219 }
220 else
221 *psize = 0;
214 } 222 }
215 return 0; 223 return 0;
216 } 224 }
...@@ -233,49 +241,36 @@ static int ...@@ -233,49 +241,36 @@ static int
233 _stream_mbox_get_state (stream_t stream, enum stream_state *pstate) 241 _stream_mbox_get_state (stream_t stream, enum stream_state *pstate)
234 { 242 {
235 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 243 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
244 if (ms->mbox)
236 return stream_get_state (ms->mbox->carrier, pstate); 245 return stream_get_state (ms->mbox->carrier, pstate);
246 return MU_ERROR_IO;
237 } 247 }
238 248
239 static int 249 static int
240 _stream_mbox_seek (stream_t stream, off_t off, enum stream_whence whence) 250 _stream_mbox_is_seekable (stream_t stream)
241 { 251 {
242 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 252 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
243 off_t noff = ms->offset; 253 if (ms->mbox)
244 int err = 0; 254 return stream_is_seekable (ms->mbox->carrier);
245 if (whence == MU_STREAM_WHENCE_SET) 255 return MU_ERROR_IO;
246 noff = off;
247 else if (whence == MU_STREAM_WHENCE_CUR)
248 noff += off;
249 else if (whence == MU_STREAM_WHENCE_END)
250 {
251 off_t size = 0;
252 _stream_mbox_get_size (stream, &size);
253 noff = size + off;
254 }
255 else
256 noff = -1; /* error. */
257 if (noff >= 0)
258 ms->offset = noff;
259 else
260 err = MU_ERROR_INVALID_PARAMETER;
261 return err;
262 } 256 }
263 257
264 static int 258 static int
265 _stream_mbox_tell (stream_t stream, off_t *off) 259 _stream_mbox_tell (stream_t stream, off_t *off)
266 { 260 {
267 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 261 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
268 if (off == NULL) 262 if (ms->mbox)
269 return MU_ERROR_INVALID_PARAMETER; 263 return stream_tell (ms->mbox->carrier, off);
270 *off = ms->offset; 264 return MU_ERROR_IO;
271 return 0;
272 } 265 }
273 266
274 static int 267 static int
275 _stream_mbox_is_readready (stream_t stream, int timeout) 268 _stream_mbox_is_readready (stream_t stream, int timeout)
276 { 269 {
277 (void)timeout; 270 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
278 return stream_is_open (stream); 271 if (ms->mbox)
272 return stream_is_readready (ms->mbox->carrier, timeout);
273 return MU_ERROR_IO;
279 } 274 }
280 275
281 static int 276 static int
...@@ -296,7 +291,9 @@ static int ...@@ -296,7 +291,9 @@ static int
296 _stream_mbox_is_open (stream_t stream) 291 _stream_mbox_is_open (stream_t stream)
297 { 292 {
298 struct _stream_mbox *ms = (struct _stream_mbox *)stream; 293 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
294 if (ms->mbox)
299 return stream_is_open (ms->mbox->carrier); 295 return stream_is_open (ms->mbox->carrier);
296 return MU_ERROR_IO;
300 } 297 }
301 298
302 299
...@@ -312,7 +309,6 @@ static struct _stream_vtable _stream_mbox_vtable = ...@@ -312,7 +309,6 @@ static struct _stream_vtable _stream_mbox_vtable =
312 _stream_mbox_readline, 309 _stream_mbox_readline,
313 _stream_mbox_write, 310 _stream_mbox_write,
314 311
315 _stream_mbox_seek,
316 _stream_mbox_tell, 312 _stream_mbox_tell,
317 313
318 _stream_mbox_get_size, 314 _stream_mbox_get_size,
...@@ -323,6 +319,7 @@ static struct _stream_vtable _stream_mbox_vtable = ...@@ -323,6 +319,7 @@ static struct _stream_vtable _stream_mbox_vtable =
323 _stream_mbox_get_flags, 319 _stream_mbox_get_flags,
324 _stream_mbox_get_state, 320 _stream_mbox_get_state,
325 321
322 _stream_mbox_is_seekable,
326 _stream_mbox_is_readready, 323 _stream_mbox_is_readready,
327 _stream_mbox_is_writeready, 324 _stream_mbox_is_writeready,
328 _stream_mbox_is_exceptionpending, 325 _stream_mbox_is_exceptionpending,
...@@ -334,24 +331,50 @@ static int ...@@ -334,24 +331,50 @@ static int
334 _stream_mbox_ctor (struct _stream_mbox *ms, mbox_t mbox, unsigned int msgno, 331 _stream_mbox_ctor (struct _stream_mbox *ms, mbox_t mbox, unsigned int msgno,
335 int is_header) 332 int is_header)
336 { 333 {
337 mu_refcount_create (&(ms->refcount)); 334 mu_refcount_create (&ms->refcount);
338 if (ms->refcount == NULL) 335 if (ms->refcount == NULL)
339 return MU_ERROR_NO_MEMORY; 336 return MU_ERROR_NO_MEMORY;
340 337
341 ms->mbox = mbox; 338 ms->mbox = mbox;
342 ms->msgno = msgno; 339 ms->msgno = msgno;
343 ms->offset = 0;
344 ms->is_header = is_header; 340 ms->is_header = is_header;
345 ms->base.vtable = &_stream_mbox_vtable; 341 ms->base.vtable = &_stream_mbox_vtable;
346 return 0; 342 return 0;
347 } 343 }
348 344
349 /* 345 void
350 static void 346 _stream_mbox_dtor (stream_t stream)
351 _stream_mbox_dtor (struct _stream_mbox *ms)
352 { 347 {
348 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
349 mu_refcount_destroy (&ms->refcount);
350 if (ms->mbox && ms->msgno && ms->msgno <= ms->mbox->messages_count)
351 {
352 /* Loose the reference only if it is the same that we saved
353 on the mailbox. */
354 if (ms->is_header && ms == (struct _stream_mbox *)
355 (ms->mbox->umessages[ms->msgno - 1]->header.stream))
356 {
357 ms->mbox->umessages[ms->msgno - 1]->header.stream = NULL;
358 }
359 else if (ms == (struct _stream_mbox *)
360 (ms->mbox->umessages[ms->msgno - 1]->body.stream))
361 {
362 ms->mbox->umessages[ms->msgno - 1]->body.stream = NULL;
363 }
364 }
365 ms->mbox = NULL;
366 ms->msgno = 0;
367 ms->is_header = 0;
368 }
369
370 int
371 stream_mbox_msgno (stream_t stream, unsigned int msgno)
372 {
373 struct _stream_mbox *ms = (struct _stream_mbox *)stream;
374 if (ms)
375 ms->msgno = msgno;
376 return 0;
353 } 377 }
354 */
355 378
356 int 379 int
357 stream_mbox_create (stream_t *pstream, mbox_t mbox, unsigned int msgno, 380 stream_mbox_create (stream_t *pstream, mbox_t mbox, unsigned int msgno,
......
...@@ -26,6 +26,8 @@ int ...@@ -26,6 +26,8 @@ int
26 mbox_get_uid (mbox_t mbox, unsigned int msgno, unsigned long *puid) 26 mbox_get_uid (mbox_t mbox, unsigned int msgno, unsigned long *puid)
27 { 27 {
28 28
29 mbox_debug_print (mbox, "get_uid(%u)", msgno);
30
29 if (mbox == NULL || msgno == 0 || puid == NULL) 31 if (mbox == NULL || msgno == 0 || puid == NULL)
30 return MU_ERROR_INVALID_PARAMETER; 32 return MU_ERROR_INVALID_PARAMETER;
31 33
......
...@@ -26,6 +26,8 @@ int ...@@ -26,6 +26,8 @@ int
26 mbox_get_uidnext (mbox_t mbox, unsigned long *puidnext) 26 mbox_get_uidnext (mbox_t mbox, unsigned long *puidnext)
27 { 27 {
28 28
29 mbox_debug_print (mbox, "get_uidnext");
30
29 if (mbox == NULL || puidnext == NULL) 31 if (mbox == NULL || puidnext == NULL)
30 return MU_ERROR_INVALID_PARAMETER; 32 return MU_ERROR_INVALID_PARAMETER;
31 33
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
25 int 25 int
26 mbox_get_uidvalidity (mbox_t mbox, unsigned long *puidvalidity) 26 mbox_get_uidvalidity (mbox_t mbox, unsigned long *puidvalidity)
27 { 27 {
28
29 mbox_debug_print (mbox, "get_uidvalidity");
30
28 if (mbox == NULL || puidvalidity == NULL) 31 if (mbox == NULL || puidvalidity == NULL)
29 return MU_ERROR_INVALID_PARAMETER; 32 return MU_ERROR_INVALID_PARAMETER;
30 33
......
...@@ -117,10 +117,10 @@ MD5_CTX *context; /* context */ ...@@ -117,10 +117,10 @@ MD5_CTX *context; /* context */
117 unsigned char *input; /* input block */ 117 unsigned char *input; /* input block */
118 unsigned int inputLen; /* length of input block */ 118 unsigned int inputLen; /* length of input block */
119 { 119 {
120 unsigned int i, index, partLen; 120 unsigned int i, indx, partLen;
121 121
122 /* Compute number of bytes mod 64 */ 122 /* Compute number of bytes mod 64 */
123 index = (unsigned int)((context->count[0] >> 3) & 0x3F); 123 indx = (unsigned int)((context->count[0] >> 3) & 0x3F);
124 124
125 /* Update number of bits */ 125 /* Update number of bits */
126 if ((context->count[0] += ((UINT4)inputLen << 3)) 126 if ((context->count[0] += ((UINT4)inputLen << 3))
...@@ -128,26 +128,26 @@ unsigned int inputLen; /* length of input block */ ...@@ -128,26 +128,26 @@ unsigned int inputLen; /* length of input block */
128 context->count[1]++; 128 context->count[1]++;
129 context->count[1] += ((UINT4)inputLen >> 29); 129 context->count[1] += ((UINT4)inputLen >> 29);
130 130
131 partLen = 64 - index; 131 partLen = 64 - indx;
132 132
133 /* Transform as many times as possible. 133 /* Transform as many times as possible.
134 */ 134 */
135 if (inputLen >= partLen) { 135 if (inputLen >= partLen) {
136 MD5_memcpy 136 MD5_memcpy
137 ((POINTER)&context->buffer[index], (POINTER)input, partLen); 137 ((POINTER)&context->buffer[indx], (POINTER)input, partLen);
138 MD5Transform (context->state, context->buffer); 138 MD5Transform (context->state, context->buffer);
139 139
140 for (i = partLen; i + 63 < inputLen; i += 64) 140 for (i = partLen; i + 63 < inputLen; i += 64)
141 MD5Transform (context->state, &input[i]); 141 MD5Transform (context->state, &input[i]);
142 142
143 index = 0; 143 indx = 0;
144 } 144 }
145 else 145 else
146 i = 0; 146 i = 0;
147 147
148 /* Buffer remaining input */ 148 /* Buffer remaining input */
149 MD5_memcpy 149 MD5_memcpy
150 ((POINTER)&context->buffer[index], (POINTER)&input[i], 150 ((POINTER)&context->buffer[indx], (POINTER)&input[i],
151 inputLen-i); 151 inputLen-i);
152 } 152 }
153 153
...@@ -159,15 +159,15 @@ unsigned char digest[16]; /* message digest */ ...@@ -159,15 +159,15 @@ unsigned char digest[16]; /* message digest */
159 MD5_CTX *context; /* context */ 159 MD5_CTX *context; /* context */
160 { 160 {
161 unsigned char bits[8]; 161 unsigned char bits[8];
162 unsigned int index, padLen; 162 unsigned int indx, padLen;
163 163
164 /* Save number of bits */ 164 /* Save number of bits */
165 Encode (bits, context->count, 8); 165 Encode (bits, context->count, 8);
166 166
167 /* Pad out to 56 mod 64. 167 /* Pad out to 56 mod 64.
168 */ 168 */
169 index = (unsigned int)((context->count[0] >> 3) & 0x3f); 169 indx = (unsigned int)((context->count[0] >> 3) & 0x3f);
170 padLen = (index < 56) ? (56 - index) : (120 - index); 170 padLen = (indx < 56) ? (56 - indx) : (120 - indx);
171 MD5Update (context, PADDING, padLen); 171 MD5Update (context, PADDING, padLen);
172 172
173 /* Append length (before padding) */ 173 /* Append length (before padding) */
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
29 #include <mailutils/error.h> 29 #include <mailutils/error.h>
30 #include <mailutils/sys/memstream.h> 30 #include <mailutils/sys/memstream.h>
31 31
32 #undef min
33 #define min(a,b) ((a) < (b) ? (a) : (b))
34
32 int 35 int
33 _stream_memory_ref (stream_t stream) 36 _stream_memory_ref (stream_t stream)
34 { 37 {
...@@ -48,18 +51,18 @@ _stream_memory_destroy (stream_t *pstream) ...@@ -48,18 +51,18 @@ _stream_memory_destroy (stream_t *pstream)
48 } 51 }
49 52
50 int 53 int
51 _stream_memory_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) 54 _stream_memory_read (stream_t stream, void *optr, size_t osize,
55 off_t offset, size_t *nbytes)
52 { 56 {
53 struct _stream_memory *mem = (struct _stream_memory *)stream; 57 struct _stream_memory *mem = (struct _stream_memory *)stream;
54 size_t n = 0; 58 size_t n = 0;
55 59
56 mu_refcount_lock (mem->refcount); 60 mu_refcount_lock (mem->refcount);
57 if (mem->ptr != NULL && (mem->offset < (off_t)mem->size)) 61 if (mem->ptr != NULL && (offset < (off_t)mem->size))
58 { 62 {
59 n = ((mem->offset + osize) > mem->size) ? 63 n = ((offset + osize) > mem->size) ?
60 mem->size - mem->offset : osize; 64 mem->size - offset : osize;
61 memcpy (optr, mem->ptr + mem->offset, n); 65 memcpy (optr, mem->ptr + offset, n);
62 mem->offset += n;
63 } 66 }
64 mu_refcount_unlock (mem->refcount); 67 mu_refcount_unlock (mem->refcount);
65 if (nbytes) 68 if (nbytes)
...@@ -68,22 +71,22 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, size_t *nbytes) ...@@ -68,22 +71,22 @@ _stream_memory_read (stream_t stream, void *optr, size_t osize, size_t *nbytes)
68 } 71 }
69 72
70 int 73 int
71 _stream_memory_readline (stream_t stream, char *optr, size_t osize, size_t *nbytes) 74 _stream_memory_readline (stream_t stream, char *optr, size_t osize,
75 off_t offset, size_t *nbytes)
72 { 76 {
73 struct _stream_memory *mem = (struct _stream_memory *)stream; 77 struct _stream_memory *mem = (struct _stream_memory *)stream;
74 char *nl; 78 char *nl;
75 size_t n = 0; 79 size_t n = 0;
76 mu_refcount_lock (mem->refcount); 80 mu_refcount_lock (mem->refcount);
77 if (mem->ptr && (mem->offset < (off_t)mem->size)) 81 if (mem->ptr && (offset < (off_t)mem->size))
78 { 82 {
79 /* Save space for the null byte. */ 83 /* Save space for the null byte. */
80 osize--; 84 osize--;
81 nl = memchr (mem->ptr + mem->offset, '\n', mem->size - mem->offset); 85 nl = memchr (mem->ptr + offset, '\n', mem->size - offset);
82 n = (nl) ? nl - (mem->ptr + mem->offset) + 1 : mem->size - mem->offset; 86 n = (nl) ? (size_t)(nl - (mem->ptr + offset) + 1) : mem->size - offset;
83 n = (n > osize) ? osize : n; 87 n = min (n, osize);
84 memcpy (optr, mem->ptr + mem->offset, n); 88 memcpy (optr, mem->ptr + offset, n);
85 optr[n] = '\0'; 89 optr[n] = '\0';
86 mem->offset += n;
87 } 90 }
88 mu_refcount_unlock (mem->refcount); 91 mu_refcount_unlock (mem->refcount);
89 if (nbytes) 92 if (nbytes)
...@@ -93,27 +96,26 @@ _stream_memory_readline (stream_t stream, char *optr, size_t osize, size_t *nbyt ...@@ -93,27 +96,26 @@ _stream_memory_readline (stream_t stream, char *optr, size_t osize, size_t *nbyt
93 96
94 int 97 int
95 _stream_memory_write (stream_t stream, const void *iptr, size_t isize, 98 _stream_memory_write (stream_t stream, const void *iptr, size_t isize,
96 size_t *nbytes) 99 off_t offset, size_t *nbytes)
97 { 100 {
98 struct _stream_memory *mem = (struct _stream_memory *)stream; 101 struct _stream_memory *mem = (struct _stream_memory *)stream;
99 102
100 mu_refcount_lock (mem->refcount); 103 mu_refcount_lock (mem->refcount);
101 /* Bigger we have to realloc. */ 104 /* Bigger we have to realloc. */
102 if (mem->capacity < (mem->offset + isize)) 105 if (mem->capacity < (offset + isize))
103 { 106 {
104 /* Realloc by blocks of 512. */ 107 /* Realloc by blocks of 512. */
105 int newsize = MU_STREAM_MEMORY_BLOCKSIZE * 108 int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
106 (((mem->offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1); 109 (((offset + isize)/MU_STREAM_MEMORY_BLOCKSIZE) + 1);
107 char *tmp = realloc (mem->ptr, newsize); 110 char *tmp = realloc (mem->ptr, newsize);
108 if (tmp == NULL) 111 if (tmp == NULL)
109 return ENOMEM; 112 return ENOMEM;
110 mem->ptr = tmp; 113 mem->ptr = tmp;
111 mem->size = mem->offset + isize; 114 mem->size = offset + isize;
112 mem->capacity = newsize; 115 mem->capacity = newsize;
113 } 116 }
114 117
115 memcpy (mem->ptr + mem->offset, iptr, isize); 118 memcpy (mem->ptr + offset, iptr, isize);
116 mem->offset += isize;
117 mu_refcount_unlock (mem->refcount); 119 mu_refcount_unlock (mem->refcount);
118 if (nbytes) 120 if (nbytes)
119 *nbytes = isize; 121 *nbytes = isize;
...@@ -140,7 +142,6 @@ _stream_memory_truncate (stream_t stream, off_t len) ...@@ -140,7 +142,6 @@ _stream_memory_truncate (stream_t stream, off_t len)
140 } 142 }
141 mem->capacity = len; 143 mem->capacity = len;
142 mem->size = len; 144 mem->size = len;
143 mem->offset = len;
144 mu_refcount_unlock (mem->refcount); 145 mu_refcount_unlock (mem->refcount);
145 return 0; 146 return 0;
146 } 147 }
...@@ -166,7 +167,6 @@ _stream_memory_close (stream_t stream) ...@@ -166,7 +167,6 @@ _stream_memory_close (stream_t stream)
166 mem->ptr = NULL; 167 mem->ptr = NULL;
167 mem->capacity = 0; 168 mem->capacity = 0;
168 mem->size = 0; 169 mem->size = 0;
169 mem->offset = 0;
170 mu_refcount_unlock (mem->refcount); 170 mu_refcount_unlock (mem->refcount);
171 return 0; 171 return 0;
172 } 172 }
...@@ -206,37 +206,19 @@ _stream_memory_get_state (stream_t stream, enum stream_state *state) ...@@ -206,37 +206,19 @@ _stream_memory_get_state (stream_t stream, enum stream_state *state)
206 } 206 }
207 207
208 int 208 int
209 _stream_memory_seek (stream_t stream, off_t off, enum stream_whence whence) 209 _stream_memory_is_seekable (stream_t stream)
210 { 210 {
211 struct _stream_memory *mem = (struct _stream_memory *)stream; 211 (void)stream;
212 off_t noff = mem->offset; 212 return 1;
213 int err = 0;
214 if (whence == MU_STREAM_WHENCE_SET)
215 noff = off;
216 else if (whence == MU_STREAM_WHENCE_CUR)
217 noff += off;
218 else if (whence == MU_STREAM_WHENCE_END)
219 noff = mem->size + off;
220 else
221 noff = -1; /* error. */
222 if (noff >= 0)
223 {
224 if (noff > mem->offset)
225 _stream_memory_truncate (stream, noff);
226 mem->offset = noff;
227 }
228 else
229 err = MU_ERROR_INVALID_PARAMETER;
230 return err;
231 } 213 }
232 214
233 int 215 int
234 _stream_memory_tell (stream_t stream, off_t *off) 216 _stream_memory_tell (stream_t stream, off_t *off)
235 { 217 {
236 struct _stream_memory *mem = (struct _stream_memory *)stream; 218 (void)stream;
237 if (off == NULL) 219 if (off == NULL)
238 return MU_ERROR_INVALID_PARAMETER; 220 return MU_ERROR_INVALID_PARAMETER;
239 *off = mem->offset; 221 *off = 0;
240 return 0; 222 return 0;
241 } 223 }
242 224
...@@ -288,7 +270,6 @@ _stream_memory_open (stream_t stream, const char *filename, int port, ...@@ -288,7 +270,6 @@ _stream_memory_open (stream_t stream, const char *filename, int port,
288 mem->ptr = NULL; 270 mem->ptr = NULL;
289 mem->capacity = 0; 271 mem->capacity = 0;
290 mem->size = 0; 272 mem->size = 0;
291 mem->offset = 0;
292 mem->flags = flags; 273 mem->flags = flags;
293 if (filename) 274 if (filename)
294 { 275 {
...@@ -341,7 +322,6 @@ static struct _stream_vtable _stream_memory_vtable = ...@@ -341,7 +322,6 @@ static struct _stream_vtable _stream_memory_vtable =
341 _stream_memory_readline, 322 _stream_memory_readline,
342 _stream_memory_write, 323 _stream_memory_write,
343 324
344 _stream_memory_seek,
345 _stream_memory_tell, 325 _stream_memory_tell,
346 326
347 _stream_memory_get_size, 327 _stream_memory_get_size,
...@@ -352,6 +332,7 @@ static struct _stream_vtable _stream_memory_vtable = ...@@ -352,6 +332,7 @@ static struct _stream_vtable _stream_memory_vtable =
352 _stream_memory_get_flags, 332 _stream_memory_get_flags,
353 _stream_memory_get_state, 333 _stream_memory_get_state,
354 334
335 _stream_memory_is_seekable,
355 _stream_memory_is_readready, 336 _stream_memory_is_readready,
356 _stream_memory_is_writeready, 337 _stream_memory_is_writeready,
357 _stream_memory_is_exceptionpending, 338 _stream_memory_is_exceptionpending,
...@@ -378,21 +359,23 @@ _stream_memory_ctor (struct _stream_memory *mem, size_t capacity) ...@@ -378,21 +359,23 @@ _stream_memory_ctor (struct _stream_memory *mem, size_t capacity)
378 else 359 else
379 mem->capacity = 0; 360 mem->capacity = 0;
380 mem->size = 0; 361 mem->size = 0;
381 mem->offset = 0;
382 mem->flags = 0; 362 mem->flags = 0;
383 mem->base.vtable = &_stream_memory_vtable; 363 mem->base.vtable = &_stream_memory_vtable;
384 return 0; 364 return 0;
385 } 365 }
386 366
387 void 367 void
388 _stream_memory_dtor (struct _stream_memory *mem) 368 _stream_memory_dtor (stream_t stream)
389 { 369 {
370 struct _stream_memory *mem = (struct _stream_memory *)stream;
371 if (mem)
372 {
390 mu_refcount_destroy (&mem->refcount); 373 mu_refcount_destroy (&mem->refcount);
391 mem->ptr = NULL; 374 mem->ptr = NULL;
392 mem->capacity = 0; 375 mem->capacity = 0;
393 mem->size = 0; 376 mem->size = 0;
394 mem->offset = 0;
395 mem->flags = 0; 377 mem->flags = 0;
378 }
396 } 379 }
397 380
398 int 381 int
......
...@@ -63,6 +63,8 @@ pop3_get_carrier (pop3_t pop3, stream_t *pcarrier) ...@@ -63,6 +63,8 @@ pop3_get_carrier (pop3_t pop3, stream_t *pcarrier)
63 return status; 63 return status;
64 } 64 }
65 } 65 }
66 /* Since we expose the stream incremente the reference count. */
67 stream_ref (pop3->carrier);
66 *pcarrier = pop3->carrier; 68 *pcarrier = pop3->carrier;
67 return 0; 69 return 0;
68 } 70 }
......
...@@ -60,6 +60,8 @@ pop3_connect (pop3_t pop3, const char *host, unsigned int port) ...@@ -60,6 +60,8 @@ pop3_connect (pop3_t pop3, const char *host, unsigned int port)
60 stream_t carrier; 60 stream_t carrier;
61 status = pop3_get_carrier (pop3, &carrier); 61 status = pop3_get_carrier (pop3, &carrier);
62 POP3_CHECK_ERROR (pop3, status); 62 POP3_CHECK_ERROR (pop3, status);
63 /* An stream_ref was done in po3_get_carrier (). */
64 stream_destroy (&carrier);
63 } 65 }
64 else 66 else
65 { 67 {
......
...@@ -44,6 +44,7 @@ pop3_get_debug (pop3_t pop3, mu_debug_t *pdebug) ...@@ -44,6 +44,7 @@ pop3_get_debug (pop3_t pop3, mu_debug_t *pdebug)
44 if (status != 0) 44 if (status != 0)
45 return status; 45 return status;
46 } 46 }
47 mu_debug_ref (pop3->debug);
47 *pdebug = pop3->debug; 48 *pdebug = pop3->debug;
48 return 0; 49 return 0;
49 } 50 }
......
...@@ -50,9 +50,10 @@ pop3_getline (pop3_t pop3) ...@@ -50,9 +50,10 @@ pop3_getline (pop3_t pop3)
50 } 50 }
51 51
52 status = stream_readline (pop3->carrier, pop3->io.buf + total, 52 status = stream_readline (pop3->carrier, pop3->io.buf + total,
53 pop3->io.len - total, &n); 53 pop3->io.len - total, pop3->offset, &n);
54 if (status != 0) 54 if (status != 0)
55 return status; 55 return status;
56 pop3->offset += n;
56 57
57 /* The server went away: It maybe a timeout and some pop server 58 /* The server went away: It maybe a timeout and some pop server
58 does not send the -ERR. Consider this like an error. */ 59 does not send the -ERR. Consider this like an error. */
...@@ -118,7 +119,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread) ...@@ -118,7 +119,7 @@ pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
118 { 119 {
119 size_t nread = 0; 120 size_t nread = 0;
120 size_t n = 0; 121 size_t n = 0;
121 int status; 122 int status = 0;
122 123
123 /* Do we need to fill up? Yes if no NL or the buffer is empty. */ 124 /* Do we need to fill up? Yes if no NL or the buffer is empty. */
124 if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf)) 125 if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
......
...@@ -54,7 +54,7 @@ pop3_send (pop3_t pop3) ...@@ -54,7 +54,7 @@ pop3_send (pop3_t pop3)
54 return MU_ERROR_TIMEOUT; 54 return MU_ERROR_TIMEOUT;
55 } 55 }
56 56
57 status = stream_write (pop3->carrier, pop3->io.buf, len, &n); 57 status = stream_write (pop3->carrier, pop3->io.buf, len, 0, &n);
58 if (n) 58 if (n)
59 { 59 {
60 /* Consume what we sent. */ 60 /* Consume what we sent. */
......
...@@ -34,11 +34,10 @@ static void p_destroy __P ((stream_t *)); ...@@ -34,11 +34,10 @@ static void p_destroy __P ((stream_t *));
34 static int p_open __P ((stream_t, const char *, int, int)); 34 static int p_open __P ((stream_t, const char *, int, int));
35 static int p_close __P ((stream_t)); 35 static int p_close __P ((stream_t));
36 36
37 static int p_read __P ((stream_t, void *, size_t, size_t *)); 37 static int p_read __P ((stream_t, void *, size_t, off_t, size_t *));
38 static int p_readline __P ((stream_t, char *, size_t, size_t *)); 38 static int p_readline __P ((stream_t, char *, size_t, off_t, size_t *));
39 static int p_write __P ((stream_t, const void *, size_t, size_t *)); 39 static int p_write __P ((stream_t, const void *, size_t, off_t, size_t *));
40 40
41 static int p_seek __P ((stream_t, off_t, enum stream_whence));
42 static int p_tell __P ((stream_t, off_t *)); 41 static int p_tell __P ((stream_t, off_t *));
43 42
44 static int p_get_size __P ((stream_t, off_t *)); 43 static int p_get_size __P ((stream_t, off_t *));
...@@ -49,6 +48,7 @@ static int p_get_fd __P ((stream_t, int *)); ...@@ -49,6 +48,7 @@ static int p_get_fd __P ((stream_t, int *));
49 static int p_get_flags __P ((stream_t, int *)); 48 static int p_get_flags __P ((stream_t, int *));
50 static int p_get_state __P ((stream_t, enum stream_state *)); 49 static int p_get_state __P ((stream_t, enum stream_state *));
51 50
51 static int p_is_seekable __P ((stream_t));
52 static int p_is_readready __P ((stream_t, int timeout)); 52 static int p_is_readready __P ((stream_t, int timeout));
53 static int p_is_writeready __P ((stream_t, int timeout)); 53 static int p_is_writeready __P ((stream_t, int timeout));
54 static int p_is_exceptionpending __P ((stream_t, int timeout)); 54 static int p_is_exceptionpending __P ((stream_t, int timeout));
...@@ -67,7 +67,6 @@ static struct _stream_vtable p_s_vtable = ...@@ -67,7 +67,6 @@ static struct _stream_vtable p_s_vtable =
67 p_readline, 67 p_readline,
68 p_write, 68 p_write,
69 69
70 p_seek,
71 p_tell, 70 p_tell,
72 71
73 p_get_size, 72 p_get_size,
...@@ -78,6 +77,7 @@ static struct _stream_vtable p_s_vtable = ...@@ -78,6 +77,7 @@ static struct _stream_vtable p_s_vtable =
78 p_get_flags, 77 p_get_flags,
79 p_get_state, 78 p_get_state,
80 79
80 p_is_seekable,
81 p_is_readready, 81 p_is_readready,
82 p_is_writeready, 82 p_is_writeready,
83 p_is_exceptionpending, 83 p_is_exceptionpending,
...@@ -151,12 +151,14 @@ p_close (stream_t stream) ...@@ -151,12 +151,14 @@ p_close (stream_t stream)
151 } 151 }
152 152
153 static int 153 static int
154 p_read (stream_t stream, void *buf, size_t buflen, size_t *pn) 154 p_read (stream_t stream, void *buf, size_t buflen, off_t offset, size_t *pn)
155 { 155 {
156 struct p_stream *p_stream = (struct p_stream *)stream; 156 struct p_stream *p_stream = (struct p_stream *)stream;
157 size_t n = 0; 157 size_t n = 0;
158 int status = 0; 158 int status = 0;
159 char *p = buf; 159 char *p = buf;
160
161 (void)offset;
160 if (p_stream) 162 if (p_stream)
161 { 163 {
162 mu_refcount_lock (p_stream->refcount); 164 mu_refcount_lock (p_stream->refcount);
...@@ -202,11 +204,14 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn) ...@@ -202,11 +204,14 @@ p_read (stream_t stream, void *buf, size_t buflen, size_t *pn)
202 } 204 }
203 205
204 static int 206 static int
205 p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn) 207 p_readline (stream_t stream, char *buf, size_t buflen, off_t offset,
208 size_t *pn)
206 { 209 {
207 struct p_stream *p_stream = (struct p_stream *)stream; 210 struct p_stream *p_stream = (struct p_stream *)stream;
208 size_t n = 0; 211 size_t n = 0;
209 int status = 0; 212 int status = 0;
213
214 (void)offset;
210 if (p_stream) 215 if (p_stream)
211 { 216 {
212 mu_refcount_lock (p_stream->refcount); 217 mu_refcount_lock (p_stream->refcount);
...@@ -227,17 +232,18 @@ p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn) ...@@ -227,17 +232,18 @@ p_readline (stream_t stream, char *buf, size_t buflen, size_t *pn)
227 } 232 }
228 233
229 static int 234 static int
230 p_write (stream_t stream, const void *buf, size_t buflen, size_t *pn) 235 p_write (stream_t stream, const void *buf, size_t buflen, off_t offset,
236 size_t *pn)
231 { 237 {
232 struct p_stream *p_stream = (struct p_stream *)stream; 238 struct p_stream *p_stream = (struct p_stream *)stream;
233 return stream_write (p_stream->pop3->carrier, buf, buflen, pn); 239 return stream_write (p_stream->pop3->carrier, buf, buflen, offset, pn);
234 } 240 }
235 241
236 static int 242 static int
237 p_seek (stream_t stream, off_t offset, enum stream_whence whence) 243 p_is_seekable (stream_t stream)
238 { 244 {
239 struct p_stream *p_stream = (struct p_stream *)stream; 245 struct p_stream *p_stream = (struct p_stream *)stream;
240 return stream_seek (p_stream->pop3->carrier, offset, whence); 246 return stream_is_seekable (p_stream->pop3->carrier);
241 } 247 }
242 248
243 static int 249 static int
......
...@@ -60,15 +60,22 @@ pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl) ...@@ -60,15 +60,22 @@ pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
60 *uidl = NULL; 60 *uidl = NULL;
61 { 61 {
62 char *space; 62 char *space;
63 /* Format: +OK msgno uidlstring */
64
63 /* Pass the "+OK". */ 65 /* Pass the "+OK". */
64 space = strchr (pop3->ack.buf, ' '); 66 space = strchr (pop3->ack.buf, ' ');
65 if (space) 67 if (space)
66 { 68 {
69 /* Skip spaces. */
70 while (*space == ' ') space++;
67 /* Pass the number. */ 71 /* Pass the number. */
68 space = strchr (space, ' '); 72 space = strchr (space, ' ');
69 if (space) 73 if (space)
70 { 74 {
71 size_t len = strlen (space); 75 size_t len;
76 /* Skip spaces between msgno and uidlstring */
77 while (*space == ' ') space++;
78 len = strlen (space);
72 if (space[len - 1] == '\n') 79 if (space[len - 1] == '\n')
73 { 80 {
74 space[len - 1] = '\0'; 81 space[len - 1] = '\0';
......
...@@ -83,17 +83,16 @@ pop3_uidl_current (iterator_t iterator, unsigned int *pno, char **puidl) ...@@ -83,17 +83,16 @@ pop3_uidl_current (iterator_t iterator, unsigned int *pno, char **puidl)
83 { 83 {
84 char *space; 84 char *space;
85 unsigned int msgno = 0; 85 unsigned int msgno = 0;
86
86 /* The format is: msgno uidlstring */ 87 /* The format is: msgno uidlstring */
87 space = strchr (buf, ' '); 88 msgno = strtoul (buf, &space, 10);
88 if (space)
89 {
90 *space++ = '\0';
91 msgno = strtoul (buf, NULL, 10);
92 }
93 if (space && space[strlen (space) - 1] == '\n') 89 if (space && space[strlen (space) - 1] == '\n')
94 space[strlen (space) - 1] = '\0'; 90 space[strlen (space) - 1] = '\0';
91
92 /* Oops. */
95 if (space == NULL) 93 if (space == NULL)
96 space = (char *)""; 94 space = (char *)"";
95
97 if (pno) 96 if (pno)
98 *pno = msgno; 97 *pno = msgno;
99 if (puidl) 98 if (puidl)
......
...@@ -90,6 +90,7 @@ pop3_t pop3; ...@@ -90,6 +90,7 @@ pop3_t pop3;
90 /* When non-zero, this global means the user is done using this program. */ 90 /* When non-zero, this global means the user is done using this program. */
91 int done; 91 int done;
92 92
93 #if 0
93 void * 94 void *
94 xmalloc (size_t size) 95 xmalloc (size_t size)
95 { 96 {
...@@ -101,6 +102,7 @@ xmalloc (size_t size) ...@@ -101,6 +102,7 @@ xmalloc (size_t size)
101 } 102 }
102 return m; 103 return m;
103 } 104 }
105 #endif
104 106
105 char * 107 char *
106 dupstr (const char *s) 108 dupstr (const char *s)
...@@ -371,6 +373,7 @@ com_uidl (char *arg) ...@@ -371,6 +373,7 @@ com_uidl (char *arg)
371 unsigned int msgno = strtoul (arg, NULL, 10); 373 unsigned int msgno = strtoul (arg, NULL, 10);
372 if (pop3_uidl (pop3, msgno, &uidl) == 0) 374 if (pop3_uidl (pop3, msgno, &uidl) == 0)
373 printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : ""); 375 printf ("Msg: %d UIDL: %s\n", msgno, (uidl) ? uidl : "");
376 free (uidl);
374 } 377 }
375 return 0; 378 return 0;
376 } 379 }
...@@ -549,7 +552,7 @@ com_top (char *arg) ...@@ -549,7 +552,7 @@ com_top (char *arg)
549 { 552 {
550 size_t n = 0; 553 size_t n = 0;
551 char buf[128]; 554 char buf[128];
552 while ((stream_readline (stream, buf, sizeof buf, &n) == 0) && n) 555 while ((stream_readline (stream, buf, sizeof buf, 0, &n) == 0) && n)
553 printf ("%s", buf); 556 printf ("%s", buf);
554 stream_destroy (&stream); 557 stream_destroy (&stream);
555 } 558 }
...@@ -573,7 +576,7 @@ com_retr (char *arg) ...@@ -573,7 +576,7 @@ com_retr (char *arg)
573 { 576 {
574 size_t n = 0; 577 size_t n = 0;
575 char buf[128]; 578 char buf[128];
576 while ((stream_readline (stream, buf, sizeof buf, &n) == 0) && n) 579 while ((stream_readline (stream, buf, sizeof buf, 0, &n) == 0) && n)
577 printf ("%s", buf); 580 printf ("%s", buf);
578 stream_destroy (&stream); 581 stream_destroy (&stream);
579 } 582 }
...@@ -600,6 +603,7 @@ com_connect (char *arg) ...@@ -600,6 +603,7 @@ com_connect (char *arg)
600 mu_debug_t debug; 603 mu_debug_t debug;
601 pop3_get_debug (pop3, &debug); 604 pop3_get_debug (pop3, &debug);
602 mu_debug_set_level (debug, MU_DEBUG_PROT); 605 mu_debug_set_level (debug, MU_DEBUG_PROT);
606 mu_debug_destroy (&debug);
603 pop3_connect (pop3, host, port); 607 pop3_connect (pop3, host, port);
604 } 608 }
605 else 609 else
......
...@@ -110,8 +110,10 @@ _ticket_prompt_ctor (struct _ticket_prompt *prompt) ...@@ -110,8 +110,10 @@ _ticket_prompt_ctor (struct _ticket_prompt *prompt)
110 } 110 }
111 111
112 void 112 void
113 _ticket_prompt_dtor (struct _ticket_prompt *prompt) 113 _ticket_prompt_dtor (ticket_t ticket)
114 { 114 {
115 struct _ticket_prompt *prompt = (struct _ticket_prompt *)ticket;
116 if (prompt)
115 mu_refcount_destroy (&prompt->refcount); 117 mu_refcount_destroy (&prompt->refcount);
116 } 118 }
117 119
......
...@@ -76,6 +76,8 @@ int ...@@ -76,6 +76,8 @@ int
76 _mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg) 76 _mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg)
77 { 77 {
78 struct _mu_debug_stream *sdebug = (struct _mu_debug_stream *)debug; 78 struct _mu_debug_stream *sdebug = (struct _mu_debug_stream *)debug;
79 size_t n = 0;
80 int status;
79 81
80 if (mesg == NULL) 82 if (mesg == NULL)
81 return MU_ERROR_INVALID_PARAMETER; 83 return MU_ERROR_INVALID_PARAMETER;
...@@ -83,7 +85,10 @@ _mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg) ...@@ -83,7 +85,10 @@ _mu_debug_stream_print (mu_debug_t debug, size_t level, const char *mesg)
83 if (!(sdebug->level & level)) 85 if (!(sdebug->level & level))
84 return 0; 86 return 0;
85 87
86 return stream_write (sdebug->stream, mesg, strlen (mesg), NULL); 88 status = stream_write (sdebug->stream, mesg, strlen (mesg), sdebug->offset,
89 &n);
90 sdebug->offset += n;
91 return status;
87 } 92 }
88 93
89 static struct _mu_debug_vtable _mu_debug_stream_vtable = 94 static struct _mu_debug_vtable _mu_debug_stream_vtable =
...@@ -117,6 +122,7 @@ mu_debug_stream_create (mu_debug_t *pdebug, stream_t stream, ...@@ -117,6 +122,7 @@ mu_debug_stream_create (mu_debug_t *pdebug, stream_t stream,
117 } 122 }
118 123
119 sdebug->level = 0; 124 sdebug->level = 0;
125 sdebug->offset = 0;
120 sdebug->stream = stream; 126 sdebug->stream = stream;
121 sdebug->close_on_destroy = close_on_destroy; 127 sdebug->close_on_destroy = close_on_destroy;
122 sdebug->base.vtable = &_mu_debug_stream_vtable; 128 sdebug->base.vtable = &_mu_debug_stream_vtable;
......
...@@ -63,39 +63,30 @@ stream_close (stream_t stream) ...@@ -63,39 +63,30 @@ stream_close (stream_t stream)
63 } 63 }
64 64
65 int 65 int
66 stream_read (stream_t stream, void *buf, size_t buflen, size_t *n) 66 stream_read (stream_t stream, void *buf, size_t buflen, off_t o, size_t *n)
67 { 67 {
68 if (stream == NULL || stream->vtable == NULL 68 if (stream == NULL || stream->vtable == NULL
69 || stream->vtable->read == NULL) 69 || stream->vtable->read == NULL)
70 return MU_ERROR_NOT_SUPPORTED; 70 return MU_ERROR_NOT_SUPPORTED;
71 return stream->vtable->read (stream, buf, buflen, n); 71 return stream->vtable->read (stream, buf, buflen, o, n);
72 } 72 }
73 73
74 int 74 int
75 stream_readline (stream_t stream, char *buf, size_t buflen, size_t *n) 75 stream_readline (stream_t stream, char *buf, size_t buflen, off_t o, size_t *n)
76 { 76 {
77 if (stream == NULL || stream->vtable == NULL 77 if (stream == NULL || stream->vtable == NULL
78 || stream->vtable->readline == NULL) 78 || stream->vtable->readline == NULL)
79 return MU_ERROR_NOT_SUPPORTED; 79 return MU_ERROR_NOT_SUPPORTED;
80 return stream->vtable->readline (stream, buf, buflen, n); 80 return stream->vtable->readline (stream, buf, buflen, o, n);
81 } 81 }
82 82
83 int 83 int
84 stream_write (stream_t stream, const void *buf, size_t buflen, size_t *n) 84 stream_write (stream_t stream, const void *buf, size_t buflen, off_t o, size_t *n)
85 { 85 {
86 if (stream == NULL || stream->vtable == NULL 86 if (stream == NULL || stream->vtable == NULL
87 || stream->vtable->write == NULL) 87 || stream->vtable->write == NULL)
88 return MU_ERROR_NOT_SUPPORTED; 88 return MU_ERROR_NOT_SUPPORTED;
89 return stream->vtable->write (stream, buf, buflen, n); 89 return stream->vtable->write (stream, buf, buflen, o, n);
90 }
91
92 int
93 stream_seek (stream_t stream, off_t off, enum stream_whence whence)
94 {
95 if (stream == NULL || stream->vtable == NULL
96 || stream->vtable->seek == NULL)
97 return MU_ERROR_NOT_SUPPORTED;
98 return stream->vtable->seek (stream, off, whence);
99 } 90 }
100 91
101 int 92 int
...@@ -162,6 +153,15 @@ stream_get_state (stream_t stream, enum stream_state *state) ...@@ -162,6 +153,15 @@ stream_get_state (stream_t stream, enum stream_state *state)
162 } 153 }
163 154
164 int 155 int
156 stream_is_seekable (stream_t stream)
157 {
158 if (stream == NULL || stream->vtable == NULL
159 || stream->vtable->is_seekable == NULL)
160 return MU_ERROR_NOT_SUPPORTED;
161 return stream->vtable->is_seekable (stream);
162 }
163
164 int
165 stream_is_readready (stream_t stream, int timeout) 165 stream_is_readready (stream_t stream, int timeout)
166 { 166 {
167 if (stream == NULL || stream->vtable == NULL 167 if (stream == NULL || stream->vtable == NULL
......
...@@ -55,7 +55,7 @@ _stream_tcp_destroy (stream_t *pstream) ...@@ -55,7 +55,7 @@ _stream_tcp_destroy (stream_t *pstream)
55 struct _stream_tcp *tcp = (struct _stream_tcp *)*pstream; 55 struct _stream_tcp *tcp = (struct _stream_tcp *)*pstream;
56 if (mu_refcount_dec (tcp->base.refcount) == 0) 56 if (mu_refcount_dec (tcp->base.refcount) == 0)
57 { 57 {
58 _stream_fd_dtor (&tcp->base); 58 _stream_fd_dtor (*pstream);
59 if (tcp->host) 59 if (tcp->host)
60 free (tcp->host); 60 free (tcp->host);
61 free (tcp); 61 free (tcp);
......