static void *copy_info(const char *name, const LPWIN32_FIND_DATAA data) { time_t ctime = file_time_to_unix(&data->ftCreationTime); time_t mtime = file_time_to_unix(&data->ftLastWriteTime); return FS_CopyInfo(name, data->nFileSizeLow, ctime, mtime); }
/* ================= Sys_ListFiles_r Internal function to filesystem. Conventions apply: - files should hold at least MAX_LISTED_FILES - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1] - depth must be 0 on the first call ================= */ void Sys_ListFiles_r(const char *path, const char *filter, unsigned flags, size_t baselen, int *count_p, void **files, int depth) { struct dirent *ent; DIR *dir; struct stat st; char fullpath[MAX_OSPATH]; char *name; size_t len; void *info; if ((dir = opendir(path)) == NULL) { return; } while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') { continue; // ignore dotfiles } len = Q_concat(fullpath, sizeof(fullpath), path, "/", ent->d_name, NULL); if (len >= sizeof(fullpath)) { continue; } st.st_mode = 0; #ifdef _DIRENT_HAVE_D_TYPE // try to avoid stat() if possible if (!(flags & FS_SEARCH_EXTRAINFO) && ent->d_type != DT_UNKNOWN && ent->d_type != DT_LNK) { st.st_mode = DTTOIF(ent->d_type); } #endif if (st.st_mode == 0 && stat(fullpath, &st) == -1) { continue; } // pattern search implies recursive search if ((flags & FS_SEARCH_BYFILTER) && S_ISDIR(st.st_mode) && depth < MAX_LISTED_DEPTH) { Sys_ListFiles_r(fullpath, filter, flags, baselen, count_p, files, depth + 1); // re-check count if (*count_p >= MAX_LISTED_FILES) { break; } } // check type if (flags & FS_SEARCH_DIRSONLY) { if (!S_ISDIR(st.st_mode)) { continue; } } else { if (!S_ISREG(st.st_mode)) { continue; } } // check filter if (filter) { if (flags & FS_SEARCH_BYFILTER) { if (!FS_WildCmp(filter, fullpath + baselen)) { continue; } } else { if (!FS_ExtCmp(filter, ent->d_name)) { continue; } } } // strip path if (flags & FS_SEARCH_SAVEPATH) { name = fullpath + baselen; } else { name = ent->d_name; } // strip extension if (flags & FS_SEARCH_STRIPEXT) { *COM_FileExtension(name) = 0; if (!*name) { continue; } } // copy info off if (flags & FS_SEARCH_EXTRAINFO) { info = FS_CopyInfo(name, st.st_size, st.st_ctime, st.st_mtime); } else { info = FS_CopyString(name); } files[(*count_p)++] = info; if (*count_p >= MAX_LISTED_FILES) { break; } } closedir(dir); }