root/lib/mcconfig/paths.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. mc_config_mkdir
  2. mc_config_init_one_config_path
  3. mc_config_init_config_paths
  4. mc_config_deinit_config_paths
  5. mc_config_get_data_path
  6. mc_config_get_cache_path
  7. mc_config_get_home_dir
  8. mc_config_get_path
  9. mc_config_get_full_path
  10. mc_config_get_full_vpath

   1 /*
   2    paths to configuration files
   3 
   4    Copyright (C) 2010-2022
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Slava Zanko <slavazanko@gmail.com>, 2010.
   9 
  10    This file is part of the Midnight Commander.
  11 
  12    The Midnight Commander is free software: you can redistribute it
  13    and/or modify it under the terms of the GNU General Public License as
  14    published by the Free Software Foundation, either version 3 of the License,
  15    or (at your option) any later version.
  16 
  17    The Midnight Commander is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24  */
  25 
  26 #include <config.h>
  27 
  28 #include <stdio.h>
  29 #include <stdlib.h>
  30 #include <errno.h>
  31 
  32 #include "lib/global.h"
  33 #include "lib/fileloc.h"
  34 #include "lib/vfs/vfs.h"
  35 #include "lib/util.h"           /* unix_error_string() */
  36 
  37 #include "lib/mcconfig.h"
  38 
  39 /*** global variables ****************************************************************************/
  40 
  41 /*** file scope macro definitions ****************************************************************/
  42 
  43 /*** file scope type declarations ****************************************************************/
  44 
  45 /*** file scope variables ************************************************************************/
  46 
  47 static gboolean xdg_vars_initialized = FALSE;
  48 static char *mc_config_str = NULL;
  49 static char *mc_cache_str = NULL;
  50 static char *mc_data_str = NULL;
  51 
  52 static gboolean config_dir_present = FALSE;
  53 
  54 static const struct
  55 {
  56     char **basedir;
  57     const char *filename;
  58 } mc_config_files_reference[] =
  59 {
  60     /* *INDENT-OFF* */
  61     /* config */
  62     { &mc_config_str, MC_CONFIG_FILE },
  63     { &mc_config_str, MC_FHL_INI_FILE },
  64     { &mc_config_str, MC_HOTLIST_FILE },
  65     { &mc_config_str, GLOBAL_KEYMAP_FILE },
  66     { &mc_config_str, MC_USERMENU_FILE },
  67     { &mc_config_str, EDIT_HOME_SYNTAX_FILE },
  68     { &mc_config_str, EDIT_HOME_MENU },
  69     { &mc_config_str, MC_PANELS_FILE },
  70 
  71     /* User should move this file with applying some changes in file */
  72     { &mc_config_str, MC_EXT_FILE },
  73     { &mc_config_str, MC_EXT_OLD_FILE },
  74 
  75     /* data */
  76     { &mc_data_str, MC_SKINS_DIR },
  77     { &mc_data_str, FISH_PREFIX },
  78     { &mc_data_str, MC_ASHRC_FILE },
  79     { &mc_data_str, MC_BASHRC_FILE },
  80     { &mc_data_str, MC_INPUTRC_FILE },
  81     { &mc_data_str, MC_ZSHRC_FILE },
  82     { &mc_data_str, MC_EXTFS_DIR },
  83     { &mc_data_str, MC_HISTORY_FILE },
  84     { &mc_data_str, MC_FILEPOS_FILE },
  85     { &mc_data_str, EDIT_HOME_CLIP_FILE },
  86     { &mc_data_str, MC_MACRO_FILE },
  87 
  88     /* cache */
  89     { &mc_cache_str, "mc.log" },
  90     { &mc_cache_str, MC_TREESTORE_FILE },
  91     { &mc_cache_str, EDIT_HOME_TEMP_FILE },
  92     { &mc_cache_str, EDIT_HOME_BLOCK_FILE },
  93 
  94     { NULL, NULL }
  95     /* *INDENT-ON* */
  96 };
  97 
  98 /* --------------------------------------------------------------------------------------------- */
  99 /*** file scope functions *********************************************************************** */
 100 /* --------------------------------------------------------------------------------------------- */
 101 
 102 static void
 103 mc_config_mkdir (const char *directory_name, GError ** mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 104 {
 105     mc_return_if_error (mcerror);
 106 
 107     if ((!g_file_test (directory_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) &&
 108         (g_mkdir_with_parents (directory_name, 0700) != 0))
 109         mc_propagate_error (mcerror, 0, _("Cannot create %s directory"), directory_name);
 110 }
 111 
 112 /* --------------------------------------------------------------------------------------------- */
 113 
 114 static char *
 115 mc_config_init_one_config_path (const char *path_base, const char *subdir, GError ** mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 116 {
 117     char *full_path;
 118 
 119     mc_return_val_if_error (mcerror, FALSE);
 120 
 121     full_path = g_build_filename (path_base, subdir, (char *) NULL);
 122 
 123     if (g_file_test (full_path, G_FILE_TEST_EXISTS))
 124     {
 125         if (g_file_test (full_path, G_FILE_TEST_IS_DIR))
 126             config_dir_present = TRUE;
 127         else
 128         {
 129             fprintf (stderr, "%s %s\n", _("FATAL: not a directory:"), full_path);
 130             exit (EXIT_FAILURE);
 131         }
 132     }
 133 
 134     mc_config_mkdir (full_path, mcerror);
 135     if (mcerror != NULL && *mcerror != NULL)
 136         MC_PTR_FREE (full_path);
 137 
 138     return full_path;
 139 }
 140 
 141 /* --------------------------------------------------------------------------------------------- */
 142 /*** public functions ****************************************************************************/
 143 /* --------------------------------------------------------------------------------------------- */
 144 
 145 void
 146 mc_config_init_config_paths (GError ** mcerror)
     /* [previous][next][first][last][top][bottom][index][help]  */
 147 {
 148     const char *profile_root;
 149     char *dir;
 150 
 151     mc_return_if_error (mcerror);
 152 
 153     if (xdg_vars_initialized)
 154         return;
 155 
 156     profile_root = mc_get_profile_root ();
 157 
 158     if (strcmp (profile_root, mc_config_get_home_dir ()) != 0)
 159     {
 160         /*
 161          * The user overrode the default profile root.
 162          *
 163          * In this case we can't use GLib's g_get_user_{config,cache,data}_dir()
 164          * as these functions use the user's home dir as the root.
 165          */
 166 
 167         dir = g_build_filename (profile_root, ".config", (char *) NULL);
 168         mc_config_str = mc_config_init_one_config_path (dir, MC_USERCONF_DIR, mcerror);
 169         g_free (dir);
 170 
 171         dir = g_build_filename (profile_root, ".cache", (char *) NULL);
 172         mc_cache_str = mc_config_init_one_config_path (dir, MC_USERCONF_DIR, mcerror);
 173         g_free (dir);
 174 
 175         dir = g_build_filename (profile_root, ".local", "share", (char *) NULL);
 176         mc_data_str = mc_config_init_one_config_path (dir, MC_USERCONF_DIR, mcerror);
 177         g_free (dir);
 178     }
 179     else
 180     {
 181         mc_config_str =
 182             mc_config_init_one_config_path (g_get_user_config_dir (), MC_USERCONF_DIR, mcerror);
 183         mc_cache_str =
 184             mc_config_init_one_config_path (g_get_user_cache_dir (), MC_USERCONF_DIR, mcerror);
 185         mc_data_str =
 186             mc_config_init_one_config_path (g_get_user_data_dir (), MC_USERCONF_DIR, mcerror);
 187     }
 188 
 189     xdg_vars_initialized = TRUE;
 190 }
 191 
 192 /* --------------------------------------------------------------------------------------------- */
 193 
 194 void
 195 mc_config_deinit_config_paths (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 196 {
 197     if (!xdg_vars_initialized)
 198         return;
 199 
 200     g_free (mc_config_str);
 201     g_free (mc_cache_str);
 202     g_free (mc_data_str);
 203 
 204     g_free (mc_global.share_data_dir);
 205     g_free (mc_global.sysconfig_dir);
 206 
 207     xdg_vars_initialized = FALSE;
 208 }
 209 
 210 /* --------------------------------------------------------------------------------------------- */
 211 
 212 const char *
 213 mc_config_get_data_path (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 214 {
 215     if (!xdg_vars_initialized)
 216         mc_config_init_config_paths (NULL);
 217 
 218     return (const char *) mc_data_str;
 219 }
 220 
 221 /* --------------------------------------------------------------------------------------------- */
 222 
 223 const char *
 224 mc_config_get_cache_path (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 225 {
 226     if (!xdg_vars_initialized)
 227         mc_config_init_config_paths (NULL);
 228 
 229     return (const char *) mc_cache_str;
 230 }
 231 
 232 /* --------------------------------------------------------------------------------------------- */
 233 
 234 const char *
 235 mc_config_get_home_dir (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 236 {
 237     static const char *homedir = NULL;
 238 
 239     if (homedir == NULL)
 240     {
 241         /* Prior to GLib 2.36, g_get_home_dir() ignores $HOME, which is why
 242          * we read it ourselves. As that function's documentation explains,
 243          * using $HOME is good for compatibility with other programs and
 244          * for running from test frameworks. */
 245         homedir = g_getenv ("HOME");
 246         if (homedir == NULL || *homedir == '\0')
 247             homedir = g_get_home_dir ();
 248     }
 249 
 250     return homedir;
 251 }
 252 
 253 /* --------------------------------------------------------------------------------------------- */
 254 
 255 const char *
 256 mc_config_get_path (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 257 {
 258     if (!xdg_vars_initialized)
 259         mc_config_init_config_paths (NULL);
 260 
 261     return (const char *) mc_config_str;
 262 }
 263 
 264 /* --------------------------------------------------------------------------------------------- */
 265 /**
 266  * Get full path to config file by short name.
 267  *
 268  * @param config_name short name
 269  * @return full path to config file
 270  */
 271 
 272 char *
 273 mc_config_get_full_path (const char *config_name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 274 {
 275     size_t rule_index;
 276 
 277     if (config_name == NULL)
 278         return NULL;
 279 
 280     if (!xdg_vars_initialized)
 281         mc_config_init_config_paths (NULL);
 282 
 283     for (rule_index = 0; mc_config_files_reference[rule_index].filename != NULL; rule_index++)
 284         if (strcmp (config_name, mc_config_files_reference[rule_index].filename) == 0)
 285             return g_build_filename (*mc_config_files_reference[rule_index].basedir,
 286                                      mc_config_files_reference[rule_index].filename, (char *) NULL);
 287 
 288     return NULL;
 289 }
 290 
 291 /* --------------------------------------------------------------------------------------------- */
 292 /**
 293  * Get full path to config file by short name.
 294  *
 295  * @param config_name short name
 296  * @return object with full path to config file
 297  */
 298 
 299 vfs_path_t *
 300 mc_config_get_full_vpath (const char *config_name)
     /* [previous][next][first][last][top][bottom][index][help]  */
 301 {
 302     vfs_path_t *ret_vpath;
 303     char *str_path;
 304 
 305     str_path = mc_config_get_full_path (config_name);
 306 
 307     ret_vpath = vfs_path_from_str (str_path);
 308     g_free (str_path);
 309 
 310     return ret_vpath;
 311 }
 312 
 313 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */