Commit d89b44d4 d89b44d44064528bf4fff3dc8999d0f423f34f8c by Sergey Poznyakoff

* 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.
1 parent 073af45f
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.
......
......@@ -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
......
......@@ -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 */
......
......@@ -71,7 +71,9 @@ memrchr.m4
openat.m4
pathmax.m4
po.m4
printf.m4
progtest.m4
rawmemchr.m4
readlink.m4
realloc.m4
regex.m4
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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)
......