PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/mcconfig/paths.c

https://repo.or.cz/zuwinko.git
C | 367 lines | 237 code | 72 blank | 58 comment | 37 complexity | 10f000ebc7d6c8bce2cc4a6f266bfcd1 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. paths to configuration files
  3. Copyright (C) 2010 The Free Software Foundation, Inc.
  4. Written by:
  5. Slava Zanko <slavazanko@gmail.com>, 2010.
  6. This file is part of the Midnight Commander.
  7. The Midnight Commander is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU General Public License as
  9. published by the Free Software Foundation; either version 2 of the
  10. License, or (at your option) any later version.
  11. The Midnight Commander is distributed in the hope that it will be
  12. useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  13. of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18. MA 02110-1301, USA.
  19. */
  20. #include <config.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include "lib/global.h"
  24. #include "lib/mcconfig.h"
  25. #include "lib/fileloc.h"
  26. #include "lib/vfs/mc-vfs/vfs.h"
  27. /*** global variables ****************************************************************************/
  28. /*** file scope macro definitions ****************************************************************/
  29. /*** file scope type declarations ****************************************************************/
  30. /*** file scope variables ************************************************************************/
  31. static gboolean xdg_vars_initialized = FALSE;
  32. static char *xdg_config = NULL;
  33. static char *xdg_cache = NULL;
  34. static char *xdg_data = NULL;
  35. static const char *homedir = NULL;
  36. static gboolean config_dir_present = FALSE;
  37. static const struct
  38. {
  39. const char *old_filename;
  40. char **new_basedir;
  41. const char *new_filename;
  42. } mc_config_migrate_rules[] =
  43. {
  44. /* *INDENT-OFF* */
  45. /* config */
  46. { "ini", &xdg_config, MC_CONFIG_FILE},
  47. { "filehighlight.ini", &xdg_config, MC_FHL_INI_FILE},
  48. { "hotlist", &xdg_config, MC_HOTLIST_FILE},
  49. { "mc.keymap", &xdg_config, GLOBAL_KEYMAP_FILE},
  50. /* data */
  51. { "skins", &xdg_data, MC_SKINS_SUBDIR},
  52. { "fish", &xdg_data, FISH_PREFIX},
  53. { "bindings", &xdg_data, MC_FILEBIND_FILE},
  54. { "menu", &xdg_data, MC_USERMENU_FILE},
  55. { "bashrc", &xdg_data, "bashrc"},
  56. { "inputrc", &xdg_data, "inputrc"},
  57. { "extfs.d", &xdg_data, MC_EXTFS_DIR},
  58. { "cedit" PATH_SEP_STR "Syntax", &xdg_data, EDIT_SYNTAX_FILE},
  59. { "cedit" PATH_SEP_STR "menu", &xdg_data, EDIT_HOME_MENU},
  60. { "cedit" PATH_SEP_STR "edit.indent.rc", &xdg_data, EDIT_DIR PATH_SEP_STR "edit.indent.rc"},
  61. { "cedit" PATH_SEP_STR "edit.spell.rc", &xdg_data, EDIT_DIR PATH_SEP_STR "edit.spell.rc"},
  62. /* cache */
  63. { "history", &xdg_cache, MC_HISTORY_FILE},
  64. { "panels.ini", &xdg_cache, MC_PANELS_FILE},
  65. { "log", &xdg_cache, "mc.log"},
  66. { "filepos", &xdg_cache, MC_FILEPOS_FILE},
  67. { "Tree", &xdg_cache, MC_TREESTORE_FILE},
  68. { "cedit" PATH_SEP_STR "cooledit.clip", &xdg_cache, EDIT_CLIP_FILE},
  69. { "cedit" PATH_SEP_STR "cooledit.temp", &xdg_cache, EDIT_TEMP_FILE},
  70. { "cedit" PATH_SEP_STR "cooledit.block", &xdg_cache, EDIT_BLOCK_FILE},
  71. {NULL, NULL, NULL}
  72. /* *INDENT-ON* */
  73. };
  74. /*** file scope functions *********************************************************************** */
  75. /* --------------------------------------------------------------------------------------------- */
  76. static void
  77. mc_config_mkdir (const char *directory_name, GError ** error)
  78. {
  79. if ((!g_file_test (directory_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) &&
  80. (g_mkdir_with_parents (directory_name, 0700) != 0))
  81. {
  82. g_propagate_error (error,
  83. g_error_new (MC_ERROR, 0, _("Cannot create %s directory"),
  84. directory_name));
  85. }
  86. }
  87. /* --------------------------------------------------------------------------------------------- */
  88. static char *
  89. mc_config_init_one_config_path (const char *path_base, const char *subdir, GError ** error)
  90. {
  91. char *full_path;
  92. full_path = g_build_filename (path_base, subdir, NULL);
  93. if (g_file_test (full_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
  94. config_dir_present = TRUE;
  95. mc_config_mkdir (full_path, error);
  96. if (error != NULL && *error != NULL)
  97. {
  98. g_free (full_path);
  99. full_path = NULL;
  100. }
  101. return full_path;
  102. }
  103. /* --------------------------------------------------------------------------------------------- */
  104. static char *
  105. mc_config_get_deprecated_path (void)
  106. {
  107. return g_build_filename (mc_config_get_home_dir (), "." MC_USERCONF_DIR, NULL);
  108. }
  109. /* --------------------------------------------------------------------------------------------- */
  110. static void
  111. mc_config_copy (const char *old_name, const char *new_name, GError ** error)
  112. {
  113. if (error != NULL && *error != NULL)
  114. return;
  115. if (g_file_test (old_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
  116. {
  117. char *contents = NULL;
  118. size_t length;
  119. if (g_file_get_contents (old_name, &contents, &length, error))
  120. g_file_set_contents (new_name, contents, length, error);
  121. g_free (contents);
  122. return;
  123. }
  124. if (g_file_test (old_name, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
  125. {
  126. GDir *dir;
  127. const char *dir_name;
  128. dir = g_dir_open (old_name, 0, error);
  129. if (dir == NULL)
  130. return;
  131. if (!g_mkdir_with_parents (new_name, 0700))
  132. {
  133. g_dir_close (dir);
  134. g_propagate_error (error,
  135. g_error_new (MC_ERROR, 0,
  136. _
  137. ("An error occured while migrating user settings: %s"),
  138. g_strerror (errno)));
  139. return;
  140. }
  141. while ((dir_name = g_dir_read_name (dir)) != NULL)
  142. {
  143. char *old_name2, *new_name2;
  144. old_name2 = g_build_filename (old_name, dir_name, NULL);
  145. new_name2 = g_build_filename (new_name, dir_name, NULL);
  146. mc_config_copy (old_name2, new_name2, error);
  147. g_free (new_name2);
  148. g_free (old_name2);
  149. }
  150. }
  151. if (rename (old_name, new_name) != 0)
  152. {
  153. g_propagate_error (error,
  154. g_error_new (MC_ERROR, 0,
  155. _
  156. ("An error occured while migrating user settings: %s"),
  157. g_strerror (errno)));
  158. }
  159. }
  160. /* --------------------------------------------------------------------------------------------- */
  161. /*** public functions ****************************************************************************/
  162. /* --------------------------------------------------------------------------------------------- */
  163. void
  164. mc_config_init_config_paths (GError ** error)
  165. {
  166. char *u_config_dir = (char *) g_get_user_config_dir ();
  167. char *u_data_dir = (char *) g_get_user_data_dir ();
  168. char *u_cache_dir = (char *) g_get_user_cache_dir ();
  169. if (xdg_vars_initialized)
  170. return;
  171. u_config_dir = (u_config_dir == NULL)
  172. ? g_build_filename (mc_config_get_home_dir (), ".config", NULL) : g_strdup (u_config_dir);
  173. u_cache_dir = (u_cache_dir == NULL)
  174. ? g_build_filename (mc_config_get_home_dir (), ".cache", NULL) : g_strdup (u_cache_dir);
  175. u_data_dir = (u_data_dir == NULL)
  176. ? g_build_filename (mc_config_get_home_dir (), ".local", "share", NULL)
  177. : g_strdup (u_data_dir);
  178. xdg_config = mc_config_init_one_config_path (u_config_dir, MC_USERCONF_DIR, error);
  179. xdg_cache = mc_config_init_one_config_path (u_cache_dir, MC_USERCONF_DIR, error);
  180. xdg_data = mc_config_init_one_config_path (u_data_dir, MC_USERCONF_DIR, error);
  181. g_free (u_data_dir);
  182. g_free (u_cache_dir);
  183. g_free (u_config_dir);
  184. xdg_vars_initialized = TRUE;
  185. }
  186. /* --------------------------------------------------------------------------------------------- */
  187. void
  188. mc_config_deinit_config_paths (void)
  189. {
  190. if (!xdg_vars_initialized)
  191. return;
  192. g_free (xdg_config);
  193. g_free (xdg_cache);
  194. g_free (xdg_data);
  195. xdg_vars_initialized = FALSE;
  196. }
  197. /* --------------------------------------------------------------------------------------------- */
  198. const char *
  199. mc_config_get_data_path (void)
  200. {
  201. if (!xdg_vars_initialized)
  202. mc_config_init_config_paths (NULL);
  203. return (const char *) xdg_data;
  204. }
  205. /* --------------------------------------------------------------------------------------------- */
  206. const char *
  207. mc_config_get_cache_path (void)
  208. {
  209. if (!xdg_vars_initialized)
  210. mc_config_init_config_paths (NULL);
  211. return (const char *) xdg_cache;
  212. }
  213. /* --------------------------------------------------------------------------------------------- */
  214. const char *
  215. mc_config_get_home_dir (void)
  216. {
  217. if (homedir == NULL)
  218. {
  219. homedir = g_getenv ("HOME");
  220. if (homedir == NULL)
  221. homedir = g_get_home_dir ();
  222. }
  223. return homedir;
  224. }
  225. /* --------------------------------------------------------------------------------------------- */
  226. const char *
  227. mc_config_get_path (void)
  228. {
  229. if (!xdg_vars_initialized)
  230. mc_config_init_config_paths (NULL);
  231. return (const char *) xdg_config;
  232. }
  233. /* --------------------------------------------------------------------------------------------- */
  234. void
  235. mc_config_migrate_from_old_place (GError ** error)
  236. {
  237. char *old_dir, *tmp_dir_name;
  238. size_t rule_index;
  239. old_dir = mc_config_get_deprecated_path ();
  240. tmp_dir_name = mc_config_init_one_config_path (xdg_config, EDIT_DIR, error);
  241. g_free (tmp_dir_name);
  242. tmp_dir_name = mc_config_init_one_config_path (xdg_cache, EDIT_DIR, error);
  243. g_free (tmp_dir_name);
  244. tmp_dir_name = mc_config_init_one_config_path (xdg_data, EDIT_DIR, error);
  245. g_free (tmp_dir_name);
  246. for (rule_index = 0; mc_config_migrate_rules[rule_index].old_filename != NULL; rule_index++)
  247. {
  248. char *old_name, *new_name;
  249. old_name =
  250. g_build_filename (old_dir, mc_config_migrate_rules[rule_index].old_filename, NULL);
  251. if (!g_file_test (old_name, G_FILE_TEST_EXISTS))
  252. {
  253. g_free (old_name);
  254. continue;
  255. }
  256. new_name = g_build_filename (*mc_config_migrate_rules[rule_index].new_basedir,
  257. mc_config_migrate_rules[rule_index].new_filename, NULL);
  258. mc_config_copy (old_name, new_name, error);
  259. g_free (new_name);
  260. g_free (old_name);
  261. }
  262. /*
  263. {
  264. char *old_dir2;
  265. old_dir2 = g_strconcat (old_dir, "~", NULL);
  266. rename (old_dir, old_dir2);
  267. g_free (old_dir2);
  268. }
  269. */
  270. g_propagate_error (error,
  271. g_error_new (MC_ERROR, 0,
  272. _
  273. ("Your old settings were migrated from %s\n"
  274. "to Freedesktop recommended dirs.\n"
  275. "To get more info, please visit\n"
  276. "http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html"),
  277. old_dir));
  278. g_free (old_dir);
  279. }
  280. /* --------------------------------------------------------------------------------------------- */
  281. gboolean
  282. mc_config_deprecated_dir_present (void)
  283. {
  284. char *old_dir = mc_config_get_deprecated_path ();
  285. gboolean is_present = g_file_test (old_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR);
  286. g_free (old_dir);
  287. return is_present && !config_dir_present;
  288. }
  289. /* --------------------------------------------------------------------------------------------- */