Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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