diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-09 13:06:58 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-10-09 13:26:18 +0300 |
commit | f3188dcc18d8de1192c87e7e0284800e9488b976 (patch) | |
tree | fed11275f4d8bbc28d8eb2239d93ddcba89fcb84 /libmailutils/base | |
parent | 37d7cd77d34cd4bf8d267b3010d923845fe74308 (diff) | |
download | mailutils-f3188dcc18d8de1192c87e7e0284800e9488b976.tar.gz mailutils-f3188dcc18d8de1192c87e7e0284800e9488b976.tar.bz2 |
Reorganize libmailutils directory structure.
* configure.ac (AC_CONFIG_FILES): Add libmailutils/ subdirs.
* include/mailutils/Makefile.am: Update references to libmailutils.
* po/POTFILES.in: Likewise.
* libmailutils/.gitignore: Update.
* libmailutils/Makefile.am: Use convenience libraries in subdirs.
* libmailutils/string/Makefile.am: New file.
* libmailutils/cstrcasecmp.c: Move to libmailutils/string.
* libmailutils/cstrlower.c: Likewise.
* libmailutils/cstrupper.c: Likewise.
* libmailutils/strltrim.c: Likewise.
* libmailutils/strskip.c: Likewise.
* libmailutils/stripws.c: Likewise.
* libmailutils/strrtrim.c: Likewise.
* libmailutils/asnprintf.c: Likewise.
* libmailutils/asprintf.c: Likewise.
* libmailutils/muctype.c: Likewise.
* libmailutils/vasnprintf.c: Likewise.
* libmailutils/mkfilename.c: Likewise.
* libmailutils/stream/Makefile.am: New file.
* libmailutils/dbgstream.c: Move to libmailutils/stream.
* libmailutils/file_stream.c: Likewise.
* libmailutils/fltstream.c: Likewise.
* libmailutils/iostream.c: Likewise.
* libmailutils/mapfile_stream.c: Likewise.
* libmailutils/memory_stream.c: Likewise.
* libmailutils/message_stream.c: Likewise.
* libmailutils/prog_stream.c: Likewise.
* libmailutils/rdcache_stream.c: Likewise.
* libmailutils/socket_stream.c: Likewise.
* libmailutils/stdio_stream.c: Likewise.
* libmailutils/stream.c: Likewise.
* libmailutils/stream_printf.c: Likewise.
* libmailutils/stream_vprintf.c: Likewise.
* libmailutils/streamcpy.c: Likewise.
* libmailutils/streamref.c: Likewise.
* libmailutils/tcp.c: Likewise.
* libmailutils/temp_file_stream.c: Likewise.
* libmailutils/xscript-stream.c
* libmailutils/cfg/Makefile.am: New file.
* libmailutils/cfg/.gitignore: New file.
* libmailutils/cfg_driver.c: Move to libmailutils/cfg/driver.c.
* libmailutils/cfg_format.c: Move to libmailutils/cfg/format.c.
* libmailutils/cfg_lexer.l: Move to libmailutils/cfg/lexer.l.
* libmailutils/cfg_parser.y: Move to libmailutils/cfg/parser.y.
* libmailutils/gocs.c: Move to libmailutils/cfg/gocs.c.
* libmailutils/diag/Makefile.am: New file.
* libmailutils/diag/.gitignore: New file.
* libmailutils/debug.c: Move to libmailutils/diag.
* libmailutils/diag.c: Likewise.
* libmailutils/gdebug.c: Likewise.
* libmailutils/errors: Likewise.
* libmailutils/muerrno.cin: Likewise.
* libmailutils/syslog.c: Likewise.
* libmailutils/dbgstderr.c: Likewise.
* libmailutils/dbgsyslog.c: Likewise.
* libmailutils/address/Makefile.am: New file.
* libmailutils/address.c: Move to libmailutils/address.
* libmailutils/parse822.c: Likewise.
* libmailutils/mailbox/Makefile.am: New file.
* libmailutils/mailbox.c: Move to libmailutils/mailbox.
* libmailutils/mbx_default.c: Likewise.
* libmailutils/mbxitr.c: Likewise.
* libmailutils/attribute.c: Likewise.
* libmailutils/body.c: Likewise.
* libmailutils/envelope.c: Likewise.
* libmailutils/folder.c: Likewise.
* libmailutils/hdritr.c: Likewise.
* libmailutils/header.c: Likewise.
* libmailutils/message.c: Likewise.
* libmailutils/msgscan.c: Likewise.
* libmailutils/mailer/Makefile.am: New file.
* libmailutils/mailer.c: Move to libmailutils/mailer.
* libmailutils/progmailer.c: Likewise.
* libmailutils/mime/Makefile.am: New file.
* libmailutils/attachment.c: Move to libmailutils/mime.
* libmailutils/mime.c: Likewise.
* libmailutils/mimehdr.c: Likewise.
* libmailutils/server/Makefile.am: New file.
* libmailutils/acl.c: Move to libmailutils/server.
* libmailutils/server.c: Likewise.
* libmailutils/msrv.c: Likewise.
* libmailutils/ipsrv.c: Likewise.
* libmailutils/auth/Makefile.am: New file.
* libmailutils/auth.c: Move to libmailutils/auth.
* libmailutils/mu_auth.c: Likewise.
* libmailutils/system.c: Likewise.
* libmailutils/base/Makefile.am: New file.
* libmailutils/base/.gitignore: New file.
* libmailutils/alloc.c: Move to libmailutils/base.
* libmailutils/amd.c: Likewise.
* libmailutils/argcv.c: Likewise.
* libmailutils/assoc.c: Likewise.
* libmailutils/daemon.c: Likewise.
* libmailutils/date.c: Likewise.
* libmailutils/fgetpwent.c: Likewise.
* libmailutils/freeitem.c: Likewise.
* libmailutils/getpass.c: Likewise.
* libmailutils/iterator.c: Likewise.
* libmailutils/kwd.c: Likewise.
* libmailutils/list.c: Likewise.
* libmailutils/listlist.c: Likewise.
* libmailutils/locale.c: Likewise.
* libmailutils/locker.c: Likewise.
* libmailutils/mailcap.c: Likewise.
* libmailutils/md5.c: Likewise.
* libmailutils/monitor.c: Likewise.
* libmailutils/munre.c: Likewise.
* libmailutils/mutil.c: Likewise.
* libmailutils/nls.c: Likewise.
* libmailutils/nullrec.c: Likewise.
* libmailutils/observer.c: Likewise.
* libmailutils/opool.c: Likewise.
* libmailutils/parsedate.y: Likewise.
* libmailutils/permstr.c: Likewise.
* libmailutils/property.c: Likewise.
* libmailutils/registrar.c: Likewise.
* libmailutils/refcount.c: Likewise.
* libmailutils/rfc2047.c: Likewise.
* libmailutils/sha1.c: Likewise.
* libmailutils/secret.c: Likewise.
* libmailutils/ticket.c: Likewise.
* libmailutils/url.c: Likewise.
* libmailutils/vartab.c: Likewise.
* libmailutils/version.c: Likewise.
* libmailutils/wicket.c: Likewise.
Diffstat (limited to 'libmailutils/base')
39 files changed, 15593 insertions, 0 deletions
diff --git a/libmailutils/base/.gitignore b/libmailutils/base/.gitignore new file mode 100644 index 000000000..e3e0cf0d2 --- /dev/null +++ b/libmailutils/base/.gitignore @@ -0,0 +1 @@ +parsedate.c diff --git a/libmailutils/base/Makefile.am b/libmailutils/base/Makefile.am new file mode 100644 index 000000000..4bb7acb47 --- /dev/null +++ b/libmailutils/base/Makefile.am @@ -0,0 +1,80 @@ +# GNU Mailutils -- a suite of utilities for electronic mail +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General +# Public License along with this library. If not, see +# <http://www.gnu.org/licenses/>. + +noinst_LTLIBRARIES = libbase.la + +libbase_la_SOURCES = \ + alloc.c\ + amd.c\ + argcv.c\ + assoc.c\ + daemon.c\ + date.c\ + fgetpwent.c\ + freeitem.c\ + getpass.c\ + iterator.c\ + kwd.c\ + list.c\ + listlist.c\ + locale.c\ + locker.c\ + mailcap.c\ + md5.c\ + monitor.c\ + munre.c\ + mutil.c\ + nls.c\ + nullrec.c\ + observer.c\ + opool.c\ + parsedate.c\ + permstr.c\ + property.c\ + registrar.c\ + refcount.c\ + rfc2047.c\ + sha1.c\ + secret.c\ + ticket.c\ + url.c\ + vartab.c\ + version.c\ + wicket.c + +localedir = $(datadir)/locale +AM_CPPFLAGS = \ + -DSYSCONFDIR=\"$(sysconfdir)\"\ + -DSITE_VIRTUAL_PWDDIR=\"@SITE_VIRTUAL_PWDDIR@\"\ + -DLOCALEDIR=\"$(localedir)\" + +INCLUDES = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils + +YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap +AM_YFLAGS=-vt +AM_LFLAGS=-dvp + +EXTRA_DIST = parsedate.y + +BUILT_SOURCES = parsedate.c + +parsedate.c: $(srcdir)/parsedate.y + $(YLWRAP) "$(YACC) $(AM_YFLAGS)" $< \ + y.tab.c parsedate.c y.output parsedate.y.output \ + -- -yy pd_yy + + diff --git a/libmailutils/base/alloc.c b/libmailutils/base/alloc.c new file mode 100644 index 000000000..05801bb1a --- /dev/null +++ b/libmailutils/base/alloc.c @@ -0,0 +1,116 @@ +/* Error-proof memory allocation functions. + Copyright (C) 2008, 2010 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <mailutils/error.h> +#include <mailutils/nls.h> +#include <mailutils/alloc.h> + +void (*mu_alloc_die_hook) (void) = NULL; + +void +mu_alloc_die () +{ + if (mu_alloc_die_hook) + mu_alloc_die_hook (); + mu_error (_("Not enough memory")); + abort (); +} + +void * +mu_alloc (size_t size) +{ + void *p = malloc (size); + if (!p) + mu_alloc_die (); + return p; +} + +void * +mu_calloc (size_t nmemb, size_t size) +{ + void *p = calloc (nmemb, size); + if (!p) + mu_alloc_die (); + return p; +} + +void * +mu_zalloc (size_t size) +{ + void *p = mu_alloc (size); + memset (p, 0, size); + return p; +} + +void * +mu_realloc (void *p, size_t size) +{ + void *newp = realloc (p, size); + if (!newp) + mu_alloc_die (); + return newp; +} + +char * +mu_strdup (const char *s) +{ + char *news = strdup (s); + if (!news) + mu_alloc_die (); + return news; +} + +/* Copied from gnulib */ +void * +mu_2nrealloc (void *p, size_t *pn, size_t s) +{ + size_t n = *pn; + + if (!p) + { + if (!n) + { + /* The approximate size to use for initial small allocation + requests, when the invoking code specifies an old size of + zero. 64 bytes is the largest "small" request for the + GNU C library malloc. */ + enum { DEFAULT_MXFAST = 64 }; + + n = DEFAULT_MXFAST / s; + n += !n; + } + } + else + { + /* Set N = ceil (1.5 * N) so that progress is made if N == 1. + Check for overflow, so that N * S stays in size_t range. + The check is slightly conservative, but an exact check isn't + worth the trouble. */ + if ((size_t) -1 / 3 * 2 / s <= n) + mu_alloc_die (); + n += (n + 1) / 2; + } + + *pn = n; + return mu_realloc (p, n * s); +} + diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c new file mode 100644 index 000000000..a5dac3f05 --- /dev/null +++ b/libmailutils/base/amd.c @@ -0,0 +1,2033 @@ +/* GNU Mailutils -- a suite of utilities for electronic mail + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008, 2009, 2010 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301 USA */ + +/* Mailutils Abstract Mail Directory Layer + First draft by Sergey Poznyakoff. + Thanks Tang Yong Ping <yongping.tang@radixs.com> for initial + patch (although not used here). + + This module provides basic support for "MH" and "Maildir" formats. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> +#include <dirent.h> + +#ifdef WITH_PTHREAD +# ifdef HAVE_PTHREAD_H +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +# endif +# include <pthread.h> +# endif +#endif + +#include <string.h> +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif + +#include <mailutils/cctype.h> +#include <mailutils/cstr.h> +#include <mailutils/attribute.h> +#include <mailutils/body.h> +#include <mailutils/debug.h> +#include <mailutils/envelope.h> +#include <mailutils/error.h> +#include <mailutils/errno.h> +#include <mailutils/header.h> +#include <mailutils/locker.h> +#include <mailutils/message.h> +#include <mailutils/mutil.h> +#include <mailutils/property.h> +#include <mailutils/stream.h> +#include <mailutils/url.h> +#include <mailutils/observer.h> +#include <mailutils/sys/stream.h> +#include <mailutils/sys/mailbox.h> +#include <mailutils/sys/registrar.h> +#include <mailutils/sys/url.h> +#include <mailutils/sys/amd.h> + +static void amd_destroy (mu_mailbox_t mailbox); +static int amd_open (mu_mailbox_t, int); +static int amd_close (mu_mailbox_t); +static int amd_get_message (mu_mailbox_t, size_t, mu_message_t *); +static int amd_quick_get_message (mu_mailbox_t mailbox, mu_message_qid_t qid, + mu_message_t *pmsg); +static int amd_append_message (mu_mailbox_t, mu_message_t); +static int amd_messages_count (mu_mailbox_t, size_t *); +static int amd_messages_recent (mu_mailbox_t, size_t *); +static int amd_message_unseen (mu_mailbox_t, size_t *); +static int amd_expunge (mu_mailbox_t); +static int amd_sync (mu_mailbox_t); +static int amd_uidnext (mu_mailbox_t mailbox, size_t *puidnext); +static int amd_uidvalidity (mu_mailbox_t, unsigned long *); +static int amd_scan (mu_mailbox_t, size_t, size_t *); +static int amd_is_updated (mu_mailbox_t); +static int amd_get_size (mu_mailbox_t, mu_off_t *); + +static int amd_body_size (mu_body_t body, size_t *psize); +static int amd_body_lines (mu_body_t body, size_t *plines); + +static int amd_header_fill (void *data, char **pbuf, size_t *plen); + +static int amd_get_attr_flags (mu_attribute_t attr, int *pflags); +static int amd_set_attr_flags (mu_attribute_t attr, int flags); +static int amd_unset_attr_flags (mu_attribute_t attr, int flags); + +static void _amd_message_delete (struct _amd_data *amd, + struct _amd_message *msg); +static int amd_pool_open (struct _amd_message *mhm); +static int amd_pool_open_count (struct _amd_data *amd); +static void amd_pool_flush (struct _amd_data *amd); +static struct _amd_message **amd_pool_lookup (struct _amd_message *mhm); + +static int amd_envelope_date (mu_envelope_t envelope, char *buf, size_t len, + size_t *psize); +static int amd_envelope_sender (mu_envelope_t envelope, char *buf, size_t len, + size_t *psize); +static int amd_remove_mbox (mu_mailbox_t mailbox); + + +static int amd_body_stream_read (mu_stream_t str, char *buffer, + size_t buflen, + size_t *pnread); +static int amd_body_stream_readdelim (mu_stream_t is, + char *buffer, size_t buflen, + int delim, + size_t *pnread); +static int amd_body_stream_size (mu_stream_t str, mu_off_t *psize); +static int amd_body_stream_seek (mu_stream_t str, mu_off_t off, + mu_off_t *presult); + +struct _amd_body_stream +{ + struct _mu_stream stream; + mu_body_t body; + mu_off_t off; +}; + + +/* Operations on message array */ + +/* Perform binary search for message MSG on a segment of message array + of AMD between the indexes FIRST and LAST inclusively. + If found, return 0 and store index of the located entry in the + variable PRET. Otherwise, return 1 and place into PRET index of + the nearest array element that is less than MSG (in the sense of + amd->msg_cmp) + Indexes are zero-based. */ + +static int +amd_msg_bsearch (struct _amd_data *amd, mu_off_t first, mu_off_t last, + struct _amd_message *msg, + mu_off_t *pret) +{ + mu_off_t mid; + int rc; + + if (last < first) + return 1; + + mid = (first + last) / 2; + rc = amd->msg_cmp (amd->msg_array[mid], msg); + if (rc > 0) + return amd_msg_bsearch (amd, first, mid-1, msg, pret); + *pret = mid; + if (rc < 0) + return amd_msg_bsearch (amd, mid+1, last, msg, pret); + /* else */ + return 0; +} + +/* Search for message MSG in the message array of AMD. + If found, return 0 and store index of the located entry in the + variable PRET. Otherwise, return 1 and place into PRET index of + the array element that is less than MSG (in the sense of + amd->msg_cmp) + Index returned in PRET is 1-based, so *PRET == 0 means that MSG + is less than the very first element of the message array. + + In other words, when amd_msg_lookup() returns 1, the value in *PRET + can be regarded as a 0-based index of the array slot where MSG can + be inserted */ + +int +amd_msg_lookup (struct _amd_data *amd, struct _amd_message *msg, + size_t *pret) +{ + int rc; + mu_off_t i; + + if (amd->msg_count == 0) + { + *pret = 0; + return 1; + } + + rc = amd->msg_cmp (msg, amd->msg_array[0]); + if (rc < 0) + { + *pret = 0; + return 1; + } + else if (rc == 0) + { + *pret = 1; + return 0; + } + + rc = amd->msg_cmp (msg, amd->msg_array[amd->msg_count - 1]); + if (rc > 0) + { + *pret = amd->msg_count; + return 1; + } + else if (rc == 0) + { + *pret = amd->msg_count; + return 0; + } + + rc = amd_msg_bsearch (amd, 0, amd->msg_count - 1, msg, &i); + *pret = i + 1; + return rc; +} + +#define AMD_MSG_INC 64 + +/* Prepare the message array for insertion of a new message + at position INDEX (zero based), by moving its contents + one slot to the right. If necessary, expand the array by + AMD_MSG_INC */ +int +amd_array_expand (struct _amd_data *amd, size_t index) +{ + if (amd->msg_count == amd->msg_max) + { + struct _amd_message **p; + + amd->msg_max += AMD_MSG_INC; /* FIXME: configurable? */ + p = realloc (amd->msg_array, amd->msg_max * amd->msg_size); + if (!p) + { + amd->msg_max -= AMD_MSG_INC; + return ENOMEM; + } + amd->msg_array = p; + } + memmove (&amd->msg_array[index+1], &amd->msg_array[index], + (amd->msg_count-index) * amd->msg_size); + amd->msg_count++; + return 0; +} + +/* Shrink the message array by removing element at INDEX-1 and + shifting left by one position all the elements on the right of + it. */ +int +amd_array_shrink (struct _amd_data *amd, size_t index) +{ + memmove (&amd->msg_array[index-1], &amd->msg_array[index], + (amd->msg_count-index) * amd->msg_size); + amd->msg_count--; + return 0; +} + + +int +amd_init_mailbox (mu_mailbox_t mailbox, size_t amd_size, + struct _amd_data **pamd) +{ + int status; + struct _amd_data *amd; + + if (mailbox == NULL) + return MU_ERR_MBX_NULL; + if (amd_size < sizeof (*amd)) + return EINVAL; + + amd = mailbox->data = calloc (1, amd_size); + if (mailbox->data == NULL) + return ENOMEM; + + /* Back pointer. */ + amd->mailbox = mailbox; + + status = mu_url_aget_path (mailbox->url, &amd->name); + if (status) + { + free (amd); + mailbox->data = NULL; + return status; + } + + /* Overloading the defaults. */ + mailbox->_destroy = amd_destroy; + + mailbox->_open = amd_open; + mailbox->_close = amd_close; + + /* Overloading of the entire mailbox object methods. */ + mailbox->_get_message = amd_get_message; + mailbox->_quick_get_message = amd_quick_get_message; + mailbox->_append_message = amd_append_message; + mailbox->_messages_count = amd_messages_count; + mailbox->_messages_recent = amd_messages_recent; + mailbox->_message_unseen = amd_message_unseen; + mailbox->_expunge = amd_expunge; + mailbox->_sync = amd_sync; + mailbox->_uidvalidity = amd_uidvalidity; + mailbox->_uidnext = amd_uidnext; + + mailbox->_scan = amd_scan; + mailbox->_is_updated = amd_is_updated; + + mailbox->_get_size = amd_get_size; + mailbox->_remove = amd_remove_mbox; + + MU_DEBUG1 (mailbox->debug, MU_DEBUG_TRACE1, "amd_init(%s)\n", amd->name); + *pamd = amd; + return 0; +} + +static void +amd_destroy (mu_mailbox_t mailbox) +{ + struct _amd_data *amd = mailbox->data; + size_t i; + + if (!amd) + return; + + amd_pool_flush (amd); + mu_monitor_wrlock (mailbox->monitor); + for (i = 0; i < amd->msg_count; i++) + { + mu_message_destroy (&amd->msg_array[i]->message, amd->msg_array[i]); + free (amd->msg_array[i]); + } + free (amd->msg_array); + + if (amd->name) + free (amd->name); + + free (amd); + mailbox->data = NULL; + mu_monitor_unlock (mailbox->monitor); +} + +static int +amd_open (mu_mailbox_t mailbox, int flags) +{ + struct _amd_data *amd = mailbox->data; + struct stat st; + + mailbox->flags = flags; + if (stat (amd->name, &st) < 0) + { + if ((flags & MU_STREAM_CREAT) && errno == ENOENT) + { + int rc; + int perms = mu_stream_flags_to_mode (flags, 1); + if (mkdir (amd->name, S_IRUSR|S_IWUSR|S_IXUSR|perms)) + return errno; + if (stat (amd->name, &st) < 0) + return errno; + if (amd->create && (rc = amd->create (amd, flags))) + return rc; + } + else + return errno; + } + + if (!S_ISDIR (st.st_mode)) + return EINVAL; + + if (mailbox->locker == NULL) + mu_locker_create (&mailbox->locker, "/dev/null", 0); + + return 0; +} + +static int +amd_close (mu_mailbox_t mailbox) +{ + struct _amd_data *amd; + int i; + + if (!mailbox) + return MU_ERR_MBX_NULL; + + amd = mailbox->data; + + /* Destroy all cached data */ + amd_pool_flush (amd); + mu_monitor_wrlock (mailbox->monitor); + for (i = 0; i < amd->msg_count; i++) + { + mu_message_destroy (&amd->msg_array[i]->message, amd->msg_array[i]); + free (amd->msg_array[i]); + } + free (amd->msg_array); + amd->msg_array = NULL; + + amd->msg_count = 0; /* number of messages in the list */ + amd->msg_max = 0; /* maximum message buffer capacity */ + + amd->uidvalidity = 0; + mu_monitor_unlock (mailbox->monitor); + + return 0; +} + +static int +amd_message_qid (mu_message_t msg, mu_message_qid_t *pqid) +{ + struct _amd_message *mhm = mu_message_get_owner (msg); + + return mhm->amd->cur_msg_file_name (mhm, pqid); +} + +struct _amd_message * +_amd_get_message (struct _amd_data *amd, size_t msgno) +{ + msgno--; + if (msgno >= amd->msg_count) + return NULL; + return amd->msg_array[msgno]; +} + +static int +_amd_attach_message (mu_mailbox_t mailbox, struct _amd_message *mhm, + mu_message_t *pmsg) +{ + int status; + mu_message_t msg; + + /* Check if we already have it. */ + if (mhm->message) + { + if (pmsg) + *pmsg = mhm->message; + return 0; + } + + /* Get an empty message struct. */ + status = mu_message_create (&msg, mhm); + if (status != 0) + return status; + + /* Set the header. */ + { + mu_header_t header = NULL; + status = mu_header_create (&header, NULL, 0); + if (status != 0) + { + mu_message_destroy (&msg, mhm); + return status; + } + mu_header_set_fill (header, amd_header_fill, msg); + /*FIXME: + mu_header_set_get_fvalue (header, amd_header_get_fvalue, msg); + */ + mu_message_set_header (msg, header, mhm); + } + + /* Set the attribute. */ + { + mu_attribute_t attribute; + status = mu_attribute_create (&attribute, msg); + if (status != 0) + { + mu_message_destroy (&msg, mhm); + return status; + } + mu_attribute_set_get_flags (attribute, amd_get_attr_flags, msg); + mu_attribute_set_set_flags (attribute, amd_set_attr_flags, msg); + mu_attribute_set_unset_flags (attribute, amd_unset_attr_flags, msg); + mu_message_set_attribute (msg, attribute, mhm); + } + + /* Prepare the body. */ + { + mu_body_t body = NULL; + struct _amd_body_stream *str; + + if ((status = mu_body_create (&body, msg)) != 0) + return status; + + str = (struct _amd_body_stream *) + _mu_stream_create (sizeof (*str), + mailbox->flags | MU_STREAM_SEEK | + _MU_STR_OPEN); + if (!str) + { + mu_body_destroy (&body, msg); + mu_message_destroy (&msg, mhm); + return ENOMEM; + } + str->stream.read = amd_body_stream_read; + str->stream.readdelim = amd_body_stream_readdelim; + str->stream.size = amd_body_stream_size; + str->stream.seek = amd_body_stream_seek; + mu_body_set_stream (body, (mu_stream_t) str, msg); + mu_body_clear_modified (body); + mu_body_set_size (body, amd_body_size, msg); + mu_body_set_lines (body, amd_body_lines, msg); + mu_message_set_body (msg, body, mhm); + str->body = body; + } + + /* Set the envelope. */ + { + mu_envelope_t envelope = NULL; + status = mu_envelope_create (&envelope, msg); + if (status != 0) + { + mu_message_destroy (&msg, mhm); + return status; + } + mu_envelope_set_sender (envelope, amd_envelope_sender, msg); + mu_envelope_set_date (envelope, amd_envelope_date, msg); + mu_message_set_envelope (msg, envelope, mhm); + } + + /* Set the UID. */ + if (mhm->amd->message_uid) + mu_message_set_uid (msg, mhm->amd->message_uid, mhm); + mu_message_set_qid (msg, amd_message_qid, mhm); + + /* Attach the message to the mailbox mbox data. */ + mhm-> |