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