2000-12-21 00:30:53 +00:00
|
|
|
/* $Id$
|
|
|
|
*
|
|
|
|
* isync - IMAP4 to maildir mailbox synchronizer
|
2002-01-16 19:47:28 +00:00
|
|
|
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
2000-12-20 21:41:21 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
2000-12-22 07:14:32 +00:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
2001-11-09 00:23:50 +00:00
|
|
|
#include <time.h>
|
2000-12-20 21:41:21 +00:00
|
|
|
#include "isync.h"
|
2002-06-20 23:33:13 +00:00
|
|
|
#include "dotlock.h"
|
2000-12-22 07:14:32 +00:00
|
|
|
|
2000-12-20 21:41:21 +00:00
|
|
|
/* 2,<flags> */
|
|
|
|
static void
|
|
|
|
parse_info (message_t * m, char *s)
|
|
|
|
{
|
|
|
|
if (*s == '2' && *(s + 1) == ',')
|
|
|
|
{
|
|
|
|
s += 2;
|
|
|
|
while (*s)
|
|
|
|
{
|
|
|
|
if (*s == 'F')
|
|
|
|
m->flags |= D_FLAGGED;
|
|
|
|
else if (*s == 'R')
|
|
|
|
m->flags |= D_ANSWERED;
|
|
|
|
else if (*s == 'T')
|
|
|
|
m->flags |= D_DELETED;
|
|
|
|
else if (*s == 'S')
|
|
|
|
m->flags |= D_SEEN;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-18 06:37:55 +00:00
|
|
|
/*
|
|
|
|
* There are three possible results of this function:
|
|
|
|
* >1 uid was already seen
|
|
|
|
* 0 uid was not yet seen
|
|
|
|
* -1 unable to read uid because of some other error
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int
|
|
|
|
read_uid (const char *path, const char *file, unsigned int *uid /* out */)
|
2000-12-22 07:14:32 +00:00
|
|
|
{
|
|
|
|
char full[_POSIX_PATH_MAX];
|
|
|
|
int fd;
|
2002-06-18 06:37:55 +00:00
|
|
|
int ret = -1;
|
2000-12-22 07:14:32 +00:00
|
|
|
int len;
|
2002-06-18 06:37:55 +00:00
|
|
|
char buf[64], *ptr;
|
2000-12-22 07:14:32 +00:00
|
|
|
|
|
|
|
snprintf (full, sizeof (full), "%s/%s", path, file);
|
|
|
|
fd = open (full, O_RDONLY);
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
|
|
|
if (errno != ENOENT)
|
|
|
|
{
|
2002-01-16 19:47:28 +00:00
|
|
|
perror (full);
|
2000-12-22 07:14:32 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2000-12-27 21:14:22 +00:00
|
|
|
return 0; /* doesn't exist */
|
2000-12-22 07:14:32 +00:00
|
|
|
}
|
2002-01-16 19:47:28 +00:00
|
|
|
len = read (fd, buf, sizeof (buf) - 1);
|
|
|
|
if (len == -1)
|
|
|
|
perror ("read");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf[len] = 0;
|
2002-06-18 06:37:55 +00:00
|
|
|
errno = 0;
|
|
|
|
*uid = strtoul (buf, &ptr, 10);
|
|
|
|
if (errno)
|
|
|
|
perror ("strtoul");
|
|
|
|
else if (ptr && *ptr == '\n')
|
|
|
|
ret = 1;
|
|
|
|
/* else invalid value */
|
2000-12-22 07:14:32 +00:00
|
|
|
}
|
|
|
|
close (fd);
|
2002-06-18 06:37:55 +00:00
|
|
|
return ret;
|
2000-12-22 07:14:32 +00:00
|
|
|
}
|
|
|
|
|
2002-06-20 23:33:13 +00:00
|
|
|
/*
|
|
|
|
* open a maildir mailbox.
|
2001-11-20 18:06:09 +00:00
|
|
|
* if OPEN_FAST is set, we just check to make
|
2000-12-20 21:41:21 +00:00
|
|
|
* sure its a valid mailbox and don't actually parse it. any IMAP messages
|
|
|
|
* with the \Recent flag set are guaranteed not to be in the mailbox yet,
|
|
|
|
* so we can save a lot of time when the user just wants to fetch new messages
|
|
|
|
* without syncing the flags.
|
2001-11-20 18:06:09 +00:00
|
|
|
* if OPEN_CREATE is set, we create the mailbox if it doesn't already exist.
|
2000-12-20 21:41:21 +00:00
|
|
|
*/
|
|
|
|
mailbox_t *
|
2001-11-20 18:06:09 +00:00
|
|
|
maildir_open (const char *path, int flags)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
|
|
|
char buf[_POSIX_PATH_MAX];
|
|
|
|
DIR *d;
|
|
|
|
struct dirent *e;
|
|
|
|
message_t **cur;
|
|
|
|
message_t *p;
|
|
|
|
mailbox_t *m;
|
|
|
|
char *s;
|
|
|
|
int count = 0;
|
2001-11-20 18:06:09 +00:00
|
|
|
struct stat sb;
|
|
|
|
const char *subdirs[] = { "cur", "new", "tmp" };
|
|
|
|
int i;
|
2002-01-16 19:47:28 +00:00
|
|
|
datum key;
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2001-07-18 18:49:55 +00:00
|
|
|
m = calloc (1, sizeof (mailbox_t));
|
2002-01-16 19:47:28 +00:00
|
|
|
m->lockfd = -1;
|
2001-07-18 18:49:55 +00:00
|
|
|
/* filename expansion happens here, not in the config parser */
|
|
|
|
m->path = expand_strdup (path);
|
|
|
|
|
2001-11-20 18:06:09 +00:00
|
|
|
if (stat (m->path, &sb))
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2001-11-20 18:06:09 +00:00
|
|
|
if (errno == ENOENT && (flags & OPEN_CREATE))
|
|
|
|
{
|
|
|
|
if (mkdir (m->path, S_IRUSR | S_IWUSR | S_IXUSR))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: mkdir %s: %s (errno %d)\n",
|
|
|
|
m->path, strerror (errno), errno);
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2001-11-20 18:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
snprintf (buf, sizeof (buf), "%s/%s", m->path, subdirs[i]);
|
|
|
|
if (mkdir (buf, S_IRUSR | S_IWUSR | S_IXUSR))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: mkdir %s: %s (errno %d)\n",
|
|
|
|
buf, strerror (errno), errno);
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2001-11-20 18:06:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: stat %s: %s (errno %d)\n", m->path,
|
|
|
|
strerror (errno), errno);
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2001-11-20 18:06:09 +00:00
|
|
|
}
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
2001-11-20 18:06:09 +00:00
|
|
|
else
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2001-11-20 18:06:09 +00:00
|
|
|
/* check to make sure this looks like a valid maildir box */
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
snprintf (buf, sizeof (buf), "%s/%s", m->path, subdirs[i]);
|
|
|
|
if (stat (buf, &sb))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "ERROR: stat %s: %s (errno %d)\n", buf,
|
|
|
|
strerror (errno), errno);
|
|
|
|
fprintf (stderr,
|
|
|
|
"ERROR: %s does not appear to be a valid maildir style mailbox\n",
|
|
|
|
m->path);
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2001-11-20 18:06:09 +00:00
|
|
|
}
|
|
|
|
}
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
2000-12-21 23:10:18 +00:00
|
|
|
|
2002-06-20 23:33:13 +00:00
|
|
|
/*
|
|
|
|
* we need a mutex on the maildir because of the state files that isync
|
2002-01-16 19:47:28 +00:00
|
|
|
* uses.
|
|
|
|
*/
|
2002-06-20 23:33:13 +00:00
|
|
|
snprintf (buf, sizeof (buf), "%s/isynclock", m->path);
|
|
|
|
if (dotlock_lock (buf, &m->lockfd))
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
|
|
|
|
2000-12-21 23:10:18 +00:00
|
|
|
/* check for the uidvalidity value */
|
2002-06-18 06:37:55 +00:00
|
|
|
i = read_uid (m->path, "isyncuidvalidity", &m->uidvalidity);
|
|
|
|
if (i == -1)
|
|
|
|
goto err;
|
|
|
|
else if (i > 0)
|
|
|
|
m->uidseen = 1;
|
2000-12-22 07:14:32 +00:00
|
|
|
|
|
|
|
/* load the current maxuid */
|
2002-06-18 06:37:55 +00:00
|
|
|
if (read_uid (m->path, "isyncmaxuid", &m->maxuid) == -1)
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2001-11-20 18:06:09 +00:00
|
|
|
if (flags & OPEN_FAST)
|
2000-12-20 21:41:21 +00:00
|
|
|
return m;
|
|
|
|
|
2002-01-16 19:47:28 +00:00
|
|
|
snprintf (buf, sizeof (buf), "%s/isyncuidmap", m->path);
|
|
|
|
m->db = dbm_open (buf, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
|
|
|
if (m->db == NULL)
|
|
|
|
{
|
|
|
|
fputs ("ERROR: unable to open UID db\n", stderr);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2000-12-20 21:41:21 +00:00
|
|
|
cur = &m->msgs;
|
|
|
|
for (; count < 2; count++)
|
|
|
|
{
|
|
|
|
/* read the msgs from the new subdir */
|
2001-07-18 18:49:55 +00:00
|
|
|
snprintf (buf, sizeof (buf), "%s/%s", m->path,
|
2000-12-20 21:41:21 +00:00
|
|
|
(count == 0) ? "new" : "cur");
|
|
|
|
d = opendir (buf);
|
|
|
|
if (!d)
|
|
|
|
{
|
|
|
|
perror ("opendir");
|
2002-01-16 19:47:28 +00:00
|
|
|
goto err;
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
|
|
|
while ((e = readdir (d)))
|
|
|
|
{
|
|
|
|
if (*e->d_name == '.')
|
|
|
|
continue; /* skip dot-files */
|
|
|
|
*cur = calloc (1, sizeof (message_t));
|
|
|
|
p = *cur;
|
|
|
|
p->file = strdup (e->d_name);
|
|
|
|
p->uid = -1;
|
2001-01-09 20:09:35 +00:00
|
|
|
p->flags = 0;
|
2000-12-20 21:41:21 +00:00
|
|
|
p->new = (count == 0);
|
|
|
|
|
2002-01-16 19:47:28 +00:00
|
|
|
/* determine the UID for this message. The basename (sans
|
|
|
|
* flags) is used as the key in the db
|
2000-12-20 21:41:21 +00:00
|
|
|
*/
|
2002-01-16 21:22:43 +00:00
|
|
|
key.dptr = p->file;
|
|
|
|
s = strchr (key.dptr, ':');
|
2002-01-16 21:43:58 +00:00
|
|
|
key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr);
|
2002-01-16 19:47:28 +00:00
|
|
|
key = dbm_fetch (m->db, key);
|
|
|
|
if (key.dptr)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2002-01-16 19:47:28 +00:00
|
|
|
p->uid = *(int *) key.dptr;
|
2000-12-22 07:14:32 +00:00
|
|
|
if (p->uid > m->maxuid)
|
|
|
|
m->maxuid = p->uid;
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
else /* XXX remove. every locally generated message triggers this */
|
2002-01-16 19:47:28 +00:00
|
|
|
puts ("Warning, no UID for message");
|
2000-12-20 21:41:21 +00:00
|
|
|
|
|
|
|
if (s)
|
|
|
|
parse_info (p, s + 1);
|
2000-12-21 00:30:53 +00:00
|
|
|
if (p->flags & D_DELETED)
|
|
|
|
m->deleted++;
|
2000-12-20 21:41:21 +00:00
|
|
|
cur = &p->next;
|
|
|
|
}
|
|
|
|
closedir (d);
|
|
|
|
}
|
|
|
|
return m;
|
2002-01-16 19:47:28 +00:00
|
|
|
|
|
|
|
err:
|
|
|
|
if (m->db)
|
|
|
|
dbm_close (m->db);
|
2002-06-20 23:33:13 +00:00
|
|
|
dotlock_unlock (&m->lockfd);
|
2002-01-16 19:47:28 +00:00
|
|
|
free (m->path);
|
|
|
|
free (m);
|
|
|
|
return NULL;
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* permanently remove messages from a maildir mailbox. if `dead' is nonzero,
|
|
|
|
* we only remove the messags marked dead.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
maildir_expunge (mailbox_t * mbox, int dead)
|
|
|
|
{
|
2002-01-16 21:43:58 +00:00
|
|
|
message_t **cur = &mbox->msgs;
|
|
|
|
message_t *tmp;
|
|
|
|
char *s;
|
|
|
|
datum key;
|
|
|
|
char path[_POSIX_PATH_MAX];
|
2000-12-20 21:41:21 +00:00
|
|
|
|
2002-01-16 21:43:58 +00:00
|
|
|
while (*cur)
|
|
|
|
{
|
|
|
|
if ((dead == 0 && (*cur)->flags & D_DELETED) ||
|
|
|
|
(dead && (*cur)->dead))
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2002-01-16 21:43:58 +00:00
|
|
|
tmp = *cur;
|
|
|
|
snprintf (path, sizeof (path), "%s/%s/%s",
|
|
|
|
mbox->path, tmp->new ? "new" : "cur", tmp->file);
|
|
|
|
if (unlink (path))
|
|
|
|
perror (path);
|
|
|
|
/* remove the message from the UID map */
|
|
|
|
key.dptr = tmp->file;
|
|
|
|
s = strchr (key.dptr, ':');
|
|
|
|
key.dsize = s ? (size_t) (s - key.dptr) : strlen (key.dptr);
|
|
|
|
dbm_delete (mbox->db, key);
|
|
|
|
*cur = (*cur)->next;
|
|
|
|
free (tmp->file);
|
|
|
|
free (tmp);
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
2002-01-16 21:43:58 +00:00
|
|
|
else
|
|
|
|
cur = &(*cur)->next;
|
|
|
|
}
|
|
|
|
return 0;
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 19:47:28 +00:00
|
|
|
int
|
|
|
|
maildir_update_maxuid (mailbox_t * mbox)
|
2000-12-22 07:14:32 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char buf[64];
|
|
|
|
size_t len;
|
|
|
|
char path[_POSIX_PATH_MAX];
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
snprintf (path, sizeof (path), "%s/isyncmaxuid", mbox->path);
|
2002-01-16 21:22:43 +00:00
|
|
|
fd = open (path, O_WRONLY | O_CREAT, 0600);
|
2000-12-22 07:14:32 +00:00
|
|
|
if (fd == -1)
|
|
|
|
{
|
|
|
|
perror ("open");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2002-01-16 21:22:43 +00:00
|
|
|
/* write out the file */
|
|
|
|
snprintf (buf, sizeof (buf), "%u\n", mbox->maxuid);
|
|
|
|
len = write (fd, buf, strlen (buf));
|
|
|
|
if (len == (size_t) - 1)
|
2000-12-22 07:14:32 +00:00
|
|
|
{
|
2002-01-16 21:43:58 +00:00
|
|
|
perror ("write");
|
|
|
|
ret = -1;
|
2000-12-22 07:14:32 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 21:22:43 +00:00
|
|
|
if (close (fd))
|
2002-01-16 21:43:58 +00:00
|
|
|
ret = -1;
|
2000-12-22 07:14:32 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2001-11-12 23:03:33 +00:00
|
|
|
#define _24_HOURS (3600 * 24)
|
|
|
|
|
|
|
|
static void
|
|
|
|
maildir_clean_tmp (const char *mbox)
|
|
|
|
{
|
|
|
|
char path[_POSIX_PATH_MAX];
|
|
|
|
DIR *dirp;
|
|
|
|
struct dirent *entry;
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
struct stat st;
|
2001-11-12 23:03:33 +00:00
|
|
|
time_t now;
|
|
|
|
|
|
|
|
snprintf (path, sizeof (path), "%s/tmp", mbox);
|
|
|
|
dirp = opendir (path);
|
|
|
|
if (dirp == NULL)
|
|
|
|
{
|
2001-11-20 18:06:09 +00:00
|
|
|
fprintf (stderr, "maildir_clean_tmp: opendir: %s: %s (errno %d)\n",
|
|
|
|
path, strerror (errno), errno);
|
2001-11-12 23:03:33 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* assuming this scan will take less than a second, we only need to
|
|
|
|
* check the time once before the following loop.
|
|
|
|
*/
|
|
|
|
time (&now);
|
|
|
|
while ((entry = readdir (dirp)))
|
|
|
|
{
|
|
|
|
snprintf (path, sizeof (path), "%s/tmp/%s", mbox, entry->d_name);
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
if (stat (path, &st))
|
2001-11-20 18:06:09 +00:00
|
|
|
fprintf (stderr, "maildir_clean_tmp: stat: %s: %s (errno %d)\n",
|
|
|
|
path, strerror (errno), errno);
|
Bunch 'o patches from Oswald Buddenhagen:
i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).
another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
usually define your mailbox layout once forever. removed -A, as it is
semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
used throughout the program. at best, create some generic output
function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups
add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)
this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
2002-10-30 02:23:05 +00:00
|
|
|
else if (S_ISREG (st.st_mode) && now - st.st_ctime >= _24_HOURS)
|
2001-11-12 23:03:33 +00:00
|
|
|
{
|
|
|
|
/* this should happen infrequently enough that it won't be
|
|
|
|
* bothersome to the user to display when it occurs.
|
|
|
|
*/
|
|
|
|
printf ("Warning: removing stale file %s\n", path);
|
|
|
|
if (unlink (path))
|
2001-11-20 18:06:09 +00:00
|
|
|
fprintf (stderr,
|
|
|
|
"maildir_clean_tmp: unlink: %s: %s (errno %d)\n",
|
|
|
|
path, strerror (errno), errno);
|
2001-11-12 23:03:33 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-30 02:01:32 +00:00
|
|
|
closedir(dirp);
|
2001-11-12 23:03:33 +00:00
|
|
|
}
|
|
|
|
|
2002-01-16 19:47:28 +00:00
|
|
|
void
|
2001-11-12 23:03:33 +00:00
|
|
|
maildir_close (mailbox_t * mbox)
|
2000-12-20 21:41:21 +00:00
|
|
|
{
|
2002-01-16 19:47:28 +00:00
|
|
|
if (mbox->db)
|
|
|
|
dbm_close (mbox->db);
|
2000-12-22 07:14:32 +00:00
|
|
|
|
2002-01-16 19:47:28 +00:00
|
|
|
/* release the mutex on the mailbox */
|
2002-06-20 23:33:13 +00:00
|
|
|
dotlock_unlock (&mbox->lockfd);
|
2000-12-22 07:14:32 +00:00
|
|
|
|
2001-11-12 23:03:33 +00:00
|
|
|
/* per the maildir(5) specification, delivery agents are supposed to
|
|
|
|
* set a 24-hour timer on items placed in the `tmp' directory.
|
|
|
|
*/
|
|
|
|
maildir_clean_tmp (mbox->path);
|
|
|
|
|
|
|
|
free (mbox->path);
|
|
|
|
free_message (mbox->msgs);
|
|
|
|
memset (mbox, 0xff, sizeof (mailbox_t));
|
|
|
|
free (mbox);
|
2000-12-20 21:41:21 +00:00
|
|
|
}
|
2000-12-21 23:10:18 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
|
|
|
|
{
|
|
|
|
char path[_POSIX_PATH_MAX];
|
|
|
|
char buf[16];
|
|
|
|
int fd;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
snprintf (path, sizeof (path), "%s/isyncuidvalidity", mbox->path);
|
|
|
|
fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
|
|
|
perror ("open");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
snprintf (buf, sizeof (buf), "%u\n", uidvalidity);
|
|
|
|
|
|
|
|
ret = write (fd, buf, strlen (buf));
|
|
|
|
|
|
|
|
if (ret == -1)
|
2000-12-22 07:14:32 +00:00
|
|
|
perror ("write");
|
2000-12-21 23:10:18 +00:00
|
|
|
else if ((size_t) ret != strlen (buf))
|
|
|
|
ret = -1;
|
|
|
|
else
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
if (close (fd))
|
|
|
|
{
|
2000-12-22 07:14:32 +00:00
|
|
|
perror ("close");
|
2000-12-21 23:10:18 +00:00
|
|
|
ret = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
if (unlink (path))
|
|
|
|
perror ("unlink");
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|