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

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