|
|
|
@ -119,14 +119,16 @@ read_uid (const char *path, const char *file)
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* open a maildir mailbox. if `fast' is nonzero, we just check to make
|
|
|
|
|
/* 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 |
|
|
|
|
* 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. |
|
|
|
|
* if OPEN_CREATE is set, we create the mailbox if it doesn't already exist. |
|
|
|
|
*/ |
|
|
|
|
mailbox_t * |
|
|
|
|
maildir_open (const char *path, int fast) |
|
|
|
|
maildir_open (const char *path, int flags) |
|
|
|
|
{ |
|
|
|
|
char buf[_POSIX_PATH_MAX]; |
|
|
|
|
DIR *d; |
|
|
|
@ -136,27 +138,68 @@ maildir_open (const char *path, int fast)
|
|
|
|
|
mailbox_t *m; |
|
|
|
|
char *s; |
|
|
|
|
int count = 0; |
|
|
|
|
struct stat sb; |
|
|
|
|
const char *subdirs[] = { "cur", "new", "tmp" }; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
m = calloc (1, sizeof (mailbox_t)); |
|
|
|
|
/* filename expansion happens here, not in the config parser */ |
|
|
|
|
m->path = expand_strdup (path); |
|
|
|
|
|
|
|
|
|
/* check to make sure this looks like a valid maildir box */ |
|
|
|
|
snprintf (buf, sizeof (buf), "%s/new", m->path); |
|
|
|
|
if (access (buf, F_OK)) |
|
|
|
|
if (stat (m->path, &sb)) |
|
|
|
|
{ |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
perror ("access"); |
|
|
|
|
return 0; |
|
|
|
|
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); |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
fprintf (stderr, "ERROR: stat %s: %s (errno %d)\n", m->path, |
|
|
|
|
strerror (errno), errno); |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
snprintf (buf, sizeof (buf), "%s/cur", m->path); |
|
|
|
|
if (access (buf, F_OK)) |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
perror ("access"); |
|
|
|
|
return 0; |
|
|
|
|
/* 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); |
|
|
|
|
free (m->path); |
|
|
|
|
free (m); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* check for the uidvalidity value */ |
|
|
|
@ -176,7 +219,7 @@ maildir_open (const char *path, int fast)
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (fast) |
|
|
|
|
if (flags & OPEN_FAST) |
|
|
|
|
return m; |
|
|
|
|
|
|
|
|
|
cur = &m->msgs; |
|
|
|
@ -224,11 +267,11 @@ maildir_open (const char *path, int fast)
|
|
|
|
|
m->maxuidchanged = 1; |
|
|
|
|
} |
|
|
|
|
/* Courier-IMAP names it files
|
|
|
|
|
* unique,S=<size>:info |
|
|
|
|
* 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 |
|
|
|
|
* unique,U=<uid>,S=<size>:info |
|
|
|
|
*/ |
|
|
|
|
if (*s && *s != ':' && *s != ',') |
|
|
|
|
{ |
|
|
|
@ -358,7 +401,8 @@ maildir_clean_tmp (const char *mbox)
|
|
|
|
|
dirp = opendir (path); |
|
|
|
|
if (dirp == NULL) |
|
|
|
|
{ |
|
|
|
|
fprintf (stderr, "maildir_clean_tmp: opendir: %s: %s (errno %d)\n", path, strerror (errno), errno); |
|
|
|
|
fprintf (stderr, "maildir_clean_tmp: opendir: %s: %s (errno %d)\n", |
|
|
|
|
path, strerror (errno), errno); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
/* assuming this scan will take less than a second, we only need to
|
|
|
|
@ -369,7 +413,8 @@ maildir_clean_tmp (const char *mbox)
|
|
|
|
|
{ |
|
|
|
|
snprintf (path, sizeof (path), "%s/tmp/%s", mbox, entry->d_name); |
|
|
|
|
if (stat (path, &info)) |
|
|
|
|
fprintf (stderr, "maildir_clean_tmp: stat: %s: %s (errno %d)\n", path, strerror (errno), errno); |
|
|
|
|
fprintf (stderr, "maildir_clean_tmp: stat: %s: %s (errno %d)\n", |
|
|
|
|
path, strerror (errno), errno); |
|
|
|
|
else if (S_ISREG (info.st_mode) && now - info.st_ctime >= _24_HOURS) |
|
|
|
|
{ |
|
|
|
|
/* this should happen infrequently enough that it won't be
|
|
|
|
@ -377,7 +422,9 @@ maildir_clean_tmp (const char *mbox)
|
|
|
|
|
*/ |
|
|
|
|
printf ("Warning: removing stale file %s\n", path); |
|
|
|
|
if (unlink (path)) |
|
|
|
|
fprintf (stderr, "maildir_clean_tmp: unlink: %s: %s (errno %d)\n", path, strerror (errno), errno); |
|
|
|
|
fprintf (stderr, |
|
|
|
|
"maildir_clean_tmp: unlink: %s: %s (errno %d)\n", |
|
|
|
|
path, strerror (errno), errno); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|