/** * A loader function for use with _eglPreloadForEach. The loader data is the * filename of the driver. This function stops on the first valid driver. */ static EGLBoolean _eglLoaderFile(const char *dir, size_t len, void *loader_data) { char path[1024]; const char *filename = (const char *) loader_data; size_t flen = strlen(filename); /* make a full path */ if (len + flen + 2 > sizeof(path)) return EGL_TRUE; if (len) { memcpy(path, dir, len); path[len++] = '/'; } memcpy(path + len, filename, flen); len += flen; path[len] = '\0'; if (library_suffix()) { const char *suffix = library_suffix(); size_t slen = strlen(suffix); const char *p; EGLBoolean need_suffix; p = filename + flen - slen; need_suffix = (p < filename || strcmp(p, suffix) != 0); if (need_suffix) { /* overflow */ if (len + slen + 1 > sizeof(path)) return EGL_TRUE; strcpy(path + len, suffix); } } #if defined(_EGL_OS_UNIX) /* check if the file exists */ if (access(path, F_OK)) return EGL_TRUE; #endif _eglAddModule(path); return EGL_TRUE; }
/** * A loader function for use with _eglPreloadForEach. The loader data is the * pattern (prefix) of the files to look for. */ static EGLBoolean _eglLoaderPattern(const char *dir, size_t len, void *loader_data) { #if defined(_EGL_OS_UNIX) const char *prefix, *suffix; size_t prefix_len, suffix_len; DIR *dirp; struct dirent *dirent; char path[1024]; if (len + 2 > sizeof(path)) return EGL_TRUE; if (len) { memcpy(path, dir, len); path[len++] = '/'; } path[len] = '\0'; dirp = opendir(path); if (!dirp) return EGL_TRUE; prefix = (const char *) loader_data; prefix_len = strlen(prefix); suffix = library_suffix(); suffix_len = (suffix) ? strlen(suffix) : 0; while ((dirent = readdir(dirp))) { size_t dirent_len = strlen(dirent->d_name); const char *p; /* match the prefix */ if (strncmp(dirent->d_name, prefix, prefix_len) != 0) continue; /* match the suffix */ if (suffix) { p = dirent->d_name + dirent_len - suffix_len; if (p < dirent->d_name || strcmp(p, suffix) != 0) continue; } /* make a full path and add it to the module array */ if (len + dirent_len + 1 <= sizeof(path)) { strcpy(path + len, dirent->d_name); _eglAddModule(path); } } closedir(dirp); return EGL_TRUE; #else /* _EGL_OS_UNIX */ /* stop immediately */ return EGL_FALSE; #endif }
US_BEGIN_NAMESPACE std::vector<std::string> AutoLoadModulesFromPath(const std::string& absoluteBasePath, const std::string& subDir) { std::vector<std::string> loadedModules; std::string loadPath = absoluteBasePath + DIR_SEP + subDir; DIR* dir = opendir(loadPath.c_str()); #ifdef CMAKE_INTDIR // Try intermediate output directories if (dir == NULL) { std::size_t indexOfLastSeparator = absoluteBasePath.find_last_of(DIR_SEP); if (indexOfLastSeparator != std::string::npos) { std::string intermediateDir = absoluteBasePath.substr(indexOfLastSeparator+1); bool equalSubDir = intermediateDir.size() == std::strlen(CMAKE_INTDIR); for (std::size_t i = 0; equalSubDir && i < intermediateDir.size(); ++i) { if (std::tolower(intermediateDir[i]) != std::tolower(CMAKE_INTDIR[i])) { equalSubDir = false; } } if (equalSubDir) { loadPath = absoluteBasePath.substr(0, indexOfLastSeparator+1) + subDir + DIR_SEP + CMAKE_INTDIR; dir = opendir(loadPath.c_str()); } } } #endif if (dir != NULL) { struct dirent *ent = NULL; while ((ent = readdir(dir)) != NULL) { bool loadFile = true; #ifdef _DIRENT_HAVE_D_TYPE if (ent->d_type != DT_UNKNOWN && ent->d_type != DT_REG) { loadFile = false; } #endif std::string entryFileName(ent->d_name); // On Linux, library file names can have version numbers appended. On other platforms, we // check the file ending. This could be refined for Linux in the future. #if !defined(US_PLATFORM_LINUX) if (entryFileName.rfind(library_suffix()) != (entryFileName.size() - library_suffix().size())) { loadFile = false; } #endif if (!loadFile) continue; std::string libPath = loadPath; if (!libPath.empty() && libPath.find_last_of(DIR_SEP) != libPath.size() -1) { libPath += DIR_SEP; } libPath += entryFileName; US_DEBUG << "Auto-loading module " << libPath; if (!load_impl(libPath)) { US_WARN << "Auto-loading of module " << libPath << " failed."; } else { loadedModules.push_back(libPath); } } closedir(dir); } return loadedModules; }