static char * FindModule(const char *module, const char *dirname, const char **subdirlist, PatternPtr patterns) { char buf[PATH_MAX + 1]; char *name = NULL; const char **subdirs = NULL; const char **s; if (strlen(dirname) > PATH_MAX) return NULL; subdirs = InitSubdirs(subdirlist); if (!subdirs) return NULL; for (s = subdirs; *s; s++) { if ((strlen(dirname) + strlen(*s)) > PATH_MAX) continue; strcpy(buf, dirname); strcat(buf, *s); if ((name = FindModuleInSubdir(buf, module))) break; } FreeSubdirs(subdirs); return name; }
static char * FindModuleInSubdir(const char *dirpath, const char *module) { struct dirent *direntry = NULL; DIR *dir = NULL; char *ret = NULL, tmpBuf[PATH_MAX]; struct stat stat_buf; dir = opendir(dirpath); if (!dir) return NULL; while ((direntry = readdir(dir))) { if (direntry->d_name[0] == '.') continue; snprintf(tmpBuf, PATH_MAX, "%s%s/", dirpath, direntry->d_name); /* the stat with the appended / fails for normal files, and works for sub dirs fine, looks a bit strange in strace but does seem to work */ if ((stat(tmpBuf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) { if ((ret = FindModuleInSubdir(tmpBuf, module))) break; continue; } snprintf(tmpBuf, PATH_MAX, "lib%s.so", module); if (strcmp(direntry->d_name, tmpBuf) == 0) { if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1) ret = NULL; break; } snprintf(tmpBuf, PATH_MAX, "%s_drv.so", module); if (strcmp(direntry->d_name, tmpBuf) == 0) { if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1) ret = NULL; break; } snprintf(tmpBuf, PATH_MAX, "%s.so", module); if (strcmp(direntry->d_name, tmpBuf) == 0) { if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1) ret = NULL; break; } } closedir(dir); return ret; }