mu: Default to XDG Base Directory Specification
Instead of using ~/.mu, use the XDG Base Directory Specification, typically: ~/.cache/xapian ~/.cache/mu.log ~/.cache/parts ~/.config/bookmarks Update dependencies, documentation.
This commit is contained in:
@ -64,7 +64,6 @@ libmu_la_SOURCES= \
|
||||
mu-bookmarks.h \
|
||||
mu-contacts.cc \
|
||||
mu-contacts.hh \
|
||||
mu-contacts.h \
|
||||
mu-container.c \
|
||||
mu-container.h \
|
||||
mu-date.c \
|
||||
@ -98,7 +97,7 @@ libmu_la_SOURCES= \
|
||||
mu-msg.h \
|
||||
mu-query.cc \
|
||||
mu-query.h \
|
||||
mu-runtime.c \
|
||||
mu-runtime.cc \
|
||||
mu-runtime.h \
|
||||
mu-script.c \
|
||||
mu-script.h \
|
||||
@ -125,7 +124,6 @@ libmu_la_LIBADD= \
|
||||
libmu_la_LDFLAGS= \
|
||||
$(ASAN_LDFLAGS)
|
||||
|
||||
|
||||
EXTRA_DIST= \
|
||||
mu-msg-crypto.c \
|
||||
doxyfile.in
|
||||
|
||||
206
lib/mu-runtime.c
206
lib/mu-runtime.c
@ -1,206 +0,0 @@
|
||||
/* -*- mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
**
|
||||
** Copyright (C) 2010-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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 the
|
||||
** Free Software Foundation; either version 3, or (at your option) any
|
||||
** later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "mu-runtime.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <locale.h> /* for setlocale() */
|
||||
#include <stdio.h> /* for fileno() */
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "mu-msg.h"
|
||||
#include "mu-log.h"
|
||||
#include "mu-util.h"
|
||||
|
||||
#define MU_XAPIAN_DIRNAME "xapian"
|
||||
#define MU_BOOKMARKS_FILENAME "bookmarks"
|
||||
#define MU_CACHE_DIRNAME "cache"
|
||||
#define MU_CONTACTS_FILENAME "contacts"
|
||||
#define MU_LOG_DIRNAME "log"
|
||||
|
||||
|
||||
struct _MuRuntimeData {
|
||||
gchar *_str[MU_RUNTIME_PATH_NUM];
|
||||
gchar *_name; /* e.g., 'mu', 'mug' */
|
||||
};
|
||||
typedef struct _MuRuntimeData MuRuntimeData;
|
||||
|
||||
/* static, global data for this singleton */
|
||||
static gboolean _initialized = FALSE;
|
||||
static MuRuntimeData *_data = NULL;
|
||||
|
||||
static void runtime_free (void);
|
||||
static gboolean init_paths (const char* muhome, MuRuntimeData *data);
|
||||
static const char* runtime_path (MuRuntimePath path);
|
||||
|
||||
|
||||
static gboolean
|
||||
init_log (const char *muhome, const char *name, MuLogOptions opts)
|
||||
{
|
||||
gboolean rv;
|
||||
char *logpath;
|
||||
|
||||
logpath = g_strdup_printf ("%s%c%s%c%s.log",
|
||||
muhome, G_DIR_SEPARATOR,
|
||||
MU_LOG_DIRNAME, G_DIR_SEPARATOR,
|
||||
name);
|
||||
|
||||
rv = mu_log_init (logpath, opts);
|
||||
g_free (logpath);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gboolean
|
||||
mu_runtime_init (const char* muhome_arg, const char *name)
|
||||
{
|
||||
gchar *muhome;
|
||||
|
||||
g_return_val_if_fail (!_initialized, FALSE);
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
if (muhome_arg)
|
||||
muhome = g_strdup (muhome_arg);
|
||||
else
|
||||
muhome = mu_util_guess_mu_homedir ();
|
||||
|
||||
if (!mu_util_create_dir_maybe (muhome, 0700, TRUE)) {
|
||||
g_printerr ("mu: invalid mu homedir specified;"
|
||||
" use --muhome=<dir>\n");
|
||||
runtime_free ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_data = g_new0 (MuRuntimeData, 1);
|
||||
_data->_str[MU_RUNTIME_PATH_MUHOME] = muhome;
|
||||
|
||||
init_paths (muhome, _data);
|
||||
_data->_name = g_strdup (name);
|
||||
|
||||
if (!init_log (muhome, name, MU_LOG_OPTIONS_BACKUP)) {
|
||||
runtime_free ();
|
||||
g_free (muhome);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return _initialized = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
runtime_free (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
mu_log_uninit();
|
||||
|
||||
if (!_data)
|
||||
return;
|
||||
|
||||
for (i = 0; i != MU_RUNTIME_PATH_NUM; ++i)
|
||||
g_free (_data->_str[i]);
|
||||
|
||||
g_free (_data->_name);
|
||||
g_free (_data);
|
||||
}
|
||||
|
||||
void
|
||||
mu_runtime_uninit (void)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
runtime_free ();
|
||||
|
||||
_initialized = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
create_dirs_maybe (MuRuntimeData *data)
|
||||
{
|
||||
if (!mu_util_create_dir_maybe
|
||||
(data->_str[MU_RUNTIME_PATH_CACHE], 0700, TRUE)) {
|
||||
g_warning ("failed to create cache dir");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!mu_util_create_dir_maybe
|
||||
(data->_str[MU_RUNTIME_PATH_LOG], 0700, TRUE)) {
|
||||
g_warning ("failed to create log dir");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
init_paths (const char* muhome, MuRuntimeData *data)
|
||||
{
|
||||
data->_str [MU_RUNTIME_PATH_XAPIANDB] =
|
||||
g_strdup_printf ("%s%c%s", muhome, G_DIR_SEPARATOR,
|
||||
MU_XAPIAN_DIRNAME);
|
||||
|
||||
data->_str [MU_RUNTIME_PATH_BOOKMARKS] =
|
||||
g_strdup_printf ("%s%c%s", muhome, G_DIR_SEPARATOR,
|
||||
MU_BOOKMARKS_FILENAME);
|
||||
|
||||
data->_str [MU_RUNTIME_PATH_CACHE] =
|
||||
g_strdup_printf ("%s%c%s", muhome, G_DIR_SEPARATOR,
|
||||
MU_CACHE_DIRNAME);
|
||||
|
||||
data->_str [MU_RUNTIME_PATH_CONTACTS] =
|
||||
g_strdup_printf ("%s%c%s", data->_str[MU_RUNTIME_PATH_CACHE],
|
||||
G_DIR_SEPARATOR, MU_CONTACTS_FILENAME);
|
||||
|
||||
data->_str [MU_RUNTIME_PATH_LOG] =
|
||||
g_strdup_printf ("%s%c%s", muhome,
|
||||
G_DIR_SEPARATOR, MU_LOG_DIRNAME);
|
||||
|
||||
if (!create_dirs_maybe (data))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* so we can called when _initialized is FALSE still */
|
||||
static const char*
|
||||
runtime_path (MuRuntimePath path)
|
||||
{
|
||||
return _data->_str[path];
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char*
|
||||
mu_runtime_path (MuRuntimePath path)
|
||||
{
|
||||
g_return_val_if_fail (_initialized, NULL);
|
||||
g_return_val_if_fail (path < MU_RUNTIME_PATH_NUM, NULL);
|
||||
|
||||
return runtime_path (path);
|
||||
}
|
||||
115
lib/mu-runtime.cc
Normal file
115
lib/mu-runtime.cc
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
** Copyright (C) 2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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 the
|
||||
** Free Software Foundation; either version 3, or (at your option) any
|
||||
** later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program; if not, write to the Free Software Foundation,
|
||||
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**
|
||||
*/
|
||||
|
||||
#include "mu-runtime.h"
|
||||
#include "mu-util.h"
|
||||
|
||||
#include <locale.h> /* for setlocale() */
|
||||
#include <unordered_map>
|
||||
static std::unordered_map<MuRuntimePath, std::string> RuntimePaths;
|
||||
|
||||
#include "mu-log.h"
|
||||
|
||||
constexpr auto PartsDir = "parts";
|
||||
constexpr auto LogDir = "log";
|
||||
constexpr auto XapianDir = "xapian";
|
||||
constexpr auto Mu = "mu";
|
||||
constexpr auto Bookmarks = "bookmarks";
|
||||
|
||||
static const std::string Sepa{G_DIR_SEPARATOR_S};
|
||||
|
||||
static void
|
||||
init_paths_xdg ()
|
||||
{
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() +
|
||||
Sepa + Mu + Sepa + XapianDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() +
|
||||
Sepa + Mu + Sepa + PartsDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() +
|
||||
Sepa + Mu);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, g_get_user_config_dir() +
|
||||
Sepa + Mu);
|
||||
}
|
||||
|
||||
static void
|
||||
init_paths_muhome (const char *muhome)
|
||||
{
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, muhome + Sepa + PartsDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir);
|
||||
RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, muhome + Sepa + Bookmarks);
|
||||
}
|
||||
|
||||
gboolean
|
||||
mu_runtime_init (const char* muhome, const char *name)
|
||||
{
|
||||
g_return_val_if_fail (RuntimePaths.empty(), FALSE);
|
||||
g_return_val_if_fail (name, FALSE);
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
if (muhome)
|
||||
init_paths_muhome (muhome);
|
||||
else
|
||||
init_paths_xdg();
|
||||
|
||||
for (const auto& d: RuntimePaths ) {
|
||||
char* dir;
|
||||
if (d.first == MU_RUNTIME_PATH_BOOKMARKS) // special case
|
||||
dir = g_path_get_dirname (d.second.c_str());
|
||||
else
|
||||
dir = g_strdup (d.second.c_str());
|
||||
|
||||
auto ok = mu_util_create_dir_maybe (dir, 0700, TRUE);
|
||||
if (!ok) {
|
||||
g_critical ("failed to create %s", dir);
|
||||
g_free (dir);
|
||||
mu_runtime_uninit();
|
||||
return FALSE;
|
||||
}
|
||||
g_free (dir);
|
||||
}
|
||||
|
||||
const auto log_path = RuntimePaths[MU_RUNTIME_PATH_LOGDIR] +
|
||||
Sepa + name + ".log";
|
||||
|
||||
if (!mu_log_init (log_path.c_str(), MU_LOG_OPTIONS_BACKUP)) {
|
||||
mu_runtime_uninit();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
mu_runtime_uninit (void)
|
||||
{
|
||||
RuntimePaths.clear();
|
||||
mu_log_uninit();
|
||||
}
|
||||
|
||||
const char*
|
||||
mu_runtime_path (MuRuntimePath path)
|
||||
{
|
||||
const auto it = RuntimePaths.find (path);
|
||||
if (it == RuntimePaths.end())
|
||||
return NULL;
|
||||
else
|
||||
return it->second.c_str();
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||
**
|
||||
** Copyright (C) 2012-2013 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2012-2019 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** 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 the
|
||||
@ -37,24 +37,6 @@ G_BEGIN_DECLS
|
||||
*/
|
||||
gboolean mu_runtime_init (const char *muhome, const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* initialize the mu runtime system with comand line argument; this
|
||||
* will parse the command line assuming the parameters of the 'mu'
|
||||
* program. Initializes logging and other systems. To uninitialize,
|
||||
* use mu_runtime_uninit
|
||||
*
|
||||
* @param ptr to the param count (typically, argc)
|
||||
* @param ptr to the params (typically, argv)
|
||||
* @param name of the main program, ie. 'mu', 'mug' or
|
||||
* 'procmule'. this influences the name of the e.g. the logfile
|
||||
*
|
||||
* @return TRUE if succeeded, FALSE in case of error
|
||||
*/
|
||||
gboolean mu_runtime_init_from_cmdline (int *pargc, char ***pargv,
|
||||
const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* free all resources
|
||||
*
|
||||
@ -62,17 +44,14 @@ gboolean mu_runtime_init_from_cmdline (int *pargc, char ***pargv,
|
||||
void mu_runtime_uninit (void);
|
||||
|
||||
|
||||
enum _MuRuntimePath {
|
||||
MU_RUNTIME_PATH_MUHOME, /* mu home path */
|
||||
typedef enum {
|
||||
MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */
|
||||
MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */
|
||||
MU_RUNTIME_PATH_CACHE, /* mu cache path */
|
||||
MU_RUNTIME_PATH_LOG, /* mu path for log files */
|
||||
MU_RUNTIME_PATH_CONTACTS, /* mu path to the contacts cache */
|
||||
MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */
|
||||
MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */
|
||||
|
||||
MU_RUNTIME_PATH_NUM
|
||||
};
|
||||
typedef enum _MuRuntimePath MuRuntimePath;
|
||||
} MuRuntimePath;
|
||||
|
||||
/**
|
||||
* get a file system path to some 'special' file or directory
|
||||
|
||||
@ -194,32 +194,6 @@ mu_util_guess_maildir (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
gchar*
|
||||
mu_util_guess_mu_homedir (void)
|
||||
{
|
||||
const char* home;
|
||||
const gchar *hdir1;
|
||||
|
||||
/* first, try MU_HOME */
|
||||
hdir1 = g_getenv ("MU_HOME");
|
||||
|
||||
if (hdir1 && mu_util_check_dir (hdir1, TRUE, FALSE))
|
||||
return g_strdup (hdir1);
|
||||
|
||||
/* then, g_get_home_dir use /etc/passwd, not $HOME; this is
|
||||
* better, as HOME may be wrong when using 'sudo' etc.*/
|
||||
home = g_get_home_dir ();
|
||||
|
||||
if (!home) {
|
||||
MU_WRITE_LOG ("failed to determine homedir");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_strdup_printf ("%s%c%s", home ? home : ".",
|
||||
G_DIR_SEPARATOR, ".mu");
|
||||
}
|
||||
|
||||
gboolean
|
||||
mu_util_create_dir_maybe (const gchar *path, mode_t mode, gboolean nowarn)
|
||||
{
|
||||
|
||||
@ -60,19 +60,6 @@ char* mu_util_dir_expand (const char* path)
|
||||
char* mu_util_guess_maildir (void)
|
||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
* guess the place of the mu homedir; first try $MU_HOME; if it is
|
||||
* unset or non-existant, try ~/.mu. Note, the fallback ~/.mu
|
||||
* directory does not necessarily exist. mu_util_check_dir can be used
|
||||
* to check that
|
||||
*
|
||||
* @return the guessed mu homedir, which needs to be freed with g_free
|
||||
* when no longer needed.
|
||||
*/
|
||||
gchar* mu_util_guess_mu_homedir (void)
|
||||
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
/**
|
||||
* if path exists, check that's a read/writeable dir; otherwise try to
|
||||
* create it (with perms 0700)
|
||||
|
||||
Reference in New Issue
Block a user