diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | lib/.cvsignore | 3 | ||||
-rw-r--r-- | libproto/include/amd.h | 8 | ||||
-rw-r--r-- | m4/.cvsignore | 2 | ||||
-rw-r--r-- | mailbox/amd.c | 227 | ||||
-rw-r--r-- | mailbox/mbx_default.c | 2 | ||||
-rw-r--r-- | movemail/movemail.c | 1 |
7 files changed, 186 insertions, 73 deletions
@@ -1,3 +1,19 @@ +2008-05-31 Sergey Poznyakoff <gray@gnu.org.ua> + + * libproto/include/amd.h (struct _amd_message.has_new_msg): New + field. + * mailbox/amd.c (amd_append_message): Cache information about + mailbox size in file .mu-size. + (make_size_file_name, read_size_file, write_size_file): New + functions. + (amd_expunge, amd_sync): Update size cache file. + (amd_get_size): Use size cache file if no mailbox_size method is + provided. + * mailbox/mbx_default.c (mu_normalize_mailbox_url): Accept `=' + suffix for all mailbox types. + * movemail/movemail.c (main): Call mu_mailbox_sync before closing + destination mailbox. + 2008-05-28 Sergey Poznyakoff <gray@gnu.org.ua> * lib/Makefile.am (libmuaux_la_SOURCES): Add userprivs.c. diff --git a/lib/.cvsignore b/lib/.cvsignore index f10a4dfea..2d9fdfa36 100644 --- a/lib/.cvsignore +++ b/lib/.cvsignore @@ -109,6 +109,8 @@ printf-args.c printf-args.h printf-parse.c printf-parse.h +rawmemchr.c +rawmemchr.valgrind readlink.c realloc.c ref-add.sed @@ -139,6 +141,7 @@ stdlib.h stdlib.in.h strcasecmp.c strchrnul.c +strchrnul.valgrind strdup.c streq.h strerror.c diff --git a/libproto/include/amd.h b/libproto/include/amd.h index 2471b3d6f..e1f94376f 100644 --- a/libproto/include/amd.h +++ b/libproto/include/amd.h @@ -44,9 +44,9 @@ do \ struct _amd_data; struct _amd_message { - mu_stream_t stream; /* Associated file stream */ - mu_off_t body_start; /* Offset of body start in the message file */ - mu_off_t body_end; /* Offset of body end (size of file, effectively)*/ + mu_stream_t stream; /* Associated file stream */ + mu_off_t body_start; /* Offset of body start in the message file */ + mu_off_t body_end; /* Offset of body end (size of file, effectively)*/ int orig_flags; /* Original attribute flags */ int attr_flags; /* Current attribute flags */ @@ -84,7 +84,7 @@ struct _amd_data struct _amd_message **msg_array; unsigned long uidvalidity; - + int has_new_msg; /* New messages have been appended */ char *name; /* Directory name */ /* Pool of open message streams */ diff --git a/m4/.cvsignore b/m4/.cvsignore index e36910f7b..0df006035 100644 --- a/m4/.cvsignore +++ b/m4/.cvsignore @@ -71,7 +71,9 @@ memrchr.m4 openat.m4 pathmax.m4 po.m4 +printf.m4 progtest.m4 +rawmemchr.m4 readlink.m4 realloc.m4 regex.m4 diff --git a/mailbox/amd.c b/mailbox/amd.c index 324cf288c..2d4c04c2b 100644 --- a/mailbox/amd.c +++ b/mailbox/amd.c @@ -767,6 +767,8 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg) } } + amd->has_new_msg = 1; + mhm->amd = amd; if (amd->msg_init_delivery) { @@ -875,12 +877,142 @@ amd_message_unseen (mu_mailbox_t mailbox, size_t *pmsgno) return 0; } +#define SIZE_FILE_NAME ".mu-size" + +static char * +make_size_file_name (struct _amd_data *amd) +{ + size_t size = strlen (amd->name) + 1 + sizeof (SIZE_FILE_NAME); + char *name = malloc (size); + if (name) + { + strcpy (name, amd->name); + strcat (name, "/"); + strcat (name, SIZE_FILE_NAME); + } + return name; +} + +static int +read_size_file (struct _amd_data *amd, mu_off_t *psize) +{ + FILE *fp; + int rc; + char *name = make_size_file_name (amd); + if (!name) + return 1; + fp = fopen (name, "r"); + if (fp) + { + unsigned long size; + if (fscanf (fp, "%lu", &size) == 1) + { + *psize = size; + rc = 0; + } + else + rc = 1; + fclose (fp); + } + free (name); + return rc; +} + +static int +write_size_file (struct _amd_data *amd, mu_off_t size) +{ + FILE *fp; + int rc; + char *name = make_size_file_name (amd); + if (!name) + return 1; + fp = fopen (name, "w"); + if (fp) + { + fprintf (fp, "%lu", (unsigned long) size); + fclose (fp); + rc = 0; + } + else + rc = 1; + free (name); + return rc; +} + +static int +compute_mailbox_size (struct _amd_data *amd, const char *name, mu_off_t *psize) +{ + DIR *dir; + struct dirent *entry; + char *buf; + size_t bufsize; + size_t dirlen; + size_t flen; + int status = 0; + struct stat sb; + + dir = opendir (name); + if (!dir) + return errno; + + dirlen = strlen (name); + bufsize = dirlen + 32; + buf = malloc (bufsize); + if (!buf) + { + closedir (dir); + return ENOMEM; + } + + strcpy (buf, name); + if (buf[dirlen-1] != '/') + buf[++dirlen - 1] = '/'; + + while ((entry = readdir (dir))) + { + switch (entry->d_name[0]) + { + case '.': + break; + + default: + flen = strlen (entry->d_name); + if (dirlen + flen + 1 > bufsize) + { + bufsize = dirlen + flen + 1; + buf = realloc (buf, bufsize); + if (!buf) + { + status = ENOMEM; + break; + } + } + strcpy (buf + dirlen, entry->d_name); + if (stat (buf, &sb) == 0) + { + if (S_ISREG (sb.st_mode)) + *psize += sb.st_size; + else if (S_ISDIR (sb.st_mode)) + compute_mailbox_size (amd, buf, psize); + } + /* FIXME: else? */ + break; + } + } + + free (buf); + + closedir (dir); + return 0; +} + static int amd_expunge (mu_mailbox_t mailbox) { struct _amd_data *amd = mailbox->data; struct _amd_message *mhm; size_t i; + int updated = amd->has_new_msg; if (amd == NULL) return EINVAL; @@ -932,6 +1064,7 @@ amd_expunge (mu_mailbox_t mailbox) free (old_name); } _amd_message_delete (amd, mhm); + updated = 1; /* Do not increase i! */ } else @@ -941,11 +1074,19 @@ amd_expunge (mu_mailbox_t mailbox) { _amd_attach_message (mailbox, mhm, NULL); _amd_message_save (amd, mhm, 1); + updated = 1; } i++; /* Move to the next message */ } } + if (updated && !amd->mailbox_size) + { + mu_off_t size = 0; + int rc = compute_mailbox_size (amd, amd->name, &size); + if (rc == 0) + write_size_file (amd, size); + } return 0; } @@ -955,6 +1096,7 @@ amd_sync (mu_mailbox_t mailbox) struct _amd_data *amd = mailbox->data; struct _amd_message *mhm; size_t i; + int updated = amd->has_new_msg; if (amd == NULL) return EINVAL; @@ -980,9 +1122,18 @@ amd_sync (mu_mailbox_t mailbox) { _amd_attach_message (mailbox, mhm, NULL); _amd_message_save (amd, mhm, 0); + updated = 1; } } + if (updated && !amd->mailbox_size) + { + mu_off_t size = 0; + int rc = compute_mailbox_size (amd, amd->name, &size); + if (rc == 0) + write_size_file (amd, size); + } + return 0; } @@ -1193,80 +1344,20 @@ amd_is_updated (mu_mailbox_t mailbox) } static int -compute_mailbox_size (const char *name, mu_off_t *psize) -{ - DIR *dir; - struct dirent *entry; - char *buf; - size_t bufsize; - size_t dirlen; - size_t flen; - int status = 0; - struct stat sb; - - dir = opendir (name); - if (!dir) - return errno; - - dirlen = strlen (name); - bufsize = dirlen + 32; - buf = malloc (bufsize); - if (!buf) - { - closedir (dir); - return ENOMEM; - } - - strcpy (buf, name); - if (buf[dirlen-1] != '/') - buf[++dirlen - 1] = '/'; - - while ((entry = readdir (dir))) - { - switch (entry->d_name[0]) - { - case '.': - break; - - default: - flen = strlen (entry->d_name); - if (dirlen + flen + 1 > bufsize) - { - bufsize = dirlen + flen + 1; - buf = realloc (buf, bufsize); - if (!buf) - { - status = ENOMEM; - break; - } - } - strcpy (buf + dirlen, entry->d_name); - if (stat (buf, &sb) == 0) - { - if (S_ISREG (sb.st_mode)) - *psize += sb.st_size; - else if (S_ISDIR (sb.st_mode)) - compute_mailbox_size (buf, psize); - } - /* FIXME: else? */ - break; - } - } - - free (buf); - - closedir (dir); - return 0; -} - -static int amd_get_size (mu_mailbox_t mailbox, mu_off_t *psize) { struct _amd_data *amd = mailbox->data; if (amd->mailbox_size) return amd->mailbox_size (mailbox, psize); *psize = 0; - return compute_mailbox_size (amd->name, psize); + if (read_size_file (amd, psize)) + { + int rc = compute_mailbox_size (amd, amd->name, psize); + if (rc == 0) + write_size_file (amd, *psize); + return rc; + } + return 0; } /* Return number of open streams residing in a message pool */ diff --git a/mailbox/mbx_default.c b/mailbox/mbx_default.c index c0db199c8..60e742610 100644 --- a/mailbox/mbx_default.c +++ b/mailbox/mbx_default.c @@ -55,7 +55,7 @@ mu_normalize_mailbox_url (char **pout, const char *dir) return MU_ERR_OUT_PTR_NULL; len = strlen (dir); - if (strncasecmp (dir, "mbox:", 5) == 0 && dir[len-1] == '=') + if (dir[len-1] == '=') { if (len > 5 && strcmp (dir + len - 5, "user=") == 0) *pout = strdup (dir); diff --git a/movemail/movemail.c b/movemail/movemail.c index 72cf6328a..4dee71d61 100644 --- a/movemail/movemail.c +++ b/movemail/movemail.c @@ -419,6 +419,7 @@ main (int argc, char **argv) if (rc) return rc; + mu_mailbox_sync (dest); rc = mu_mailbox_close (dest); mu_mailbox_destroy (&dest); if (rc) |