re-interpret relative local paths in config file
this makes config+data file "sets" relocatable, which is useful for testing. this is technically a gratuitous backwards incompatible behavior change, but to the degree that anyone uses relative paths at all, they almost certainly rely on PWD being set up such that they won't see a difference.
This commit is contained in:
parent
cf13630a00
commit
d3f118be79
3
NEWS
3
NEWS
|
@ -3,6 +3,9 @@
|
|||
Changed default config & state locations to follow the XDG basedir spec.
|
||||
The old locations remain supported.
|
||||
|
||||
The reference point for relative local paths in the configuration file
|
||||
is now the file's containing directory.
|
||||
|
||||
[1.4.0]
|
||||
|
||||
The 'isync' compatibility wrapper was removed.
|
||||
|
|
23
src/config.c
23
src/config.c
|
@ -23,7 +23,7 @@ char FieldDelimiter = ':';
|
|||
static store_conf_t *stores;
|
||||
|
||||
char *
|
||||
expand_strdup( const char *s )
|
||||
expand_strdup( const char *s, const conffile_t *cfile )
|
||||
{
|
||||
struct passwd *pw;
|
||||
const char *p, *q;
|
||||
|
@ -51,6 +51,9 @@ expand_strdup( const char *s )
|
|||
}
|
||||
nfasprintf( &r, "%s%s", q, p ? p : "" );
|
||||
return r;
|
||||
} else if (*s != '/') {
|
||||
nfasprintf( &r, "%.*s%s", cfile->path_len, cfile->file, s );
|
||||
return r;
|
||||
} else {
|
||||
return nfstrdup( s );
|
||||
}
|
||||
|
@ -220,7 +223,7 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
|
|||
} while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
|
||||
conf->ops[F] |= XOP_HAVE_TYPE;
|
||||
} else if (!strcasecmp( "SyncState", cfile->cmd )) {
|
||||
conf->sync_state = expand_strdup( cfile->val );
|
||||
conf->sync_state = !strcmp( cfile->val, "*" ) ? "*" : expand_strdup( cfile->val, cfile );
|
||||
} else if (!strcasecmp( "CopyArrivalDate", cfile->cmd )) {
|
||||
conf->use_internal_date = parse_bool( cfile );
|
||||
} else if (!strcasecmp( "MaxMessages", cfile->cmd )) {
|
||||
|
@ -354,25 +357,35 @@ load_config( const char *where )
|
|||
char buf[1024];
|
||||
|
||||
if (!where) {
|
||||
int path_len, path_len2;
|
||||
const char *config_home = getenv( "XDG_CONFIG_HOME" );
|
||||
if (config_home)
|
||||
nfsnprintf( path, sizeof(path), "%s/isyncrc", config_home );
|
||||
nfsnprintf( path, sizeof(path), "%s/%nisyncrc", config_home, &path_len );
|
||||
else
|
||||
nfsnprintf( path, sizeof(path), "%s/.config/isyncrc", Home );
|
||||
nfsnprintf( path2, sizeof(path2), "%s/.mbsyncrc", Home );
|
||||
nfsnprintf( path, sizeof(path), "%s/.config/%nisyncrc", Home, &path_len );
|
||||
nfsnprintf( path2, sizeof(path2), "%s/%n.mbsyncrc", Home, &path_len2 );
|
||||
struct stat st;
|
||||
int ex = !lstat( path, &st );
|
||||
int ex2 = !lstat( path2, &st );
|
||||
if (ex2 && !ex) {
|
||||
cfile.file = path2;
|
||||
cfile.path_len = path_len2;
|
||||
} else {
|
||||
if (ex && ex2)
|
||||
warn( "Both %s and %s exist; using the former.\n", path, path2 );
|
||||
cfile.file = path;
|
||||
cfile.path_len = path_len;
|
||||
}
|
||||
} else {
|
||||
const char *sl = strrchr( where, '/' );
|
||||
if (!sl) {
|
||||
nfsnprintf( path, sizeof(path), "./%n%s", &cfile.path_len, where );
|
||||
cfile.file = path;
|
||||
} else {
|
||||
cfile.path_len = sl - where + 1;
|
||||
cfile.file = where;
|
||||
}
|
||||
}
|
||||
|
||||
info( "Reading configuration file %s\n", cfile.file );
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ typedef struct {
|
|||
int line;
|
||||
int err;
|
||||
int ms_warn;
|
||||
int path_len;
|
||||
char *cmd, *val, *rest;
|
||||
} conffile_t;
|
||||
|
||||
|
@ -26,7 +27,7 @@ extern char FieldDelimiter;
|
|||
#define ARG_OPTIONAL 0
|
||||
#define ARG_REQUIRED 1
|
||||
|
||||
char *expand_strdup( const char *s );
|
||||
char *expand_strdup( const char *s, const conffile_t *cfile );
|
||||
|
||||
char *get_arg( conffile_t *cfile, int required, int *comment );
|
||||
|
||||
|
|
|
@ -3590,7 +3590,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
||||
#ifdef HAVE_LIBSSL
|
||||
} else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
|
||||
server->sconf.cert_file = expand_strdup( cfg->val );
|
||||
server->sconf.cert_file = expand_strdup( cfg->val, cfg );
|
||||
if (access( server->sconf.cert_file, R_OK )) {
|
||||
sys_error( "%s:%d: CertificateFile '%s'",
|
||||
cfg->file, cfg->line, server->sconf.cert_file );
|
||||
|
@ -3599,14 +3599,14 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
} else if (!strcasecmp( "SystemCertificates", cfg->cmd )) {
|
||||
server->sconf.system_certs = parse_bool( cfg );
|
||||
} else if (!strcasecmp( "ClientCertificate", cfg->cmd )) {
|
||||
server->sconf.client_certfile = expand_strdup( cfg->val );
|
||||
server->sconf.client_certfile = expand_strdup( cfg->val, cfg );
|
||||
if (access( server->sconf.client_certfile, R_OK )) {
|
||||
sys_error( "%s:%d: ClientCertificate '%s'",
|
||||
cfg->file, cfg->line, server->sconf.client_certfile );
|
||||
cfg->err = 1;
|
||||
}
|
||||
} else if (!strcasecmp( "ClientKey", cfg->cmd )) {
|
||||
server->sconf.client_keyfile = expand_strdup( cfg->val );
|
||||
server->sconf.client_keyfile = expand_strdup( cfg->val, cfg );
|
||||
if (access( server->sconf.client_keyfile, R_OK )) {
|
||||
sys_error( "%s:%d: ClientKey '%s'",
|
||||
cfg->file, cfg->line, server->sconf.client_keyfile );
|
||||
|
|
|
@ -1857,9 +1857,9 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
|
||||
while (getcline( cfg ) && cfg->cmd) {
|
||||
if (!strcasecmp( "Inbox", cfg->cmd )) {
|
||||
store->inbox = expand_strdup( cfg->val );
|
||||
store->inbox = expand_strdup( cfg->val, cfg );
|
||||
} else if (!strcasecmp( "Path", cfg->cmd )) {
|
||||
store->path = expand_strdup( cfg->val );
|
||||
store->path = expand_strdup( cfg->val, cfg );
|
||||
#ifdef USE_DB
|
||||
} else if (!strcasecmp( "AltMap", cfg->cmd )) {
|
||||
store->alt_map = parse_bool( cfg );
|
||||
|
@ -1892,7 +1892,7 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
|
|||
}
|
||||
}
|
||||
if (!store->inbox)
|
||||
store->inbox = expand_strdup( "~/Maildir" );
|
||||
store->inbox = expand_strdup( "~/Maildir", NULL );
|
||||
if (store->sub_style == SUB_MAILDIRPP && store->path) {
|
||||
error( "Maildir store '%s': Setting Path is incompatible with 'SubFolders Maildir++'\n", store->name );
|
||||
cfg->err = 1;
|
||||
|
|
|
@ -105,6 +105,8 @@ and literal double quotes and backslashes (\fB\\\fR) must be backslash-escaped.
|
|||
All keywords (including those used as arguments) are case-insensitive.
|
||||
Bash-like home directory expansion using the tilde (\fB~\fR) is supported
|
||||
in all options which represent local paths.
|
||||
The reference point for relative local paths is the configuration file's
|
||||
containing directory.
|
||||
There are a few global options, the others apply to particular sections.
|
||||
Sections begin with a section-starting keyword and are terminated by an empty
|
||||
line or end of file.
|
||||
|
@ -205,7 +207,8 @@ yet all messages are archived.
|
|||
(Default: \fBno\fR)
|
||||
.
|
||||
.SS Maildir Stores
|
||||
The reference point for relative \fBPath\fRs is the current working directory.
|
||||
The reference point for relative \fBPath\fRs is the configuration file's
|
||||
containing directory.
|
||||
.P
|
||||
As \fBmbsync\fR needs UIDs, but no standardized UID storage scheme exists for
|
||||
Maildir, \fBmbsync\fR supports two schemes, each with its pros and cons.
|
||||
|
|
|
@ -289,12 +289,12 @@ sub writecfg($)
|
|||
"FSync no
|
||||
|
||||
MaildirStore far
|
||||
Path ./
|
||||
Inbox ./far
|
||||
Path \"\"
|
||||
Inbox far
|
||||
".$$sfx[0]."
|
||||
MaildirStore near
|
||||
Path ./
|
||||
Inbox ./near
|
||||
Path \"\"
|
||||
Inbox near
|
||||
".$$sfx[1]."
|
||||
Channel test
|
||||
Far :far:
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef struct channel_conf {
|
|||
const char *name;
|
||||
store_conf_t *stores[2];
|
||||
const char *boxes[2];
|
||||
char *sync_state;
|
||||
const char *sync_state;
|
||||
string_list_t *patterns;
|
||||
int ops[2];
|
||||
int max_messages; // For near side only.
|
||||
|
|
Loading…
Reference in New Issue
Block a user