commit 19d86d2aa9415047d8e0a391bd2502023bff80fc
Author: Oswald Buddenhagen <[email protected]>
Date: Mon Mar 10 11:57:37 2014 +0100
rework maildir store mapping
the trivial approach of having "home" and "root" stores produced ugly
results, and totally failed with the introduction of nested folder
handling.
instead, create a store per local directory, just as one would manually.
CCMAIL: [email protected]
src/compat/config.c | 86 +++++++++++++++++++++++++++++++------------
src/compat/isync.h | 7 +++
src/compat/util.c | 13 ++++++
3 files changed, 82 insertions(+), 24 deletions(-)
diff --git a/src/compat/config.c b/src/compat/config.c
index 2e160b6..39bbbe9 100644
--- a/src/compat/config.c
+++ b/src/compat/config.c
@@ -29,8 +29,6 @@
#include <stdio.h>
#include <ctype.h>
-static int local_home, local_root;
-
static char *
my_strndup( const char *s, size_t nchars )
{
@@ -121,16 +119,6 @@ load_config( const char *path, config_t ***stor )
cfg = **stor = nfmalloc( sizeof(config_t) );
*stor = &cfg->next;
memcpy( cfg, &global, sizeof(config_t) );
- if (val[0] == '~' && val[1] == '/') {
- val += 2;
- local_home = 1;
- } else if (!memcmp( val, Home, HomeLen ) &&
val[HomeLen] == '/') {
- val += HomeLen + 1;
- local_home = 1;
- } else if (val[0] == '/')
- local_root = 1;
- else
- local_home = 1;
/* not expanded at this point */
cfg->path = nfstrdup( val );
} else if (!strcasecmp( "OneToOne", cmd )) {
@@ -382,7 +370,9 @@ write_config( int fd )
{
FILE *fp;
const char *cn, *scn;
+ char *path, *local_box, *local_store;
config_t *box, *sbox, *pbox;
+ int pl;
if (!(fp = fdopen( fd, "w" ))) {
perror( "fdopen" );
@@ -395,15 +385,17 @@ write_config( int fd )
if (global.expunge || expunge)
fputs( "Expunge Both\n", fp );
fputc( '\n', fp );
- if (local_home || o2o)
- fprintf( fp, "MaildirStore local\nPath \"%s/\"\nInbox
\"%s/INBOX\"\nAltMap %s\n\n",
- maildir, maildir, tb( altmap > 0 ) );
- if (local_root)
- fprintf( fp, "MaildirStore local_root\nPath /\nAltMap %s\n\n",
tb( altmap > 0 ) );
if (o2o) {
write_imap_server( fp, &global );
write_imap_store( fp, &global );
- fprintf( fp, "Channel o2o\nMaster :%s:\nSlave :local:\nPattern
%%\n", global.store_name );
+ fprintf( fp, "MaildirStore local\nPath %s/\n", quotify( maildir
) );
+ if (!inbox) { /* just in case listing actually produces an
INBOX ... */
+ nfasprintf( (char **)&inbox, "%s/INBOX", maildir );
+ fprintf( fp, "Inbox %s\n", quotify( inbox ) );
+ }
+ if (altmap > 0)
+ fputs( "AltMap yes\n", fp );
+ fprintf( fp, "\nChannel o2o\nMaster :%s:\nSlave
:local:\nPattern %%\n", global.store_name );
write_channel_parm( fp, &global );
} else {
for (box = boxes; box; box = box->next) {
@@ -446,6 +438,55 @@ write_config( int fd )
gotsrv:
write_imap_store( fp, box );
gotall:
+
+ path = expand_strdup( box->path );
+ if (!memcmp( path, Home, HomeLen ) && path[HomeLen] ==
'/')
+ nfasprintf( &path, "~%s", path + HomeLen );
+ local_store = local_box = strrchr( path, '/' ) + 1;
+ pl = local_store - path;
+ /* try to re-use existing store */
+ for (pbox = boxes; pbox != box; pbox = pbox->next)
+ if (pbox->local_store_path && !memcmp(
pbox->local_store_path, path, pl ) && !pbox->local_store_path[pl])
+ goto gotstor;
+ box->local_store_path = my_strndup( path, pl );
+ /* derive a suitable name */
+ if (!strcmp( box->local_store_path, "/var/mail/" ) ||
!strcmp( box->local_store_path, "/var/spool/mail/" )) {
+ local_store = nfstrdup( "spool" );
+ } else if (!strcmp( box->local_store_path, "~/" )) {
+ local_store = nfstrdup( "home" );
+ } else {
+ local_store = memrchr( box->local_store_path,
'/', pl - 1 );
+ if (local_store) {
+ local_store = my_strndup( local_store +
1, pl - 2 - (local_store - box->local_store_path) );
+ for (pl = 0; local_store[pl]; pl++)
+ local_store[pl] = tolower(
local_store[pl] );
+ } else {
+ local_store = nfstrdup( "local" );
+ }
+ }
+ /* avoid name clashes with imap stores */
+ for (pbox = boxes; pbox != box; pbox = pbox->next)
+ if (!strcmp( pbox->store_name, local_store )) {
+ nfasprintf( &local_store, "local_%s",
local_store );
+ goto gotsdup;
+ }
+ gotsdup:
+ /* avoid name clashes with other local stores */
+ for (pbox = boxes; pbox != box; pbox = pbox->next)
+ if (pbox->local_store_name && !strcmp(
pbox->local_store_name, local_store )) {
+ nfasprintf( (char
**)&box->local_store_name, "%s-%d", local_store, ++pbox->local_stores );
+ goto gotdup;
+ }
+ box->local_store_name = local_store;
+ box->local_stores = 1;
+ gotdup:
+ fprintf( fp, "MaildirStore %s\nPath %s\n",
box->local_store_name, quotify( box->local_store_path ) );
+ if (altmap > 0)
+ fputs( "AltMap yes\n", fp );
+ fputc( '\n', fp );
+ pbox = box;
+ gotstor:
+
if (box->alias)
cn = box->alias;
else {
@@ -473,12 +514,9 @@ write_config( int fd )
box->channels = 1;
box->channel_name = cn;
gotchan:
- if (box->path[0] == '/')
- fprintf( fp, "Channel %s\nMaster
:%s:\"%s\"\nSlave :local_root:\"%s\"\n",
- box->channel_name, box->store_name,
box->box, box->path + 1 );
- else
- fprintf( fp, "Channel %s\nMaster
:%s:\"%s\"\nSlave :local:\"%s\"\n",
- box->channel_name, box->store_name,
box->box, box->path );
+
+ fprintf( fp, "Channel %s\nMaster :%s:%s\nSlave
:%s:%s\n",
+ box->channel_name, box->store_name,
quotify( box->box ), pbox->local_store_name, quotify( local_box ) );
write_channel_parm( fp, box );
}
diff --git a/src/compat/isync.h b/src/compat/isync.h
index 1181aae..b8c7cc2 100644
--- a/src/compat/isync.h
+++ b/src/compat/isync.h
@@ -56,6 +56,9 @@ typedef struct config {
const char *store_name;
int stores;
+ const char *local_store_name;
+ const char *local_store_path;
+ int local_stores;
char *copy_deleted_to;
unsigned int use_namespace:1;
@@ -99,3 +102,7 @@ int nfasprintf( char **str, const char *fmt, ... );
int nfsnprintf( char *buf, int blen, const char *fmt, ... );
void sys_error( const char *, ... );
void ATTR_NORETURN oob( void );
+
+#ifndef HAVE_MEMRCHR
+void *memrchr( const void *s, int c, size_t n );
+#endif
diff --git a/src/compat/util.c b/src/compat/util.c
index cca2072..f7389a2 100644
--- a/src/compat/util.c
+++ b/src/compat/util.c
@@ -87,6 +87,19 @@ vasprintf( char **strp, const char *fmt, va_list ap )
}
#endif
+#ifndef HAVE_MEMRCHR
+void *
+memrchr( const void *s, int c, size_t n )
+{
+ u_char *b = (u_char *)s, *e = b + n;
+
+ while (--e >= b)
+ if (*e == c)
+ return (void *)e;
+ return 0;
+}
+#endif
+
void
oob( void )
{
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/13534_NeoTech
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel