This is a first attempt at supporting $XDG_DATA_HOME/mbsync as a
SyncState location in addition to ~/.mbsync. The behavior changed by
this patch is as follows:

To determine the SyncState directory, if not set explicitly
 - expand $XDG_DATA_HOME from the environment, falling back to
   $HOME/.local/share/ as per the specification
 - check whether XDG_DATA_HOME/mbsync exists and is a directory, and if not
 - fall back to ~/.mbsync

The patch also extends the bevior of mbsync after a path to the
syncstate directory has been determined (regardless of where the path
came from) by adding a check for whether the chosen path is invalid.

If the path is found to be invalid, either by an unexpected failure to
access the directory at the given path, or by the object located in the
file system an the given path not being a directory, an error message is
presented to the user.

Best,
-A


-- 

------------------------------------------------------------------------------
my GPG Public Key:                 https://files.grapentin.org/.gpg/public.key
------------------------------------------------------------------------------
From 0b90d132b510304adc4a6944ab38e42e3dc5e536 Mon Sep 17 00:00:00 2001
From: Andreas Grapentin <andr...@grapentin.org>
Date: Mon, 30 Nov 2020 21:46:08 +0100
Subject: [PATCH] src/config.c: added support for SyncState directories within
 XDG_DATA_HOME

---
 NEWS         |  3 +++
 src/config.c | 36 +++++++++++++++++++++++++++++-------
 src/mbsync.1 |  5 +++--
 3 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/NEWS b/NEWS
index 37c94a2..247343f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
 [1.4.0]
 
+Added support for a second syncstate directory location in
+XDG_DATA_HOME/mbsync/
+
 Added support for a second user config file location in
 XDG_CONFIG_HOME/mbsyncrc.
 
diff --git a/src/config.c b/src/config.c
index 345842a..ebd6b29 100644
--- a/src/config.c
+++ b/src/config.c
@@ -34,6 +34,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <errno.h>
+#include <sys/stat.h>
 
 static store_conf_t *stores;
 
@@ -328,20 +329,21 @@ load_config( const char *where )
        char *arg, *p;
        uint len, max_size;
        int cops, gcops, glob_ok, fn, i;
-       char path[_POSIX_PATH_MAX];
+       char config_path[_POSIX_PATH_MAX];
+       char data_path[_POSIX_PATH_MAX];
        char buf[1024];
 
        if (!where) {
                const char *config_home = getenv("XDG_CONFIG_HOME");
                if (config_home)
-                       nfsnprintf( path, sizeof(path), "%s/" EXE "rc", 
config_home );
+                       nfsnprintf( config_path, sizeof(config_path), "%s/" EXE 
"rc", config_home );
                else
-                       nfsnprintf( path, sizeof(path), "%s/.config/" EXE "rc", 
Home );
-               cfile.file = path;
+                       nfsnprintf( config_path, sizeof(config_path), 
"%s/.config/" EXE "rc", Home );
+               cfile.file = config_path;
                cfile.fp = fopen( cfile.file, "r" );
 
                if (!cfile.fp && errno == ENOENT) {
-                       nfsnprintf( path, sizeof(path), "%s/." EXE "rc", Home );
+                       nfsnprintf( config_path, sizeof(config_path), "%s/." 
EXE "rc", Home );
                        cfile.fp = fopen( cfile.file, "r" );
                }
        } else {
@@ -544,7 +546,27 @@ load_config( const char *where )
        if (cfile.ms_warn)
                warn( "Notice: Master/Slave are deprecated; use Far/Near 
instead.\n" );
        cfile.err |= merge_ops( gcops, global_conf.ops );
-       if (!global_conf.sync_state)
-               global_conf.sync_state = expand_strdup( "~/." EXE "/" );
+       struct stat s;
+       int stat_res;
+       if (!global_conf.sync_state) {
+               const char *data_home = getenv("XDG_DATA_HOME");
+               if (data_home)
+                       nfsnprintf( data_path, sizeof(data_path), "%s/" EXE 
"/", data_home );
+               else
+                       nfsnprintf( data_path, sizeof(data_path), 
"%s/.local/share/" EXE "/", Home );
+               global_conf.sync_state = data_path;
+               stat_res = stat( global_conf.sync_state, &s );
+
+               if ((stat_res == -1 && errno == ENOENT) || !S_ISDIR(s.st_mode)) 
{
+                       nfsnprintf( data_path, sizeof(data_path), "%s/." EXE 
"/", Home );
+                       stat_res = stat( global_conf.sync_state, &s );
+               }
+       } else {
+               stat_res = stat( global_conf.sync_state, &s );
+       }
+       if ((stat_res == -1 && errno != ENOENT) || !S_ISDIR(s.st_mode)) {
+               sys_error( "Cannot open user syncstate directory '%s'", 
global_conf.sync_state );
+               return 1;
+       }
        return cfile.err;
 }
diff --git a/src/mbsync.1 b/src/mbsync.1
index 1ae3c89..9f75216 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -685,7 +685,7 @@ the appended string is made up according to the pattern
 \fB:\fIfar-store\fB:\fIfar-box\fB_:\fInear-store\fB:\fInear-box\fR
 (see also \fBFieldDelimiter\fR below).
 .br
-(Global default: \fI~/.mbsync/\fR).
+(Global default: \fI$XDG_DATA_HOME/mbsync\fR, or, if missing, 
\fI~/.mbsync/\fR).
 .
 .SS Groups
 .TP
@@ -808,8 +808,9 @@ There is no risk as long as the IMAP mailbox is accessed by 
only one client
 .B ~/.mbsyncrc
 Default configuration files
 .TP
+.B $XDG_DATA_HOME/mbsync
 .B ~/.mbsync/
-Directory containing synchronization state files
+Directories containing synchronization state files
 .
 .SH SEE ALSO
 mdconvert(1), mutt(1), maildir(5)
-- 
2.29.2

Attachment: signature.asc
Description: PGP signature

_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to