Blender V5.0
GHOST_SystemPathsUnix.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2010 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <optional>
10#include <sstream>
11
13
14#include "GHOST_Debug.hh"
15
16/* For timing. */
17#include <sys/time.h>
18#include <unistd.h>
19
20#include <pwd.h> /* For get home without use `getenv()`. */
21#include <string>
22
23using std::string;
24
25#ifdef PREFIX
26static const char *static_path = PREFIX "/share";
27#else
28static const char *static_path = nullptr;
29#endif
30
32
34
35const char *GHOST_SystemPathsUnix::getSystemDir(int /*version*/, const char *versionstr) const
36{
37 /* no prefix assumes a portable build which only uses bundled scripts */
38 if (static_path) {
39 static string system_path = string(static_path) + "/blender/" + versionstr;
40 return system_path.c_str();
41 }
42
43 return nullptr;
44}
45
49static const char *home_dir_get()
50{
51 const char *home_dir = getenv("HOME");
52 if (home_dir == nullptr) {
53 if (const passwd *pwuser = getpwuid(getuid())) {
54 home_dir = pwuser->pw_dir;
55 }
56 }
57 return home_dir;
58}
59
60const char *GHOST_SystemPathsUnix::getUserDir(int version, const char *versionstr) const
61{
62 static string user_path;
63 static int last_version = 0;
64
65 /* in blender 2.64, we migrate to XDG. to ensure the copy previous settings
66 * operator works we give a different path depending on the requested version */
67 if (version < 264) {
68 if (user_path.empty() || last_version != version) {
69 const char *home = home_dir_get();
70
71 last_version = version;
72
73 if (home) {
74 user_path = string(home) + "/.blender/" + versionstr;
75 }
76 else {
77 return nullptr;
78 }
79 }
80 return user_path.c_str();
81 }
82 if (user_path.empty() || last_version != version) {
83 const char *home = getenv("XDG_CONFIG_HOME");
84
85 last_version = version;
86
87 if (home) {
88 user_path = string(home) + "/blender/" + versionstr;
89 }
90 else {
91 home = home_dir_get();
92 if (home) {
93 user_path = string(home) + "/.config/blender/" + versionstr;
94 }
95 else {
96 return nullptr;
97 }
98 }
99 }
100
101 return user_path.c_str();
102}
103
106{
107 const char *type_str;
108
109 switch (type) {
111 type_str = "DESKTOP";
112 break;
114 type_str = "DOCUMENTS";
115 break;
117 type_str = "DOWNLOAD";
118 break;
120 type_str = "MUSIC";
121 break;
123 type_str = "PICTURES";
124 break;
126 type_str = "VIDEOS";
127 break;
129 const char *cache_dir = getenv("XDG_CACHE_HOME");
130 if (cache_dir) {
131 return cache_dir;
132 }
133
134 /* If `XDG_CACHE_HOME` is not set, then `$HOME/.cache is used`. */
135 const char *home_dir = home_dir_get();
136 if (home_dir == nullptr) {
137 return std::nullopt;
138 }
139 return string(home_dir) + "/.cache";
140 }
141 default:
143 false,
144 "GHOST_SystemPathsUnix::getUserSpecialDir(): Invalid enum value for type parameter");
145 return std::nullopt;
146 }
147
148 /* Pipe `stderr` to `/dev/null` to avoid error prints. We will fail gracefully still. */
149 string command = string("xdg-user-dir ") + type_str + " 2> /dev/null";
150
151 FILE *fstream = popen(command.c_str(), "r");
152 if (fstream == nullptr) {
153 return std::nullopt;
154 }
155 std::stringstream path_stream;
156 while (!feof(fstream)) {
157 char c = fgetc(fstream);
158 /* `xdg-user-dir` ends the path with '\n'. */
159 if (c == '\n') {
160 break;
161 }
162 path_stream << c;
163 }
164 if (pclose(fstream) == -1) {
165 perror("GHOST_SystemPathsUnix::getUserSpecialDir failed at pclose()");
166 return std::nullopt;
167 }
168
169 std::string path = path_stream.str();
170 return path[0] ? std::optional(path) : std::nullopt;
171}
172
174{
175 return nullptr;
176}
177
178void GHOST_SystemPathsUnix::addToSystemRecentFiles(const char * /*filename*/) const
179{
180 /* TODO: implement for X11 */
181}
#define GHOST_ASSERT(x, info)
static const char * static_path
static const char * home_dir_get()
GHOST_TUserSpecialDirTypes
@ GHOST_kUserSpecialDirDesktop
@ GHOST_kUserSpecialDirMusic
@ GHOST_kUserSpecialDirPictures
@ GHOST_kUserSpecialDirVideos
@ GHOST_kUserSpecialDirDownloads
@ GHOST_kUserSpecialDirCaches
@ GHOST_kUserSpecialDirDocuments
const char * getBinaryDir() const override
const char * getUserDir(int version, const char *versionstr) const override
std::optional< std::string > getUserSpecialDir(GHOST_TUserSpecialDirTypes type) const override
~GHOST_SystemPathsUnix() override
void addToSystemRecentFiles(const char *filepath) const override
const char * getSystemDir(int version, const char *versionstr) const override