Skip to content

Commit 508795c

Browse files
loader settings unix search path follows driver/layer searching
The searching for the loader_settings.json file relied on faulty assumptions about which paths would be used, notably ignoring XDG env-vars, as well as SYSCONFDIR, EXTRASYSCONFDIR, and the fallback xdg paths.
1 parent bacab74 commit 508795c

File tree

2 files changed

+106
-21
lines changed

2 files changed

+106
-21
lines changed

loader/loader.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3270,7 +3270,7 @@ void copy_data_file_info(const char *cur_path, const char *relative_path, size_t
32703270
char *cur_write = *output_path;
32713271

32723272
while (cur_path[start] != '\0') {
3273-
while (cur_path[start] == PATH_SEPARATOR) {
3273+
while (cur_path[start] == PATH_SEPARATOR && cur_path[start] != '\0') {
32743274
start++;
32753275
}
32763276
stop = start;

loader/settings.c

Lines changed: 105 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -387,46 +387,131 @@ VkResult parse_device_configurations(const struct loader_instance* inst, cJSON*
387387
return res;
388388
}
389389

390+
#if COMMON_UNIX_PLATFORMS
391+
// Given a base and suffix path, determine if a file at that location exists, and if it is return success.
392+
// Since base may contain multiple paths seperated by PATH_SEPARATOR, we must extract each segment and check segment + suffix
393+
// individually
390394
VkResult check_if_settings_path_exists(const struct loader_instance* inst, const char* base, const char* suffix,
391395
char** settings_file_path) {
392396
if (NULL == base || NULL == suffix) {
393397
return VK_ERROR_INITIALIZATION_FAILED;
394398
}
399+
395400
size_t base_len = strlen(base);
396401
size_t suffix_len = strlen(suffix);
397-
size_t path_len = base_len + suffix_len + 1;
398-
*settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
399-
if (NULL == *settings_file_path) {
400-
return VK_ERROR_OUT_OF_HOST_MEMORY;
401-
}
402-
loader_strncpy(*settings_file_path, path_len, base, base_len);
403-
loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
404402

405-
if (!loader_platform_file_exists(*settings_file_path)) {
403+
uint32_t start = 0;
404+
uint32_t stop = 0;
405+
while (base[start] != '\0' && start < base_len && stop < base_len) {
406+
start = stop;
407+
stop = start + 1;
408+
while (base[stop] != PATH_SEPARATOR && base[stop] != '\0' && stop < base_len) {
409+
stop++;
410+
}
411+
412+
size_t segment_len = (stop - start);
413+
if (segment_len <= 1) {
414+
// segment is *just* a PATH_SEPARATOR, skip it
415+
continue;
416+
}
417+
size_t path_len = segment_len + suffix_len + 1;
418+
*settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
419+
if (NULL == *settings_file_path) {
420+
return VK_ERROR_OUT_OF_HOST_MEMORY;
421+
}
422+
loader_strncpy(*settings_file_path, path_len, base + start, segment_len);
423+
loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
424+
425+
if (loader_platform_file_exists(*settings_file_path)) {
426+
return VK_SUCCESS;
427+
}
406428
loader_instance_heap_free(inst, *settings_file_path);
407429
*settings_file_path = NULL;
408-
return VK_ERROR_INITIALIZATION_FAILED;
409430
}
410-
return VK_SUCCESS;
431+
432+
return VK_ERROR_INITIALIZATION_FAILED;
411433
}
434+
435+
// Follow the logic of read_data_files_in_search_paths but only look for "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME
412436
VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
413-
VkResult res =
414-
check_if_settings_path_exists(inst, loader_secure_getenv("HOME", inst),
415-
"/.local/share/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
437+
// First, get XDG env-vars we use. Don't need to worry about free'ing because on linux getenv is non-allocating
438+
char* xdg_config_home = loader_secure_getenv("XDG_CONFIG_HOME", inst);
439+
char* xdg_config_dirs = loader_secure_getenv("XDG_CONFIG_DIRS", inst);
440+
char* xdg_data_home = loader_secure_getenv("XDG_DATA_HOME", inst);
441+
char* xdg_data_dirs = loader_secure_getenv("XDG_DATA_DIRS", inst);
442+
443+
// Use fallback directories for xdg_config_dirs and xdg_data_dirs if they are NULL.
444+
#if !defined(__Fuchsia__) && !defined(__QNX__)
445+
if (NULL == xdg_config_dirs || '\0' == xdg_config_dirs[0]) {
446+
xdg_config_dirs = FALLBACK_CONFIG_DIRS;
447+
}
448+
#endif
449+
450+
#if !defined(__Fuchsia__) && !defined(__QNX__)
451+
if (NULL == xdg_data_dirs || '\0' == xdg_data_dirs[0]) {
452+
xdg_data_dirs = FALLBACK_DATA_DIRS;
453+
}
454+
#endif
455+
456+
VkResult res = check_if_settings_path_exists(inst, xdg_config_home, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
457+
settings_file_path);
458+
if (res == VK_SUCCESS) {
459+
return res;
460+
}
461+
462+
res = check_if_settings_path_exists(inst, xdg_data_home, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
463+
settings_file_path);
464+
if (res == VK_SUCCESS) {
465+
return res;
466+
}
467+
468+
// Check home if either xdg_config_home or xdg_data_home wasn't set
469+
char* home = loader_secure_getenv("HOME", inst);
470+
if (home != NULL) {
471+
if (NULL == xdg_config_home || '\0' == xdg_config_home[0]) {
472+
res = check_if_settings_path_exists(inst, home, "/.config/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
473+
settings_file_path);
474+
if (res == VK_SUCCESS) {
475+
return res;
476+
}
477+
}
478+
if (NULL == xdg_data_home || '\0' == xdg_data_home[0]) {
479+
res = check_if_settings_path_exists(inst, home, "/.local/share/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
480+
settings_file_path);
481+
if (res == VK_SUCCESS) {
482+
return res;
483+
}
484+
}
485+
}
486+
487+
res = check_if_settings_path_exists(inst, xdg_config_dirs, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
488+
settings_file_path);
416489
if (res == VK_SUCCESS) {
417490
return res;
418491
}
419-
// If HOME isn't set, fallback to XDG_DATA_HOME
420-
res = check_if_settings_path_exists(inst, loader_secure_getenv("XDG_DATA_HOME", inst),
421-
"/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
492+
493+
res = check_if_settings_path_exists(inst, SYSCONFDIR, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
494+
settings_file_path);
495+
if (res == VK_SUCCESS) {
496+
return res;
497+
}
498+
#if defined(EXTRASYSCONFDIR)
499+
500+
res = check_if_settings_path_exists(inst, EXTRASYSCONFDIR, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
501+
settings_file_path);
422502
if (res == VK_SUCCESS) {
423503
return res;
424504
}
425-
// if XDG_DATA_HOME isn't set, fallback to /etc.
426-
// note that the settings_fil_path_suffix stays the same since its the same layout as for XDG_DATA_HOME
427-
return check_if_settings_path_exists(inst, "/etc", "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
428-
settings_file_path);
505+
#endif
506+
res = check_if_settings_path_exists(inst, xdg_data_dirs, "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
507+
settings_file_path);
508+
if (res == VK_SUCCESS) {
509+
return res;
510+
}
511+
512+
return VK_ERROR_INITIALIZATION_FAILED;
429513
}
514+
#endif
430515

431516
bool check_if_layer_configurations_are_equal(loader_settings_layer_configuration* a, loader_settings_layer_configuration* b) {
432517
if (!a->name || !b->name || 0 != strcmp(a->name, b->name)) {

0 commit comments

Comments
 (0)