Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
file_location.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2014, 2016-2017 Tobias Ellinghaus.
4 Copyright (C) 2011 Henrik Andersson.
5 Copyright (C) 2011 johannes hanika.
6 Copyright (C) 2011 Kanstantsin Shautsou.
7 Copyright (C) 2011 Moritz Lipp.
8 Copyright (C) 2012 Christian Tellefsen.
9 Copyright (C) 2012 Jean-Sébastien Pédron.
10 Copyright (C) 2012 Jérémy Rosen.
11 Copyright (C) 2012 Richard Wonka.
12 Copyright (C) 2013 Simon Spannagel.
13 Copyright (C) 2014, 2016 Roman Lebedev.
14 Copyright (C) 2016 Pedro Côrte-Real.
15 Copyright (C) 2016-2017 Peter Budai.
16 Copyright (C) 2018 parafin.
17 Copyright (C) 2019 Philippe Weyland.
18 Copyright (C) 2020-2021 David-Tillmann Schaefer.
19 Copyright (C) 2020-2021 Pascal Obry.
20 Copyright (C) 2022, 2025-2026 Aurélien PIERRE.
21 Copyright (C) 2022 Martin Bařinka.
22 Copyright (C) 2023 Alynx Zhou.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37
38/* getpwnam_r availability check */
39#if defined __APPLE__ || defined _POSIX_C_SOURCE >= 1 || defined _XOPEN_SOURCE || defined _BSD_SOURCE \
40 || defined _SVID_SOURCE || defined _POSIX_SOURCE || defined __DragonFly__ || defined __FreeBSD__ \
41 || defined __NetBSD__ || defined __OpenBSD__
42#include "config.h"
43
44#include <pwd.h>
45#define HAVE_GETPWNAM_R 1
46#endif
47
48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
51
52#ifdef __APPLE__
53#include "osx/osx.h"
54#endif
55
56#include "common/grealpath.h"
57#include "common/paths.h" // DT_PATH_MAX
58#include "darktable.h"
59#include "file_location.h"
60#include "whereami.h"
61#include "system/macros.h"
62#include "system/mem_alloc.h"
63#include "common/logging.h"
64#include "common/utility.h"
65
66void dt_loc_init(const char *datadir, const char *moduledir, const char *localedir, const char *configdir, const char *cachedir, const char *tmpdir, const char *kerneldir)
67{
68 // Assemble pathes
69 char* application_directory = NULL;
70 int dirname_length;
71 // calling wai_getExecutablePath twice as recommended in the docs:
72 // the first call retrieves the length of the path
73 int length = wai_getExecutablePath(NULL, 0, &dirname_length);
74 if (length > 0)
75 {
76 application_directory = (char*)malloc(length + 1);
77 // the second call retrieves the path including the executable
78 wai_getExecutablePath(application_directory, length, &dirname_length);
79 // strip of the executable name from the path to retrieve the path alone
80 application_directory[dirname_length] = '\0';
81 }
82 dt_print(DT_DEBUG_DEV, "application_directory: %s\n", application_directory);
83
84 // set up absolute pathes based on their relative value
85 dt_loc_init_datadir(application_directory, datadir);
86 dt_loc_init_moduledir(application_directory, moduledir);
87 dt_loc_init_localedir(application_directory, localedir);
88 dt_loc_init_kerneldir(application_directory, kerneldir);
91 dt_loc_init_sharedir(application_directory);
92 dt_loc_init_tmp_dir(tmpdir);
93 dt_free(application_directory);
94}
95
96gchar *dt_loc_get_home_dir(const gchar *user)
97{
98 if(IS_NULL_PTR(user) || g_strcmp0(user, g_get_user_name()) == 0)
99 {
100 const char *home_dir = g_getenv("HOME");
101 return g_strdup((!IS_NULL_PTR(home_dir)) ? home_dir : g_get_home_dir());
102 }
103
104#if defined HAVE_GETPWNAM_R
105 /* if the given username is not the same as the current one, we try
106 * to retrieve the pw dir from the password file entry */
107 struct passwd pwd;
108 struct passwd *result;
109#ifdef _SC_GETPW_R_SIZE_MAX
110 int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
111 if(bufsize < 0)
112 {
113 bufsize = 4096;
114 }
115#else
116 int bufsize = 4096;
117#endif
118
119 gchar *buffer = g_malloc0_n(bufsize, sizeof(gchar));
120 if(IS_NULL_PTR(buffer))
121 {
122 return NULL;
123 }
124
125 getpwnam_r(user, &pwd, buffer, bufsize, &result);
126 if(IS_NULL_PTR(result))
127 {
128 dt_free(buffer);
129 return NULL;
130 }
131
132 gchar *dir = g_strdup(pwd.pw_dir);
133 dt_free(buffer);
134
135 return dir;
136#else
137 return NULL;
138#endif
139}
140
141gchar *dt_loc_init_generic(const char *absolute_value, const char *application_directory, const char *default_value)
142{
143 gchar *result = NULL;
144 gchar *path = NULL;
145
146 if(absolute_value)
147 {
148 // the only adjustment the absolute path needs is transforming the possible tilde '~' to an absolute path
149 path = dt_util_fix_path(absolute_value);
150 }
151 else
152 {
153 // the default_value could be absolute or relative. we decide upon presence of the application_directory.
154 if(application_directory)
155 {
156 // default_value is relative.
157 // combine basename (application_directory) and relative path (default_value).
158 gchar complete_path[DT_PATH_MAX] = { 0 };
159#if defined(__APPLE__)
160 char *bundle_path = dt_osx_get_bundle_res_path();
161 if(bundle_path)
162 {
164
165 // on a mac inside the bundle the executables are in <bundleroot>/Contents/MacOS/
166 // all other directories are a subdirectory of <bundleroot>/Contents/Resources:
167 // <bundleroot>/Contents/Resources/etc
168 // <bundleroot>/Contents/Resources/lib
169 // <bundleroot>/Contents/Resources/share
170 // so the relative path from the binary directory to the other directories differs to the non-bundle version by
171 // ../etc -> ../Resources/etc,
172 // ../lib -> ../Resources/lib,
173 // ../share -> ../Resources/share,
174 // So we have to modify the relative default value
175
176 // +2: removes the two dots '..'
177 g_snprintf(complete_path, sizeof(complete_path), "%s/../Resources%s", application_directory, default_value + 2);
178 }
179 else
180 {
182 g_snprintf(complete_path, sizeof(complete_path), "%s/%s", application_directory, default_value);
183 }
184#else
185 g_snprintf(complete_path, sizeof(complete_path), "%s/%s", application_directory, default_value);
186#endif
187 path = g_strdup(complete_path);
188 }
189 else
190 {
191 // default_value is absolute
192 path = g_strdup(default_value);
193 }
194 }
195
196 // create file if it does not exist
197 if(g_file_test(path, G_FILE_TEST_EXISTS) == FALSE) g_mkdir_with_parents(path, 0700);
198
199 // removes '.', '..', and extra '/' characters.
200 result = g_realpath(path);
201
202 dt_free(path);
203 return result;
204}
205
206void dt_loc_init_user_config_dir(const char *configdir)
207{
208 char *default_config_dir = g_build_filename(g_get_user_config_dir(), "ansel", NULL);
209 darktable.configdir = dt_loc_init_generic(configdir, NULL, default_config_dir);
210 dt_check_opendir("ansel.configdir", darktable.configdir);
211 dt_free(default_config_dir);
212}
213
214void dt_loc_init_tmp_dir(const char *tmpdir)
215{
216 darktable.tmpdir = dt_loc_init_generic(tmpdir, NULL, g_get_tmp_dir());
217 dt_check_opendir("ansel.tmpdir", darktable.tmpdir);
218}
219
220void dt_loc_init_user_cache_dir(const char *cachedir)
221{
222 char *default_cache_dir = g_build_filename(g_get_user_cache_dir(), "ansel", NULL);
223 darktable.cachedir = dt_loc_init_generic(cachedir, NULL, default_cache_dir);
224 dt_check_opendir("ansel.cachedir", darktable.cachedir);
225 dt_free(default_cache_dir);
226}
227
228void dt_loc_init_moduledir(const char* application_directory, const char *moduledir)
229{
230 darktable.moduledir = dt_loc_init_generic(moduledir, application_directory, DARKTABLE_MODULEDIR);
231 dt_check_opendir("ansel.moduledir", darktable.moduledir);
232}
233
234void dt_check_opendir(const char* context, const char* directory)
235{
237 {
238 fprintf(stderr, "directory for %s has not been set.\n", context);
239 exit(EXIT_FAILURE);
240 }
241
242#if _WIN32
243 wchar_t *wdirectory = g_utf8_to_utf16 (directory, -1, NULL, NULL, NULL);
244 DWORD attribs = GetFileAttributesW(wdirectory);
245 dt_free(wdirectory);
246 if (attribs != INVALID_FILE_ATTRIBUTES &&
247 (attribs & FILE_ATTRIBUTE_DIRECTORY))
248 {
249 dt_print(DT_DEBUG_DEV, "%s: %s\n", context, directory);
250 }
251 else
252 {
253 fprintf(stderr, "%s: directory '%s' fails to open.'\n", context, directory);
254 exit(EXIT_FAILURE);
255 }
256#else
257 DIR* dir = opendir(directory);
258 if (dir)
259 {
260 dt_print(DT_DEBUG_DEV, "%s: %s\n", context, directory);
261 closedir(dir);
262 }
263 else
264 {
265 fprintf(stderr, "opendir '%s' fails with: '%s'\n", directory, strerror(errno));
266 exit(EXIT_FAILURE);
267 }
268#endif
269}
270
271void dt_loc_init_localedir(const char* application_directory, const char *localedir)
272{
273 darktable.localedir = dt_loc_init_generic(localedir, application_directory, DARKTABLE_LOCALEDIR);
274 dt_check_opendir("ansel.localedir", darktable.localedir);
275}
276
277void dt_loc_init_datadir(const char* application_directory, const char *datadir)
278{
279 darktable.datadir = dt_loc_init_generic(datadir, application_directory, DARKTABLE_DATADIR);
280 dt_check_opendir("ansel.datadir", darktable.datadir);
281}
282
283void dt_loc_init_sharedir(const char* application_directory)
284{
285 darktable.sharedir = dt_loc_init_generic(NULL, application_directory, DARKTABLE_SHAREDIR);
286 dt_check_opendir("ansel.sharedir", darktable.sharedir);
287}
288
289void dt_loc_init_kerneldir(const char* application_directory, const char *kerneldir)
290{
291#ifdef HAVE_OPENCL
292 darktable.kerneldir = dt_loc_init_generic(kerneldir, application_directory, DARKTABLE_KERNELSDIR);
293 dt_check_opendir("ansel.kerneldir", darktable.kerneldir);
294#else
295 darktable.kerneldir = NULL;
296#endif
297}
298
299const char *dt_loc_datadir(void)
300{
301 return darktable.datadir;
302}
303
304const char *dt_loc_sharedir(void)
305{
306 return darktable.sharedir;
307}
308
309const char *dt_loc_moduledir(void)
310{
311 return darktable.moduledir;
312}
313
314const char *dt_loc_localedir(void)
315{
316 return darktable.localedir;
317}
318
319const char *dt_loc_tmpdir(void)
320{
321 return darktable.tmpdir;
322}
323
324const char *dt_loc_configdir(void)
325{
326 return darktable.configdir;
327}
328
329const char *dt_loc_cachedir(void)
330{
331 return darktable.cachedir;
332}
333
334const char *dt_loc_kerneldir(void)
335{
336 return darktable.kerneldir;
337}
338
339void dt_loc_get_kerneldir(char *kerneldir, size_t bufsize)
340{
341 g_strlcpy(kerneldir, dt_loc_kerneldir(), bufsize);
342}
343
344void dt_loc_get_moduledir(char *moduledir, size_t bufsize)
345{
346 g_strlcpy(moduledir, dt_loc_moduledir(), bufsize);
347}
348
349void dt_loc_get_localedir(char *localedir, size_t bufsize)
350{
351 g_strlcpy(localedir, dt_loc_localedir(), bufsize);
352}
353
354void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
355{
356 g_strlcpy(configdir, dt_loc_configdir(), bufsize);
357}
358void dt_loc_get_user_cache_dir(char *cachedir, size_t bufsize)
359{
360 g_strlcpy(cachedir, dt_loc_cachedir(), bufsize);
361}
362void dt_loc_get_tmp_dir(char *tmpdir, size_t bufsize)
363{
364 g_strlcpy(tmpdir, dt_loc_tmpdir(), bufsize);
365}
366void dt_loc_get_datadir(char *datadir, size_t bufsize)
367{
368 g_strlcpy(datadir, dt_loc_datadir(), bufsize);
369}
370void dt_loc_get_sharedir(char *sharedir, size_t bufsize)
371{
372 g_strlcpy(sharedir, dt_loc_sharedir(), bufsize);
373}
374// clang-format off
375// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
376// vim: shiftwidth=2 expandtab tabstop=2 cindent
377// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
378// clang-format on
#define FALSE
Definition ashift_lsd.c:158
#define DARKTABLE_LOCALEDIR
#define DARKTABLE_KERNELSDIR
#define DARKTABLE_DATADIR
#define DARKTABLE_SHAREDIR
#define DARKTABLE_MODULEDIR
darktable_t darktable
Definition darktable.c:213
gchar * directory
documentation root given after –doc, or NULL
void dt_loc_get_sharedir(char *sharedir, size_t bufsize)
void dt_loc_init_tmp_dir(const char *tmpdir)
const char * dt_loc_moduledir(void)
const char * dt_loc_sharedir(void)
void dt_loc_init_moduledir(const char *application_directory, const char *moduledir)
void dt_loc_get_user_cache_dir(char *cachedir, size_t bufsize)
void dt_loc_get_tmp_dir(char *tmpdir, size_t bufsize)
const char * dt_loc_datadir(void)
const char * dt_loc_cachedir(void)
void dt_loc_get_kerneldir(char *kerneldir, size_t bufsize)
void dt_loc_get_datadir(char *datadir, size_t bufsize)
void dt_loc_get_localedir(char *localedir, size_t bufsize)
gchar * dt_loc_init_generic(const char *absolute_value, const char *application_directory, const char *default_value)
void dt_loc_init_datadir(const char *application_directory, const char *datadir)
void dt_loc_init_user_cache_dir(const char *cachedir)
void dt_loc_init(const char *datadir, const char *moduledir, const char *localedir, const char *configdir, const char *cachedir, const char *tmpdir, const char *kerneldir)
const char * dt_loc_kerneldir(void)
void dt_loc_get_moduledir(char *moduledir, size_t bufsize)
void dt_loc_init_kerneldir(const char *application_directory, const char *kerneldir)
void dt_loc_init_localedir(const char *application_directory, const char *localedir)
const char * dt_loc_tmpdir(void)
void dt_loc_init_sharedir(const char *application_directory)
const char * dt_loc_configdir(void)
void dt_loc_init_user_config_dir(const char *configdir)
gchar * dt_loc_get_home_dir(const gchar *user)
void dt_check_opendir(const char *context, const char *directory)
const char * dt_loc_localedir(void)
void dt_loc_get_user_config_dir(char *configdir, size_t bufsize)
static gchar * g_realpath(const char *path)
Definition grealpath.h:49
@ DT_DEBUG_DEV
Definition logging.h:53
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
char * dt_osx_get_bundle_res_path()
Definition osx.mm:139
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
char * tmpdir
Definition darktable.h:219
char * cachedir
Definition darktable.h:221
char * sharedir
Definition darktable.h:216
char * moduledir
Definition darktable.h:217
char * configdir
Definition darktable.h:220
char * datadir
Definition darktable.h:215
char * localedir
Definition darktable.h:218
char * kerneldir
Definition darktable.h:222
gchar * dt_util_fix_path(const gchar *path)
Definition utility.c:226