@@ -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
390394VkResult 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
412436VkResult 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
431516bool 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