updated year in copyright notice
the uid for each message in the maildir is now stored in a dbm database rather than the filename. this change was necessary because isync became confused if you copied a message to another folder, in which case the uid was invalid. as a result of the above change, isync now acquires a mutex on the mailbox to protect the dbm database from concurrent access. main() was reworked to continue gracefully when an error is encountered, and to always call maildir_close() so that the lock can be disabled, and the database closed.
This commit is contained in:
parent
2c648da5cf
commit
c121ec912f
|
@ -1,5 +1,8 @@
|
|||
2001-11-20 me <me@sigpipe.org>
|
||||
|
||||
* ChangeLog, Makefile.am, isync.spec:
|
||||
post 0.7-release commit
|
||||
|
||||
* Makefile.am, NEWS, isync.1, isync.h, maildir.c, main.c:
|
||||
added --create/-C command line option to force creation of the local
|
||||
maildir-style mailbox if nonexistent
|
||||
|
|
8
NEWS
8
NEWS
|
@ -1,3 +1,11 @@
|
|||
[0.8]
|
||||
|
||||
IMPORTANT: In order to fix the problem where messages copied from one mailbox
|
||||
to another were not uploaded to the new mailbox, the way Isync stores the UID
|
||||
for each message needed to be changed. As a result, you MUST delete all the
|
||||
messages in the local maildir box before using this version. Otherwise it
|
||||
will upload every message to the server thinking its a new mail.
|
||||
|
||||
[0.7]
|
||||
|
||||
Added `MaxMessages' configuration option to allow tracking of only the most
|
||||
|
|
2
TODO
2
TODO
|
@ -4,3 +4,5 @@ add support for syncing with other: and shared: via NAMESPACE
|
|||
|
||||
isync gets confused when new mail is delivered while in the middle of an
|
||||
IMAP session. need to handled those asynchronous notifications properly.
|
||||
|
||||
add a way to automatically create and sync IMAP subfolders.
|
||||
|
|
2
config.c
2
config.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
AC_INIT(isync.h)
|
||||
AM_INIT_AUTOMAKE(isync,0.7)
|
||||
AM_INIT_AUTOMAKE(isync,0.8)
|
||||
AM_PROG_CC_STDC
|
||||
AC_ARG_WITH(ssl-dir, [ --with-ssl-dir=DIR location where openssl is insalled],
|
||||
[if test -d $withval/lib; then
|
||||
|
@ -19,6 +19,7 @@ AC_CHECK_LIB(socket,socket)
|
|||
AC_CHECK_LIB(nsl,inet_ntoa)
|
||||
AC_CHECK_LIB(crypto,ERR_error_string)
|
||||
AC_CHECK_LIB(ssl,SSL_library_init)
|
||||
AC_CHECK_LIB(db,db_create)
|
||||
dnl test for gcc. use the prefix so we know that gcc-3.0 is also gcc
|
||||
if test `echo $CC | sed 's/^gcc.*/gcc/'` = gcc; then
|
||||
CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wmissing-prototypes"
|
||||
|
|
2
cram.c
2
cram.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
|
2
imap.c
2
imap.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
|
12
isync.1
12
isync.1
|
@ -1,6 +1,6 @@
|
|||
.ig
|
||||
\" isync - IMAP4 to maildir mailbox synchronizer
|
||||
\" Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
\" Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
\"
|
||||
\" 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
|
||||
|
@ -16,7 +16,7 @@
|
|||
\" along with this program; if not, write to the Free Software
|
||||
\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
..
|
||||
.TH isync 1 "2001 Nov 20"
|
||||
.TH isync 1 "2002 Jan 16"
|
||||
..
|
||||
.SH NAME
|
||||
isync - synchronize IMAP4 and maildir mailboxes
|
||||
|
@ -304,13 +304,9 @@ will then use the global value by default.
|
|||
Default configuration file
|
||||
..
|
||||
.SH BUGS
|
||||
maildir(5) states that readers should not attempt to parse the filename of a
|
||||
a message other than the :info field. However, since
|
||||
.B isync
|
||||
relies on using the message UIDs that info must be inserted into the
|
||||
filename in a way which will be interoperable with existing readers. So
|
||||
the UID is placed in the filename of the messages in the local maildir
|
||||
mailbox rather than the :info field.
|
||||
does not use NFS-safe locking. It will correctly prevent concurrent
|
||||
synchronization of a mailbox on the same host, but not across NFS.
|
||||
.P
|
||||
When synchronizing multiple mailboxes on the same IMAP server, it is not
|
||||
possible to select different SSL options for each mailbox. Only the options
|
||||
|
|
13
isync.h
13
isync.h
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
@ -18,11 +18,14 @@
|
|||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define DB_DBM_HSEARCH 1
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
#if HAVE_LIBSSL
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include <db.h>
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct
|
||||
|
@ -79,13 +82,13 @@ struct config
|
|||
/* struct representing local mailbox file */
|
||||
struct mailbox
|
||||
{
|
||||
DBM *db;
|
||||
char *path;
|
||||
message_t *msgs;
|
||||
int lockfd;
|
||||
unsigned int deleted; /* # of deleted messages */
|
||||
unsigned int uidvalidity;
|
||||
unsigned int maxuid; /* largest uid we know about */
|
||||
unsigned int changed:1;
|
||||
unsigned int maxuidchanged:1;
|
||||
};
|
||||
|
||||
/* message dispositions */
|
||||
|
@ -106,7 +109,6 @@ struct message
|
|||
message_t *next;
|
||||
unsigned int processed:1; /* message has already been evaluated */
|
||||
unsigned int new:1; /* message is in the new/ subdir */
|
||||
unsigned int changed:1; /* flags changed */
|
||||
unsigned int dead:1; /* message doesn't exist on the server */
|
||||
unsigned int wanted:1; /* when using MaxMessages, keep this message */
|
||||
};
|
||||
|
@ -191,7 +193,8 @@ int imap_append_message (imap_t *, int, message_t *);
|
|||
mailbox_t *maildir_open (const char *, int flags);
|
||||
int maildir_expunge (mailbox_t *, int);
|
||||
int maildir_set_uidvalidity (mailbox_t *, unsigned int uidvalidity);
|
||||
int maildir_close (mailbox_t *);
|
||||
void maildir_close (mailbox_t *);
|
||||
int maildir_update_maxuid (mailbox_t * mbox);
|
||||
|
||||
message_t * find_msg (message_t * list, unsigned int uid);
|
||||
void free_message (message_t *);
|
||||
|
|
2
list.c
2
list.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
|
204
maildir.c
204
maildir.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
@ -85,7 +85,7 @@ read_uid (const char *path, const char *file)
|
|||
{
|
||||
char full[_POSIX_PATH_MAX];
|
||||
int fd;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
int len;
|
||||
char buf[64];
|
||||
unsigned int uid = 0;
|
||||
|
@ -96,29 +96,59 @@ read_uid (const char *path, const char *file)
|
|||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
perror ("open");
|
||||
perror (full);
|
||||
return -1;
|
||||
}
|
||||
return 0; /* doesn't exist */
|
||||
}
|
||||
ret = do_lock (fd, F_RDLCK);
|
||||
if (!ret)
|
||||
{
|
||||
len = read (fd, buf, sizeof (buf) - 1);
|
||||
if (len == -1)
|
||||
{
|
||||
perror ("read");
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[len] = 0;
|
||||
uid = atol (buf);
|
||||
}
|
||||
}
|
||||
ret |= do_lock (fd, F_UNLCK);
|
||||
close (fd);
|
||||
return ret ? (unsigned int) ret : uid;
|
||||
|
||||
}
|
||||
|
||||
/* NOTE: this is NOT NFS safe */
|
||||
static int
|
||||
maildir_lock (mailbox_t * m)
|
||||
{
|
||||
char path[_POSIX_PATH_MAX];
|
||||
|
||||
snprintf (path, sizeof (path), "%s/isynclock", m->path);
|
||||
m->lockfd = open (path, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR);
|
||||
if (m->lockfd == -1)
|
||||
{
|
||||
perror (path);
|
||||
return -1;
|
||||
}
|
||||
if (do_lock (m->lockfd, F_WRLCK))
|
||||
{
|
||||
close (m->lockfd);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
maildir_unlock (mailbox_t * m)
|
||||
{
|
||||
char path[_POSIX_PATH_MAX];
|
||||
|
||||
snprintf (path, sizeof (path), "%s/isynclock", m->path);
|
||||
unlink (path);
|
||||
do_lock (m->lockfd, F_UNLCK);
|
||||
close (m->lockfd);
|
||||
}
|
||||
|
||||
/* open a maildir mailbox.
|
||||
* if OPEN_FAST is set, we just check to make
|
||||
* sure its a valid mailbox and don't actually parse it. any IMAP messages
|
||||
|
@ -141,8 +171,10 @@ maildir_open (const char *path, int flags)
|
|||
struct stat sb;
|
||||
const char *subdirs[] = { "cur", "new", "tmp" };
|
||||
int i;
|
||||
datum key;
|
||||
|
||||
m = calloc (1, sizeof (mailbox_t));
|
||||
m->lockfd = -1;
|
||||
/* filename expansion happens here, not in the config parser */
|
||||
m->path = expand_strdup (path);
|
||||
|
||||
|
@ -154,9 +186,7 @@ maildir_open (const char *path, int flags)
|
|||
{
|
||||
fprintf (stderr, "ERROR: mkdir %s: %s (errno %d)\n",
|
||||
m->path, strerror (errno), errno);
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
|
@ -166,9 +196,7 @@ maildir_open (const char *path, int flags)
|
|||
{
|
||||
fprintf (stderr, "ERROR: mkdir %s: %s (errno %d)\n",
|
||||
buf, strerror (errno), errno);
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,9 +205,7 @@ maildir_open (const char *path, int flags)
|
|||
{
|
||||
fprintf (stderr, "ERROR: stat %s: %s (errno %d)\n", m->path,
|
||||
strerror (errno), errno);
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -195,33 +221,37 @@ maildir_open (const char *path, int flags)
|
|||
fprintf (stderr,
|
||||
"ERROR: %s does not appear to be a valid maildir style mailbox\n",
|
||||
m->path);
|
||||
free (m->path);
|
||||
free (m);
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we need a mutex on the maildir because of the state files that isync
|
||||
* uses.
|
||||
*/
|
||||
if (maildir_lock (m))
|
||||
goto err;
|
||||
|
||||
/* check for the uidvalidity value */
|
||||
m->uidvalidity = read_uid (m->path, "isyncuidvalidity");
|
||||
if (m->uidvalidity == (unsigned int) -1)
|
||||
{
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
}
|
||||
goto err;
|
||||
|
||||
/* load the current maxuid */
|
||||
if ((m->maxuid = read_uid (m->path, "isyncmaxuid")) == (unsigned int) -1)
|
||||
{
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
}
|
||||
goto err;
|
||||
|
||||
if (flags & OPEN_FAST)
|
||||
return m;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
cur = &m->msgs;
|
||||
for (; count < 2; count++)
|
||||
{
|
||||
|
@ -231,10 +261,8 @@ maildir_open (const char *path, int flags)
|
|||
d = opendir (buf);
|
||||
if (!d)
|
||||
{
|
||||
free (m->path);
|
||||
free (m);
|
||||
perror ("opendir");
|
||||
return 0;
|
||||
goto err;
|
||||
}
|
||||
while ((e = readdir (d)))
|
||||
{
|
||||
|
@ -247,40 +275,25 @@ maildir_open (const char *path, int flags)
|
|||
p->flags = 0;
|
||||
p->new = (count == 0);
|
||||
|
||||
/* filename format is something like:
|
||||
* <unique-prefix>,U=<n>:2,<flags>
|
||||
* This is completely non-standard, but in order for mail
|
||||
* clients to understand the flags, we have to use the
|
||||
* standard :info as described by the qmail spec
|
||||
/* determine the UID for this message. The basename (sans
|
||||
* flags) is used as the key in the db
|
||||
*/
|
||||
s = strstr (p->file, ",U=");
|
||||
if (!s)
|
||||
s = strstr (p->file, "UID");
|
||||
if (!s)
|
||||
puts ("Warning, no UID for message");
|
||||
else
|
||||
{
|
||||
p->uid = strtol (s + 3, &s, 10);
|
||||
if (p->uid > m->maxuid)
|
||||
{
|
||||
m->maxuid = p->uid;
|
||||
m->maxuidchanged = 1;
|
||||
}
|
||||
/* Courier-IMAP names it files
|
||||
* unique,S=<size>:info
|
||||
* so we need to put the UID before the size, hence here
|
||||
* we check for a comma as a valid terminator as well,
|
||||
* since the format will be
|
||||
* unique,U=<uid>,S=<size>:info
|
||||
*/
|
||||
if (*s && *s != ':' && *s != ',')
|
||||
{
|
||||
puts ("Warning, unable to parse UID");
|
||||
p->uid = -1; /* reset */
|
||||
}
|
||||
}
|
||||
|
||||
strfcpy (buf, p->file, sizeof (buf));
|
||||
s = strchr (p->file, ':');
|
||||
if (s)
|
||||
*s = 0;
|
||||
key.dptr = buf;
|
||||
key.dsize = strlen (buf);
|
||||
key = dbm_fetch (m->db, key);
|
||||
if (key.dptr)
|
||||
{
|
||||
p->uid = *(int *) key.dptr;
|
||||
if (p->uid > m->maxuid)
|
||||
m->maxuid = p->uid;
|
||||
}
|
||||
else
|
||||
puts ("Warning, no UID for message");
|
||||
|
||||
if (s)
|
||||
parse_info (p, s + 1);
|
||||
if (p->flags & D_DELETED)
|
||||
|
@ -290,6 +303,15 @@ maildir_open (const char *path, int flags)
|
|||
closedir (d);
|
||||
}
|
||||
return m;
|
||||
|
||||
err:
|
||||
if (m->db)
|
||||
dbm_close (m->db);
|
||||
if (m->lockfd != -1)
|
||||
maildir_unlock (m);
|
||||
free (m->path);
|
||||
free (m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* permanently remove messages from a maildir mailbox. if `dead' is nonzero,
|
||||
|
@ -322,8 +344,8 @@ maildir_expunge (mailbox_t * mbox, int dead)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
update_maxuid (mailbox_t * mbox)
|
||||
int
|
||||
maildir_update_maxuid (mailbox_t * mbox)
|
||||
{
|
||||
int fd;
|
||||
char buf[64];
|
||||
|
@ -355,7 +377,7 @@ update_maxuid (mailbox_t * mbox)
|
|||
uid = atol (buf);
|
||||
if (uid > mbox->maxuid)
|
||||
{
|
||||
puts ("Error, maxuid is now higher (fatal)");
|
||||
fputs ("ERROR: maxuid is now higher (fatal)\n", stderr);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
|
@ -429,48 +451,14 @@ maildir_clean_tmp (const char *mbox)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
maildir_close (mailbox_t * mbox)
|
||||
{
|
||||
message_t *cur = mbox->msgs;
|
||||
char path[_POSIX_PATH_MAX];
|
||||
char oldpath[_POSIX_PATH_MAX];
|
||||
char *p;
|
||||
int ret = 0;
|
||||
if (mbox->db)
|
||||
dbm_close (mbox->db);
|
||||
|
||||
if (mbox->changed)
|
||||
{
|
||||
for (; cur; cur = cur->next)
|
||||
{
|
||||
if (cur->changed)
|
||||
{
|
||||
/* generate old path */
|
||||
snprintf (oldpath, sizeof (oldpath), "%s/%s/%s",
|
||||
mbox->path, cur->new ? "new" : "cur", cur->file);
|
||||
|
||||
/* truncate old flags (if present) */
|
||||
p = strchr (cur->file, ':');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
/* generate new path - always put this in the cur/ directory
|
||||
* because its no longer new
|
||||
*/
|
||||
snprintf (path, sizeof (path), "%s/cur/%s:2,%s%s%s%s",
|
||||
mbox->path,
|
||||
cur->file, (cur->flags & D_FLAGGED) ? "F" : "",
|
||||
(cur->flags & D_ANSWERED) ? "R" : "",
|
||||
(cur->flags & D_SEEN) ? "S" : "",
|
||||
(cur->flags & D_DELETED) ? "T" : "");
|
||||
|
||||
if (rename (oldpath, path))
|
||||
perror ("rename");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mbox->maxuidchanged)
|
||||
ret = update_maxuid (mbox);
|
||||
/* release the mutex on the mailbox */
|
||||
maildir_unlock (mbox);
|
||||
|
||||
/* per the maildir(5) specification, delivery agents are supposed to
|
||||
* set a 24-hour timer on items placed in the `tmp' directory.
|
||||
|
@ -481,8 +469,6 @@ maildir_close (mailbox_t * mbox)
|
|||
free_message (mbox->msgs);
|
||||
memset (mbox, 0xff, sizeof (mailbox_t));
|
||||
free (mbox);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
51
main.c
51
main.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
@ -67,7 +67,7 @@ static void
|
|||
usage (void)
|
||||
{
|
||||
printf ("%s %s IMAP4 to maildir synchronizer\n", PACKAGE, VERSION);
|
||||
puts ("Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>");
|
||||
puts ("Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>");
|
||||
printf ("usage: %s [ flags ] mailbox [mailbox ...]\n", PACKAGE);
|
||||
puts (" -a, --all Synchronize all defined mailboxes");
|
||||
puts (" -c, --config CONFIG read an alternate config file (default: ~/.isyncrc)");
|
||||
|
@ -134,7 +134,7 @@ main (int argc, char **argv)
|
|||
{
|
||||
int i;
|
||||
config_t *box = 0;
|
||||
mailbox_t *mail;
|
||||
mailbox_t *mail = 0;
|
||||
imap_t *imap = 0;
|
||||
int expunge = 0; /* by default, don't delete anything */
|
||||
int fast = 0;
|
||||
|
@ -250,6 +250,9 @@ main (int argc, char **argv)
|
|||
if (!global.host)
|
||||
{
|
||||
fprintf (stderr, "%s: no such mailbox\n", argv[optind]);
|
||||
/* continue is ok here because we are not handling the
|
||||
* `all' case.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
global.path = argv[optind];
|
||||
|
@ -257,6 +260,7 @@ main (int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
do {
|
||||
if (!box->pass)
|
||||
{
|
||||
/* if we don't have a global password set, prompt the user for
|
||||
|
@ -267,8 +271,8 @@ main (int argc, char **argv)
|
|||
global.pass = getpass ("Password:");
|
||||
if (!global.pass)
|
||||
{
|
||||
puts ("Aborting, no password");
|
||||
exit (1);
|
||||
fprintf (stderr, "Skipping %s, no password", box->path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
box->pass = strdup (global.pass);
|
||||
|
@ -284,8 +288,8 @@ main (int argc, char **argv)
|
|||
mail = maildir_open (box->path, i);
|
||||
if (!mail)
|
||||
{
|
||||
fprintf (stderr, "ERROR: unable to load mailbox %s\n", box->path);
|
||||
goto cleanup;
|
||||
fprintf (stderr, "%s: unable to open mailbox\n", box->path);
|
||||
break;
|
||||
}
|
||||
|
||||
imap = imap_open (box, fast ? mail->maxuid + 1 : 1, imap);
|
||||
|
@ -293,7 +297,7 @@ main (int argc, char **argv)
|
|||
{
|
||||
fprintf (stderr, "%s: skipping mailbox due to IMAP error\n",
|
||||
box->path);
|
||||
goto cleanup;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!quiet)
|
||||
|
@ -304,23 +308,33 @@ main (int argc, char **argv)
|
|||
i |= (delete || box->delete) ? SYNC_DELETE : 0;
|
||||
i |= (expunge || box->expunge) ? SYNC_EXPUNGE : 0;
|
||||
if (sync_mailbox (mail, imap, i, box->max_size, box->max_messages))
|
||||
exit (1);
|
||||
{
|
||||
imap_close (imap); /* Just to be safe. Don't really know
|
||||
* what the problem was.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fast)
|
||||
{
|
||||
if ((expunge || box->expunge) && (imap->deleted || mail->deleted))
|
||||
if ((expunge || box->expunge) &&
|
||||
(imap->deleted || mail->deleted))
|
||||
{
|
||||
/* remove messages marked for deletion */
|
||||
if (!quiet)
|
||||
printf ("Expunging %d messages from server\n",
|
||||
imap->deleted);
|
||||
if (imap_expunge (imap))
|
||||
exit (1);
|
||||
{
|
||||
imap_close (imap);
|
||||
imap = NULL;
|
||||
break;
|
||||
}
|
||||
if (!quiet)
|
||||
printf ("Expunging %d messages from local mailbox\n",
|
||||
mail->deleted);
|
||||
if (maildir_expunge (mail, 0))
|
||||
exit (1);
|
||||
break;
|
||||
}
|
||||
/* remove messages deleted from server. this can safely be an
|
||||
* `else' clause since dead messages are marked as deleted by
|
||||
|
@ -330,14 +344,15 @@ main (int argc, char **argv)
|
|||
maildir_expunge (mail, 1);
|
||||
}
|
||||
|
||||
/* write changed flags back to the mailbox */
|
||||
if (!quiet)
|
||||
printf ("Committing changes to %s\n", mail->path);
|
||||
} while (0);
|
||||
|
||||
if (maildir_close (mail))
|
||||
exit (1);
|
||||
/* we never sync the same mailbox twice, so close it now */
|
||||
if (mail)
|
||||
maildir_close (mail);
|
||||
|
||||
cleanup:
|
||||
/* the imap connection is not closed so we can keep the connection
|
||||
* open, and there is no IMAP command for un-SELECT-ing a mailbox.
|
||||
*/
|
||||
if (all)
|
||||
box = box->next;
|
||||
}
|
||||
|
|
92
sync.c
92
sync.c
|
@ -1,7 +1,7 @@
|
|||
/* $Id$
|
||||
*
|
||||
* isync - IMAP4 to maildir mailbox synchronizer
|
||||
* Copyright (C) 2000-1 Michael R. Elkins <me@mutt.org>
|
||||
* Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>
|
||||
*
|
||||
* 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
|
||||
|
@ -40,6 +40,24 @@ find_msg (message_t * list, unsigned int uid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_uid (DBM *db, const char *f, unsigned int uid)
|
||||
{
|
||||
char path[_POSIX_PATH_MAX];
|
||||
char *s;
|
||||
datum key, val;
|
||||
|
||||
strfcpy (path, f, sizeof (path));
|
||||
s = strchr (path, ':');
|
||||
if (s)
|
||||
*s = 0;
|
||||
key.dptr = path;
|
||||
key.dsize = strlen (path);
|
||||
val.dptr = (void*) &uid;
|
||||
val.dsize = sizeof (uid);
|
||||
dbm_store (db, key, val, DBM_REPLACE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
||||
unsigned int max_size, unsigned int max_msgs)
|
||||
|
@ -76,7 +94,8 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
if (mbox->maxuid == 0 || imap->maxuid > mbox->maxuid)
|
||||
{
|
||||
mbox->maxuid = imap->maxuid;
|
||||
mbox->maxuidchanged = 1;
|
||||
if (maildir_update_maxuid (mbox))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if we are --fast mode, the mailbox wont have been loaded, so
|
||||
|
@ -93,7 +112,6 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
if (cur->uid == (unsigned int) -1)
|
||||
{
|
||||
struct stat sb;
|
||||
int uid;
|
||||
|
||||
if ((flags & SYNC_QUIET) == 0)
|
||||
{
|
||||
|
@ -132,35 +150,12 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
}
|
||||
|
||||
cur->size = sb.st_size;
|
||||
|
||||
uid = imap_append_message (imap, fd, cur);
|
||||
cur->uid = imap_append_message (imap, fd, cur);
|
||||
/* if the server gave us back a uid, update the db */
|
||||
if (cur->uid != (unsigned int) -1)
|
||||
set_uid (mbox->db, cur->file, cur->uid);
|
||||
|
||||
close (fd);
|
||||
|
||||
/* if the server gave us back a uid, rename the file so
|
||||
* we remember for next time
|
||||
*/
|
||||
if (uid != -1)
|
||||
{
|
||||
strfcpy (newpath, path, sizeof (newpath));
|
||||
/* kill :info field */
|
||||
p = strchr (newpath, ':');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
/* XXX not quite right, should really always put the
|
||||
* msg in "cur/", but i'm too tired right now.
|
||||
*/
|
||||
snprintf (newpath + strlen (newpath),
|
||||
sizeof (newpath) - strlen (newpath),
|
||||
",U=%d:2,%s%s%s%s", uid,
|
||||
(cur->flags & D_FLAGGED) ? "F" : "",
|
||||
(cur->flags & D_ANSWERED) ? "R" : "",
|
||||
(cur->flags & D_SEEN) ? "S" : "",
|
||||
(cur->flags & D_DELETED) ? "T" : "");
|
||||
if (rename (path, newpath))
|
||||
perror ("rename");
|
||||
}
|
||||
}
|
||||
else if (flags & SYNC_DELETE)
|
||||
{
|
||||
|
@ -187,7 +182,7 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
if (imap_copy_message (imap, cur->uid,
|
||||
imap->box->copy_deleted_to))
|
||||
{
|
||||
printf ("Error, unable to copy deleted message to \"%s\"\n",
|
||||
fprintf (stderr, "ERROR: unable to copy deleted message to \"%s\"\n",
|
||||
imap->box->copy_deleted_to);
|
||||
return -1;
|
||||
}
|
||||
|
@ -208,8 +203,28 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
if ((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
|
||||
mbox->deleted++;
|
||||
cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
|
||||
cur->changed = 1;
|
||||
mbox->changed = 1;
|
||||
|
||||
/* generate old path */
|
||||
snprintf (path, sizeof (path), "%s/%s/%s",
|
||||
mbox->path, cur->new ? "new" : "cur", cur->file);
|
||||
|
||||
/* truncate old flags (if present) */
|
||||
p = strchr (cur->file, ':');
|
||||
if (p)
|
||||
*p = 0;
|
||||
|
||||
/* generate new path - always put this in the cur/ directory
|
||||
* because its no longer new
|
||||
*/
|
||||
snprintf (newpath, sizeof (newpath), "%s/cur/%s:2,%s%s%s%s",
|
||||
mbox->path,
|
||||
cur->file, (cur->flags & D_FLAGGED) ? "F" : "",
|
||||
(cur->flags & D_ANSWERED) ? "R" : "",
|
||||
(cur->flags & D_SEEN) ? "S" : "",
|
||||
(cur->flags & D_DELETED) ? "T" : "");
|
||||
|
||||
if (rename (path, newpath))
|
||||
perror ("rename");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,15 +304,15 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
for (;;)
|
||||
{
|
||||
/* create new file */
|
||||
snprintf (path, sizeof (path), "%s/tmp/%ld_%d.%d.%s,U=%d%s",
|
||||
snprintf (path, sizeof (path), "%s/tmp/%ld_%d.%d.%s%s",
|
||||
mbox->path, time (0), MaildirCount++, getpid (),
|
||||
Hostname, cur->uid, suffix);
|
||||
Hostname, suffix);
|
||||
|
||||
if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) > 0)
|
||||
break;
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
perror ("open");
|
||||
perror (path);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -336,6 +351,11 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
|
|||
*/
|
||||
if (link (path, newpath))
|
||||
perror ("link");
|
||||
else
|
||||
{
|
||||
/* update the db with the UID mapping for this file */
|
||||
set_uid (mbox->db, newpath, cur->uid);
|
||||
}
|
||||
}
|
||||
|
||||
/* always remove the temp file */
|
||||
|
|
Loading…
Reference in New Issue
Block a user