/src/wxwidgets/src/unix/stdpaths.cpp
Line | Count | Source |
1 | | /////////////////////////////////////////////////////////////////////////////// |
2 | | // Name: src/unix/stdpaths.cpp |
3 | | // Purpose: wxStandardPaths implementation for Unix & OpenVMS systems |
4 | | // Author: Vadim Zeitlin |
5 | | // Created: 2004-10-19 |
6 | | // Copyright: (c) 2004 Vadim Zeitlin <vadim@wxwidgets.org> |
7 | | // Licence: wxWindows licence |
8 | | /////////////////////////////////////////////////////////////////////////////// |
9 | | |
10 | | // ============================================================================ |
11 | | // declarations |
12 | | // ============================================================================ |
13 | | |
14 | | // ---------------------------------------------------------------------------- |
15 | | // headers |
16 | | // ---------------------------------------------------------------------------- |
17 | | |
18 | | // for compilers that support precompilation, includes "wx.h". |
19 | | #include "wx/wxprec.h" |
20 | | |
21 | | |
22 | | #if wxUSE_STDPATHS |
23 | | |
24 | | #include "wx/stdpaths.h" |
25 | | |
26 | | #ifndef WX_PRECOMP |
27 | | #include "wx/app.h" |
28 | | #include "wx/wxcrt.h" |
29 | | #include "wx/utils.h" |
30 | | #endif //WX_PRECOMP |
31 | | |
32 | | #include "wx/filename.h" |
33 | | #include "wx/log.h" |
34 | | #include "wx/textfile.h" |
35 | | |
36 | | #if defined( __LINUX__ ) || defined( __VMS ) |
37 | | #include <unistd.h> |
38 | | #endif |
39 | | |
40 | | // ============================================================================ |
41 | | // common VMS/Unix part of wxStandardPaths implementation |
42 | | // ============================================================================ |
43 | | |
44 | | void wxStandardPaths::SetInstallPrefix(const wxString& prefix) |
45 | 0 | { |
46 | 0 | m_prefix = prefix; |
47 | 0 | } |
48 | | |
49 | | // Helper function returning the value of XDG_CONFIG_HOME environment variable |
50 | | // or its default value if it is not defined. |
51 | | static wxString GetXDGConfigHome() |
52 | 0 | { |
53 | 0 | wxString dir; |
54 | 0 | if ( !wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() ) |
55 | 0 | dir = wxFileName::GetHomeDir() + wxS("/.config"); |
56 | 0 | return dir; |
57 | 0 | } |
58 | | |
59 | | wxString wxStandardPaths::GetUserConfigDir() const |
60 | 0 | { |
61 | 0 | wxString dir; |
62 | |
|
63 | 0 | switch ( GetFileLayout() ) |
64 | 0 | { |
65 | 0 | case FileLayout_Classic: |
66 | 0 | dir = wxFileName::GetHomeDir(); |
67 | 0 | break; |
68 | | |
69 | 0 | case FileLayout_XDG: |
70 | 0 | dir = GetXDGConfigHome(); |
71 | 0 | break; |
72 | 0 | } |
73 | | |
74 | 0 | wxASSERT_MSG( !dir.empty(), wxS("unsupported file layout") ); |
75 | |
|
76 | 0 | return dir; |
77 | 0 | } |
78 | | |
79 | | |
80 | | // ============================================================================ |
81 | | // wxStandardPaths implementation for VMS |
82 | | // ============================================================================ |
83 | | |
84 | | #ifdef __VMS |
85 | | |
86 | | wxString wxStandardPaths::GetInstallPrefix() const |
87 | | { |
88 | | if ( m_prefix.empty() ) |
89 | | { |
90 | | const_cast<wxStandardPaths *>(this)->m_prefix = wxT("/sys$system"); |
91 | | } |
92 | | |
93 | | return m_prefix; |
94 | | } |
95 | | |
96 | | wxString wxStandardPaths::GetConfigDir() const |
97 | | { |
98 | | return wxT("/sys$manager"); |
99 | | } |
100 | | |
101 | | wxString wxStandardPaths::GetDataDir() const |
102 | | { |
103 | | return AppendAppInfo(GetInstallPrefix() + wxT("/sys$share")); |
104 | | } |
105 | | |
106 | | wxString wxStandardPaths::GetLocalDataDir() const |
107 | | { |
108 | | return AppendAppInfo(wxT("/sys$manager")); |
109 | | } |
110 | | |
111 | | wxString wxStandardPaths::GetUserDataDir() const |
112 | | { |
113 | | return wxFileName::GetHomeDir(); |
114 | | } |
115 | | |
116 | | wxString wxStandardPaths::GetPluginsDir() const |
117 | | { |
118 | | return wxString(); // TODO: this is wrong, it should return something |
119 | | } |
120 | | |
121 | | wxString |
122 | | wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang, |
123 | | ResourceCat category) const |
124 | | { |
125 | | return wxStandardPathsBase::GetLocalizedResourcesDir(lang, category); |
126 | | } |
127 | | |
128 | | wxString wxStandardPaths::GetExecutablePath() const |
129 | | { |
130 | | return wxStandardPathsBase::GetExecutablePath(); |
131 | | } |
132 | | |
133 | | #else // !__VMS |
134 | | |
135 | | // ============================================================================ |
136 | | // wxStandardPaths implementation for Unix |
137 | | // ============================================================================ |
138 | | |
139 | | wxString wxStandardPaths::GetExecutablePath() const |
140 | 0 | { |
141 | 0 | #ifdef __LINUX__ |
142 | 0 | wxString exeStr; |
143 | |
|
144 | 0 | char buf[4096]; |
145 | 0 | int result = readlink("/proc/self/exe", buf, WXSIZEOF(buf) - 1); |
146 | 0 | if ( result != -1 ) |
147 | 0 | { |
148 | 0 | buf[result] = '\0'; // readlink() doesn't NUL-terminate the buffer |
149 | | |
150 | | // if the /proc/self/exe symlink has been dropped by the kernel for |
151 | | // some reason, then readlink() could also return success but |
152 | | // "(deleted)" as link destination... |
153 | 0 | if ( strcmp(buf, "(deleted)") != 0 ) |
154 | 0 | exeStr = wxString(buf, wxConvLibc); |
155 | 0 | } |
156 | |
|
157 | 0 | if ( exeStr.empty() ) |
158 | 0 | { |
159 | | // UPX-specific hack: when using UPX on linux, the kernel will drop the |
160 | | // /proc/self/exe link; in this case we try to look for a special |
161 | | // environment variable called " " which is created by UPX to save |
162 | | // /proc/self/exe contents. See |
163 | | // http://sf.net/tracker/?func=detail&atid=309863&aid=1565357&group_id=9863 |
164 | | // for more information about this issue. |
165 | 0 | wxGetEnv(wxT(" "), &exeStr); |
166 | 0 | } |
167 | |
|
168 | 0 | if ( !exeStr.empty() ) |
169 | 0 | return exeStr; |
170 | 0 | #endif // __LINUX__ |
171 | | |
172 | 0 | return wxStandardPathsBase::GetExecutablePath(); |
173 | 0 | } |
174 | | |
175 | | void wxStandardPaths::DetectPrefix() |
176 | 0 | { |
177 | | // we can try to infer the prefix from the location of the executable |
178 | 0 | wxString exeStr = GetExecutablePath(); |
179 | 0 | if ( !exeStr.empty() ) |
180 | 0 | { |
181 | | // consider that we're in the last "bin" subdirectory of our prefix |
182 | 0 | size_t pos = exeStr.rfind(wxT("/bin/")); |
183 | 0 | if ( pos != wxString::npos ) |
184 | 0 | m_prefix.assign(exeStr, 0, pos); |
185 | 0 | } |
186 | |
|
187 | 0 | if ( m_prefix.empty() ) |
188 | 0 | { |
189 | 0 | m_prefix = wxT("/usr/local"); |
190 | 0 | } |
191 | 0 | } |
192 | | |
193 | | wxString wxStandardPaths::GetInstallPrefix() const |
194 | 0 | { |
195 | 0 | if ( m_prefix.empty() ) |
196 | 0 | { |
197 | 0 | wxStandardPaths *pathPtr = const_cast<wxStandardPaths *>(this); |
198 | 0 | pathPtr->DetectPrefix(); |
199 | 0 | } |
200 | |
|
201 | 0 | return m_prefix; |
202 | 0 | } |
203 | | |
204 | | // ---------------------------------------------------------------------------- |
205 | | // public functions |
206 | | // ---------------------------------------------------------------------------- |
207 | | |
208 | | wxString wxStandardPaths::GetConfigDir() const |
209 | 0 | { |
210 | 0 | return wxT("/etc"); |
211 | 0 | } |
212 | | |
213 | | wxString wxStandardPaths::GetDataDir() const |
214 | 0 | { |
215 | | // allow to override the location of the data directory by setting |
216 | | // WX_APPNAME_DATA_DIR environment variable: this is very useful in |
217 | | // practice for running well-written (and so using wxStandardPaths to find |
218 | | // their files) wx applications without installing them |
219 | 0 | static const wxString |
220 | 0 | envOverride( |
221 | 0 | getenv( |
222 | 0 | ("WX_" + wxTheApp->GetAppName().Upper() + "_DATA_DIR").c_str() |
223 | 0 | ) |
224 | 0 | ); |
225 | |
|
226 | 0 | if ( !envOverride.empty() ) |
227 | 0 | return envOverride; |
228 | | |
229 | 0 | return AppendAppInfo(GetInstallPrefix() + wxT("/share")); |
230 | 0 | } |
231 | | |
232 | | wxString wxStandardPaths::GetLocalDataDir() const |
233 | 0 | { |
234 | 0 | return AppendAppInfo(wxT("/etc")); |
235 | 0 | } |
236 | | |
237 | | wxString wxStandardPaths::GetUserDataDir() const |
238 | 0 | { |
239 | 0 | return AppendAppInfo(wxFileName::GetHomeDir() + wxT("/.")); |
240 | 0 | } |
241 | | |
242 | | wxString wxStandardPaths::GetPluginsDir() const |
243 | 0 | { |
244 | 0 | return AppendAppInfo(GetInstallPrefix() + wxT("/lib")); |
245 | 0 | } |
246 | | |
247 | | wxString |
248 | | wxStandardPaths::GetLocalizedResourcesDir(const wxString& lang, |
249 | | ResourceCat category) const |
250 | 0 | { |
251 | 0 | if ( category != ResourceCat_Messages ) |
252 | 0 | return wxStandardPathsBase::GetLocalizedResourcesDir(lang, category); |
253 | | |
254 | 0 | return GetInstallPrefix() + wxT("/share/locale/") + lang + wxT("/LC_MESSAGES"); |
255 | 0 | } |
256 | | |
257 | | wxString wxStandardPaths::GetUserDir(Dir userDir) const |
258 | 0 | { |
259 | | // Note that we do not use the file layout here because there is no reason |
260 | | // not to respect the XDG convention even if SetFileLayout(FileLayout_XDG) |
261 | | // hadn't been called: we're not bound by any backwards compatibility |
262 | | // considerations as there can't be any pre-existing config or data files |
263 | | // in the home directory that wouldn't be found any longer after updating |
264 | | // the version of wxWidgets used by the application. |
265 | |
|
266 | 0 | wxLogNull logNull; |
267 | 0 | const wxString homeDir = wxFileName::GetHomeDir(); |
268 | 0 | if (userDir == Dir_Cache) |
269 | 0 | { |
270 | 0 | wxString cacheDir; |
271 | 0 | if ( !wxGetEnv(wxS("XDG_CACHE_HOME"), &cacheDir) ) |
272 | 0 | cacheDir = homeDir + wxS("/.cache"); |
273 | |
|
274 | 0 | return cacheDir; |
275 | 0 | } |
276 | | |
277 | 0 | const wxString configDir = GetXDGConfigHome(); |
278 | 0 | if (userDir == Dir_Config) |
279 | 0 | return configDir; |
280 | | |
281 | 0 | const wxFileName dirsFile(configDir, wxS("user-dirs.dirs")); |
282 | 0 | if ( dirsFile.FileExists() ) |
283 | 0 | { |
284 | 0 | wxString userDirId; |
285 | 0 | switch (userDir) |
286 | 0 | { |
287 | 0 | case Dir_Desktop: |
288 | 0 | userDirId = "XDG_DESKTOP_DIR"; |
289 | 0 | break; |
290 | 0 | case Dir_Downloads: |
291 | 0 | userDirId = "XDG_DOWNLOAD_DIR"; |
292 | 0 | break; |
293 | 0 | case Dir_Music: |
294 | 0 | userDirId = "XDG_MUSIC_DIR"; |
295 | 0 | break; |
296 | 0 | case Dir_Pictures: |
297 | 0 | userDirId = "XDG_PICTURES_DIR"; |
298 | 0 | break; |
299 | 0 | case Dir_Videos: |
300 | 0 | userDirId = "XDG_VIDEOS_DIR"; |
301 | 0 | break; |
302 | 0 | default: |
303 | 0 | userDirId = "XDG_DOCUMENTS_DIR"; |
304 | 0 | break; |
305 | 0 | } |
306 | | |
307 | 0 | wxTextFile textFile; |
308 | 0 | if ( textFile.Open(dirsFile.GetFullPath()) ) |
309 | 0 | { |
310 | 0 | for ( wxString line = textFile.GetFirstLine(); |
311 | 0 | !textFile.Eof(); |
312 | 0 | line = textFile.GetNextLine() ) |
313 | 0 | { |
314 | 0 | int pos = line.Find(userDirId); |
315 | 0 | if (pos != wxNOT_FOUND) |
316 | 0 | { |
317 | 0 | wxString value = line.AfterFirst(wxT('=')); |
318 | 0 | value.Replace(wxT("$HOME"), homeDir); |
319 | 0 | value.Trim(true); |
320 | 0 | value.Trim(false); |
321 | | // Remove quotes |
322 | 0 | value.Replace("\"", "", true /* replace all */); |
323 | 0 | if (!value.IsEmpty() && wxDirExists(value)) |
324 | 0 | return value; |
325 | 0 | else |
326 | 0 | break; |
327 | 0 | } |
328 | 0 | } |
329 | 0 | } |
330 | 0 | } |
331 | | |
332 | 0 | return wxStandardPathsBase::GetUserDir(userDir); |
333 | 0 | } |
334 | | |
335 | | #endif // __VMS/!__VMS |
336 | | |
337 | | wxString |
338 | | wxStandardPaths::MakeConfigFileName(const wxString& basename, |
339 | | ConfigFileConv conv) const |
340 | 0 | { |
341 | 0 | wxFileName fn(wxEmptyString, basename); |
342 | |
|
343 | 0 | bool addExt = false; |
344 | |
|
345 | 0 | switch ( GetFileLayout() ) |
346 | 0 | { |
347 | 0 | case FileLayout_Classic: |
348 | 0 | switch ( conv ) |
349 | 0 | { |
350 | 0 | case ConfigFileConv_Dot: |
351 | 0 | fn.SetName(wxT('.') + fn.GetName()); |
352 | 0 | break; |
353 | | |
354 | 0 | case ConfigFileConv_Ext: |
355 | 0 | addExt = true; |
356 | 0 | break; |
357 | 0 | } |
358 | 0 | break; |
359 | | |
360 | 0 | case FileLayout_XDG: |
361 | | // Dot files are never used in XDG mode. |
362 | 0 | addExt = true; |
363 | 0 | break; |
364 | 0 | } |
365 | | |
366 | 0 | if ( addExt ) |
367 | 0 | fn.SetExt(wxS("conf")); |
368 | |
|
369 | 0 | return fn.GetFullName(); |
370 | 0 | } |
371 | | |
372 | | wxString wxStandardPaths::GetSharedLibrariesDir() const |
373 | 0 | { |
374 | 0 | return GetInstallPrefix() + "/lib"; |
375 | 0 | } |
376 | | |
377 | | #endif // wxUSE_STDPATHS |