+ char path[PATH_MAX], *search_paths, *next, *end;
+ char *get_extensions_name;
+ const struct __DRIextensionRec **extensions = NULL;
+ const struct __DRIextensionRec **(*get_extensions)(void);
+
+ search_paths = NULL;
+ if (geteuid() == getuid() && search_path_vars) {
+ for (int i = 0; search_path_vars[i] != NULL; i++) {
+ search_paths = getenv(search_path_vars[i]);
+ if (search_paths)
+ break;
+ }
+ }
+ if (search_paths == NULL)
+ search_paths = DEFAULT_DRIVER_DIR;
+
+ void *driver = NULL;
+ end = search_paths + strlen(search_paths);
+ for (char *p = search_paths; p < end; p = next + 1) {
+ int len;
+ next = strchr(p, ':');
+ if (next == NULL)
+ next = end;
+
+ len = next - p;
+#if GLX_USE_TLS
+ snprintf(path, sizeof(path), "%.*s/tls/%s_dri.so", len, p, driver_name);
+ driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+#endif
+ if (driver == NULL) {
+ snprintf(path, sizeof(path), "%.*s/%s_dri.so", len, p, driver_name);
+ driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+ if (driver == NULL)
+ log_(_LOADER_DEBUG, "MESA-LOADER: failed to open %s: %s\n",
+ path, dlerror());
+ }
+ /* not need continue to loop all paths once the driver is found */
+ if (driver != NULL)
+ break;
+ }
+
+ if (driver == NULL) {
+ log_(_LOADER_WARNING, "MESA-LOADER: failed to open %s (search paths %s)\n",
+ driver_name, search_paths);
+ *out_driver_handle = NULL;
+ return NULL;
+ }
+
+ log_(_LOADER_DEBUG, "MESA-LOADER: dlopen(%s)\n", path);
+
+ get_extensions_name = loader_get_extensions_name(driver_name);
+ if (get_extensions_name) {
+ get_extensions = dlsym(driver, get_extensions_name);
+ if (get_extensions) {
+ extensions = get_extensions();
+ } else {
+ log_(_LOADER_DEBUG, "MESA-LOADER: driver does not expose %s(): %s\n",
+ get_extensions_name, dlerror());
+ }
+ free(get_extensions_name);
+ }
+
+ if (!extensions)
+ extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS);
+ if (extensions == NULL) {
+ log_(_LOADER_WARNING,
+ "MESA-LOADER: driver exports no extensions (%s)\n", dlerror());
+ dlclose(driver);
+ }
+
+ *out_driver_handle = driver;
+ return extensions;