1 /** \file archdep_user_config_path.c
2 * \brief Retrieve path to the user's configuration directory
3 * \author Bas Wassink <b.wassink@ziggo.nl>
4 *
5 * Get path to user's VICE configuration directory, this is where the vice
6 * files like vicerc/vice.ini, vice.log, autostart-$emu.d64 will be.
7 *
8 * OS support:
9 * - Linux
10 * - Windows
11 * - MacOS
12 * - BeOS/Haiku (untested)
13 * - AmigaOS (untested)
14 * - OS/2 (untested)
15 *
16 */
17
18 /*
19 * This file is part of VICE, the Versatile Commodore Emulator.
20 * See README for copyright notice.
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
35 * 02111-1307 USA.
36 *
37 */
38
39 #include "vice.h"
40
41 #include <stddef.h>
42
43 #include "archdep_defs.h"
44
45 #include "archdep.h"
46
47 #ifdef ARCHDEP_OS_WINDOWS
48 # include "windows.h"
49 # include "shlobj.h"
50 #endif
51
52 #ifdef HAVE_DEBUG_GTK3UI
53 # include "debug_gtk3.h"
54 #endif
55
56 #include <stddef.h>
57
58 #include "lib.h"
59
60 #if !defined(ARCHDEP_OS_UNIX) && !defined(ARCHDEP_OS_WINDOWS) \
61 && !(defined(ARCHDEP_OS_BEOS))
62 # include "archdep_boot_path.h"
63 #endif
64
65 #ifdef ARCHDEP_OS_BEOS
66 # include "archdep_home_path.h"
67 #endif
68
69 #include "archdep_join_paths.h"
70 #include "archdep_xdg.h"
71
72 #include "archdep_user_config_path.h"
73
74
75 /** \brief User's VICE configuration directory reference
76 *
77 * Allocated once in the first call to archdep_user_config_path(), should be
78 * freed on emulator exit with archdep_user_config_path_free()
79 */
80 static char *user_config_dir = NULL;
81
82
83 /** \brief Get path to the user's VICE configuration directory
84 *
85 * On systems supporting home directories this will return a directory inside
86 * the home directory, depending on OS:
87 *
88 * - Windows: $HOME\\AppData\\Roaming\\vice
89 * - Unix: $HOME/.config/vice (rather: XDG_CONFIG_HOME)
90 * - BeOS: $HOME/config/settings/vice
91 * (Haiku sets $XDG_CONFIG_HOME to '/boot/home/config/settings')
92 *
93 * On other systems the path to the executable is returned.
94 *
95 * Free memory used on emulator exit with archdep_user_config_path_free()
96 *
97 * \return path to VICE config directory
98 */
archdep_user_config_path(void)99 char *archdep_user_config_path(void)
100 {
101 #ifdef ARCHDEP_OS_WINDOWS
102 TCHAR szPath[MAX_PATH];
103 #endif
104 /* don't recalculate path if it's already known */
105 if (user_config_dir != NULL) {
106 return user_config_dir;
107 }
108
109 #if defined(ARCHDEP_OS_UNIX) || defined(ARCHDEP_OS_HAIKU)
110 char *xdg_config = archdep_xdg_config_home();
111 user_config_dir = archdep_join_paths(xdg_config, "vice", NULL);
112 lib_free(xdg_config);
113
114 #elif defined(ARCHDEP_OS_WINDOWS)
115 /*
116 * Use WinAPI to get %APPDATA% directory, hopefully more reliable than
117 * hardcoding 'AppData/Roaming'. We can't use SHGetKnownFolderPath() here
118 * since SDL should be able to run on Windows XP and perhaps even lower.
119 */
120 if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_APPDATA, NULL, 0, szPath))) {
121 user_config_dir = archdep_join_paths(szPath, "vice", NULL);
122 #ifdef HAVE_DEBUG_GTK3UI
123 debug_gtk3("Got AppData via SHGetFolderPathA(): '%s'.", user_config_dir);
124 #endif
125 } else {
126 #ifdef HAVE_DEBUG_GTK3UI
127 debug_gtk3("Failed to get AppData via SHGetFolderPathA().");
128 #endif
129 user_config_dir = NULL;
130 }
131 #else
132 user_config_dir = lib_strdup(archdep_boot_path());
133 #endif
134 return user_config_dir;
135 }
136
137
138 /** \brief Free memory used by the user's config path
139 */
archdep_user_config_path_free(void)140 void archdep_user_config_path_free(void)
141 {
142 if (user_config_dir != NULL) {
143 lib_free(user_config_dir);
144 user_config_dir = NULL;
145 }
146 }
147