diff options
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | loader/loader.c | 115 | ||||
-rw-r--r-- | loader/vk_loader_platform.h | 44 |
3 files changed, 106 insertions, 62 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d3037f82..494dd594 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,17 +286,10 @@ if(NOT WIN32) include(GNUInstallDirs) add_definitions(-DSYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}") - add_definitions(-DDATADIR="${CMAKE_INSTALL_FULL_DATADIR}") - # Make sure /etc is searched by the loader - if (NOT (CMAKE_INSTALL_FULL_SYSCONFDIR STREQUAL "/etc")) + if(NOT (CMAKE_INSTALL_FULL_SYSCONFDIR STREQUAL "/etc")) add_definitions(-DEXTRASYSCONFDIR="/etc") endif() - - # Make sure /usr/share is searched by the loader - if (NOT (CMAKE_INSTALL_FULL_DATADIR STREQUAL "/usr/share")) - add_definitions(-DEXTRADATADIR="/usr/share") - endif() endif() if(UNIX) diff --git a/loader/loader.c b/loader/loader.c index 2875af13..81c37c4c 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -30,6 +30,7 @@ #include <stdarg.h> #include <stdbool.h> #include <string.h> +#include <stddef.h> #include <sys/types.h> #if defined(_WIN32) @@ -2585,7 +2586,7 @@ static void loader_add_layer_properties(const struct loader_instance *inst, stru * Linux Layer| dirs | dirs */ static VkResult loader_get_manifest_files(const struct loader_instance *inst, const char *env_override, const char *source_override, - bool is_layer, bool warn_if_not_present, const char *location, const char *home_location, + bool is_layer, bool warn_if_not_present, const char *location, const char *relative_location, struct loader_manifest_files *out_files) { const char * override = NULL; char *override_getenv = NULL; @@ -2617,9 +2618,9 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co } #if !defined(_WIN32) - if (location == NULL && home_location == NULL) { + if (relative_location == NULL) { #else - home_location = NULL; + relative_location = NULL; if (location == NULL) { #endif loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, @@ -2638,16 +2639,92 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co // Make a copy of the input we are using so it is not modified // Also handle getting the location(s) from registry on Windows if (override == NULL) { - loc = loader_stack_alloc(strlen(location) + 1); + size_t loc_size = 0; +#if !defined(_WIN32) + const char *xdgconfdirs = secure_getenv("XDG_CONFIG_DIRS"); + const char *xdgdatadirs = secure_getenv("XDG_DATA_DIRS"); + if (xdgconfdirs == NULL || xdgconfdirs[0] == '\0') + xdgconfdirs = "/etc/xdg"; + if (xdgdatadirs == NULL || xdgdatadirs[0] == '\0') + xdgdatadirs = "/usr/local/share:/usr/share"; + const size_t rel_size = strlen(relative_location); + // Leave space for trailing separators + loc_size += strlen(xdgconfdirs) + strlen(xdgdatadirs) + 2*rel_size + 2; + for (const char *x = xdgconfdirs; *x; ++x) + if (*x == PATH_SEPARATOR) loc_size += rel_size; + for (const char *x = xdgdatadirs; *x; ++x) + if (*x == PATH_SEPARATOR) loc_size += rel_size; + loc_size += strlen(SYSCONFDIR) + rel_size + 1; +#if defined(EXTRASYSCONFDIR) + loc_size += strlen(EXTRASYSCONFDIR) + rel_size + 1; +#endif +#else + loc_size += strlen(location) + 1; +#endif + loc = loader_stack_alloc(loc_size); if (loc == NULL) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_manifest_files: Failed to allocate " "%d bytes for manifest file location.", - strlen(location)); + loc_size); res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } - strcpy(loc, location); + char *loc_write = loc; +#if !defined(_WIN32) + const char *loc_read; + + loc_read = &xdgconfdirs[0]; + for (const char *x = loc_read;; ++x) { + if (*x == PATH_SEPARATOR || *x == '\0') { + const size_t s = x - loc_read; + memcpy(loc_write, loc_read, s); + loc_write += s; + memcpy(loc_write, relative_location, rel_size); + loc_write += rel_size; + *loc_write++ = PATH_SEPARATOR; + if (*x == 0) + break; + loc_read = ++x; + } + } + + memcpy(loc_write, SYSCONFDIR, strlen(SYSCONFDIR)); + loc_write += strlen(SYSCONFDIR); + memcpy(loc_write, relative_location, rel_size); + loc_write += rel_size; + *loc_write++ = PATH_SEPARATOR; + +#if defined(EXTRASYSCONFDIR) + memcpy(loc_write, EXTRASYSCONFDIR, strlen(EXTRASYSCONFDIR)); + loc_write += strlen(EXTRASYSCONFDIR); + memcpy(loc_write, relative_location, rel_size); + loc_write += rel_size; + *loc_write++ = PATH_SEPARATOR; +#endif + + loc_read = &xdgdatadirs[0]; + for (const char *x = loc_read;; ++x) { + if (*x == PATH_SEPARATOR || *x == '\0') { + const size_t s = x - loc_read; + memcpy(loc_write, loc_read, s); + loc_write += s; + memcpy(loc_write, relative_location, rel_size); + loc_write += rel_size; + *loc_write++ = PATH_SEPARATOR; + if (*x == 0) + break; + loc_read = ++x; + } + } + --loc_write; +#else + memcpy(loc_write, location, strlen(location)); + loc_write += strlen(location); +#endif + assert(loc_write - loc < (ptrdiff_t)loc_size); + *loc_write = '\0'; + #if defined(_WIN32) VkResult reg_result = loaderGetRegistryFiles(inst, loc, ®); if (VK_SUCCESS != reg_result || NULL == reg) { @@ -2786,11 +2863,11 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co } file = next_file; #if !defined(_WIN32) - if (home_location != NULL && (next_file == NULL || *next_file == '\0') && override == NULL) { + if (relative_location != NULL && (next_file == NULL || *next_file == '\0') && override == NULL) { char *xdgdatahome = secure_getenv("XDG_DATA_HOME"); size_t len; if (xdgdatahome != NULL) { - char *home_loc = loader_stack_alloc(strlen(xdgdatahome) + 2 + strlen(home_location)); + char *home_loc = loader_stack_alloc(strlen(xdgdatahome) + 2 + strlen(relative_location)); if (home_loc == NULL) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_manifest_files: Failed to allocate " @@ -2800,15 +2877,15 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co } strcpy(home_loc, xdgdatahome); // Add directory separator if needed - if (home_location[0] != DIRECTORY_SYMBOL) { + if (relative_location[0] != DIRECTORY_SYMBOL) { len = strlen(home_loc); home_loc[len] = DIRECTORY_SYMBOL; home_loc[len + 1] = '\0'; } - strcat(home_loc, home_location); + strcat(home_loc, relative_location); file = home_loc; next_file = loader_get_next_path(file); - home_location = NULL; + relative_location = NULL; loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n", home_loc); @@ -2817,7 +2894,7 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co } else { char *home = secure_getenv("HOME"); if (home != NULL) { - char *home_loc = loader_stack_alloc(strlen(home) + 16 + strlen(home_location)); + char *home_loc = loader_stack_alloc(strlen(home) + 16 + strlen(relative_location)); if (home_loc == NULL) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, "loader_get_manifest_files: Failed to allocate " @@ -2834,15 +2911,15 @@ static VkResult loader_get_manifest_files(const struct loader_instance *inst, co } strcat(home_loc, ".local/share"); - if (home_location[0] != DIRECTORY_SYMBOL) { + if (relative_location[0] != DIRECTORY_SYMBOL) { len = strlen(home_loc); home_loc[len] = DIRECTORY_SYMBOL; home_loc[len + 1] = '\0'; } - strcat(home_loc, home_location); + strcat(home_loc, relative_location); file = home_loc; next_file = loader_get_next_path(file); - home_location = NULL; + relative_location = NULL; loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Searching the following path for manifest files: %s\n", home_loc); @@ -2914,7 +2991,7 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t } // Get a list of manifest files for ICDs - res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false, true, DEFAULT_VK_DRIVERS_INFO, HOME_VK_DRIVERS_INFO, + res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false, true, DEFAULT_VK_DRIVERS_INFO, RELATIVE_VK_DRIVERS_INFO, &manifest_files); if (VK_SUCCESS != res || manifest_files.count == 0) { goto out; @@ -3128,14 +3205,14 @@ void loader_layer_scan(const struct loader_instance *inst, struct loader_layer_l // Get a list of manifest files for explicit layers if (VK_SUCCESS != loader_get_manifest_files(inst, LAYERS_PATH_ENV, LAYERS_SOURCE_PATH, true, true, DEFAULT_VK_ELAYERS_INFO, - HOME_VK_ELAYERS_INFO, &manifest_files[0])) { + RELATIVE_VK_ELAYERS_INFO, &manifest_files[0])) { goto out; } // Get a list of manifest files for any implicit layers // Pass NULL for environment variable override - implicit layers are not // overridden by LAYERS_PATH_ENV - if (VK_SUCCESS != loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, HOME_VK_ILAYERS_INFO, + if (VK_SUCCESS != loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO, &manifest_files[1])) { goto out; } @@ -3198,7 +3275,7 @@ void loader_implicit_layer_scan(const struct loader_instance *inst, struct loade // Pass NULL for environment variable override - implicit layers are not // overridden by LAYERS_PATH_ENV VkResult res = - loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, HOME_VK_ILAYERS_INFO, &manifest_files); + loader_get_manifest_files(inst, NULL, NULL, true, false, DEFAULT_VK_ILAYERS_INFO, RELATIVE_VK_ILAYERS_INFO, &manifest_files); if (VK_SUCCESS != res || manifest_files.count == 0) { return; } diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h index 8a70865d..9af64a9e 100644 --- a/loader/vk_loader_platform.h +++ b/loader/vk_loader_platform.h @@ -57,35 +57,9 @@ #define VULKAN_ILAYERCONF_DIR "implicit_layer.d" #define VULKAN_LAYER_DIR "layer" -#if defined(EXTRASYSCONFDIR) -#define EXTRA_DRIVERS_SYSCONFDIR_INFO ":" EXTRASYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR -#define EXTRA_ELAYERS_SYSCONFDIR_INFO ":" EXTRASYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR -#define EXTRA_ILAYERS_SYSCONFDIR_INFO ":" EXTRASYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR -#else -#define EXTRA_DRIVERS_SYSCONFDIR_INFO -#define EXTRA_ELAYERS_SYSCONFDIR_INFO -#define EXTRA_ILAYERS_SYSCONFDIR_INFO -#endif - -#if defined(EXTRADATADIR) -#define EXTRA_DRIVERS_DATADIR_INFO ":" EXTRADATADIR VULKAN_DIR VULKAN_ICDCONF_DIR -#define EXTRA_ELAYERS_DATADIR_INFO ":" EXTRADATADIR VULKAN_DIR VULKAN_ELAYERCONF_DIR -#define EXTRA_ILAYERS_DATADIR_INFO ":" EXTRADATADIR VULKAN_DIR VULKAN_ILAYERCONF_DIR -#else -#define EXTRA_DRIVERS_DATADIR_INFO -#define EXTRA_ELAYERS_DATADIR_INFO -#define EXTRA_ILAYERS_DATADIR_INFO -#endif - -#define DEFAULT_VK_DRIVERS_INFO \ - SYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR \ - ":" DATADIR VULKAN_DIR VULKAN_ICDCONF_DIR EXTRA_DRIVERS_SYSCONFDIR_INFO EXTRA_DRIVERS_DATADIR_INFO -#define DEFAULT_VK_ELAYERS_INFO \ - SYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR \ - ":" DATADIR VULKAN_DIR VULKAN_ELAYERCONF_DIR EXTRA_ELAYERS_SYSCONFDIR_INFO EXTRA_ELAYERS_DATADIR_INFO -#define DEFAULT_VK_ILAYERS_INFO \ - SYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR \ - ":" DATADIR VULKAN_DIR VULKAN_ILAYERCONF_DIR EXTRA_ILAYERS_SYSCONFDIR_INFO EXTRA_ILAYERS_DATADIR_INFO +#define DEFAULT_VK_DRIVERS_INFO "" +#define DEFAULT_VK_ELAYERS_INFO "" +#define DEFAULT_VK_ILAYERS_INFO "" #define DEFAULT_VK_DRIVERS_PATH "" #if !defined(DEFAULT_VK_LAYERS_PATH) @@ -97,9 +71,9 @@ #endif #define LAYERS_PATH_ENV "VK_LAYER_PATH" -#define HOME_VK_DRIVERS_INFO VULKAN_DIR VULKAN_ICDCONF_DIR -#define HOME_VK_ELAYERS_INFO VULKAN_DIR VULKAN_ELAYERCONF_DIR -#define HOME_VK_ILAYERS_INFO VULKAN_DIR VULKAN_ILAYERCONF_DIR +#define RELATIVE_VK_DRIVERS_INFO VULKAN_DIR VULKAN_ICDCONF_DIR +#define RELATIVE_VK_ELAYERS_INFO VULKAN_DIR VULKAN_ELAYERCONF_DIR +#define RELATIVE_VK_ILAYERS_INFO VULKAN_DIR VULKAN_ILAYERCONF_DIR // C99: #define PRINTF_SIZE_T_SPECIFIER "%zu" @@ -201,9 +175,9 @@ static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_ #define LAYERS_SOURCE_PATH NULL #endif #define LAYERS_PATH_ENV "VK_LAYER_PATH" -#define HOME_VK_DRIVERS_INFO "" -#define HOME_VK_ELAYERS_INFO "" -#define HOME_VK_ILAYERS_INFO "" +#define RELATIVE_VK_DRIVERS_INFO "" +#define RELATIVE_VK_ELAYERS_INFO "" +#define RELATIVE_VK_ILAYERS_INFO "" #define PRINTF_SIZE_T_SPECIFIER "%Iu" // File IO |