uint file_read_hdr(byte **data, const char *filename, const char *hdr, uint hdrsize, byte flags) { int err; FILE *fd = fopen(filename, "rb"); if(fd == NULL) { err = errno; if(err != ENOENT || !(flags & FILE_FLAG_IGNMISS)) loge(LOG_IO, STR_FILE_OPENERR, filename, strerror(err), err); return 0; } if(fseek(fd, 0L, SEEK_END)) { err = errno; loge(LOG_IO, STR_FILE_EGEN, filename, strerror(err), err); fclose(fd); return 0; } long size = ftell(fd); if(size < 0L) { err = errno; loge(LOG_IO, STR_FILE_EGEN, filename, strerror(err), err); fclose(fd); return 0; } if(fseek(fd, 0L, SEEK_SET)) { err = errno; loge(LOG_IO, STR_FILE_EGEN, filename, strerror(err), err); fclose(fd); return 0; } if(!size) { if(!(flags & FILE_FLAG_IGNEMPTY)) loge(LOG_IO, STR_FILE_EEMPTY, filename); fclose(fd); if((flags & FILE_FLAG_IGNEMPTY) && (flags & FILE_FLAG_STRING)) { *data = mem_alloc(1, MEM_FILE); (*data)[0] = 0; return 1; } return 0; } if(size < hdrsize) { loge(LOG_IO, STR_FILE_ESHORT, filename); fclose(fd); return 0; } *data = mem_alloc(size + ((flags & FILE_FLAG_STRING) ? 1 : 0), MEM_FILE); if(hdrsize > 0) { if(fread(*data, 1, hdrsize, fd) != hdrsize) { err = feof(fd); loge(LOG_IO, err == 0 ? STR_FILE_EIO : STR_FILE_EEOF, filename); fclose(fd); mem_free(*data); return 0; } if(memcmp(*data, hdr, hdrsize) != 0) { loge(LOG_IO, STR_FILE_EMFHDR, filename); fclose(fd); mem_free(*data); return 0; } } if(fread(&((*data)[hdrsize]), 1, size-hdrsize, fd) != size) { err = feof(fd); loge(LOG_IO, err == 0 ? STR_FILE_EIO : STR_FILE_EEOF, filename); fclose(fd); mem_free(*data); return 0; } fclose(fd); if(flags & FILE_FLAG_STRING) (*data)[size] = 0; return size; } byte file_has_ext(const char *file, const char **exts, int n_exts) { int len = strlen(file); int extlen; for(int extidx = 0; extidx < n_exts; extidx++) { extlen = strlen(exts[extidx]); if(len < extlen + 2) continue; if((file[len - (extlen + 1)] == '.') && str_eq_lower(exts[extidx], &file[len - extlen])) return 1; } return 0; } const char **file_list_dir(int *count, const char *path, const char **exts, int n_exts) { DIR *dir; struct dirent *ent; int found = 0; // int extlen; // int extidx; int pos = 0; int plen = strlen(path); char *buf = NULL; uint *idx = NULL; const char *sep = "/"; if(path[plen - 1] == '/') sep = ""; else plen += 1; dir = opendir(path); if(dir) { while(ent = readdir(dir)) { if(ent->d_type == DT_REG) { if(exts && !file_has_ext(ent->d_name, exts, n_exts)) { /* len = strlen(ent->d_name); for(extidx = 0; extidx < n_exts; extidx++) { extlen = strlen(exts[extidx]); if(len < extlen + 2) continue; if((ent->d_name[len - (extlen + 1)] == '.') && str_eq_lower(exts[extidx], &ent->d_name[len - extlen])) break; } if(extidx == n_exts) */ continue; } idx = mem_realloc(idx, (sizeof(uint) * (found + 1)), MEM_FILE); buf = mem_realloc(buf, pos + plen + strlen(ent->d_name) + 1, MEM_FILE); idx[found] = pos; pos += sprintf(&buf[pos], "%s%s%s", path, sep, ent->d_name) + 1; found += 1; } } closedir(dir); } *count = found; if(buf) { char **list = mem_alloc((sizeof(char *) * found) + pos, MEM_FILE); memcpy(&list[found], buf, pos); for(int z = 0; z < found; z++) { list[z] = &((char *)&list[found])[idx[z]]; } mem_free(buf); mem_free(idx); // logd("TMP", "%d ...", found); // for(int z = 0; z < found; z++) { // logd("TMP", "%d -> %s", z, list[z]); // } return (const char **)list; } return NULL; } const char **file_list(int *count, const char *path, const char **exts, int n_exts) { struct stat node; *count = 0; if(stat(path, &node)) return NULL; if(((node.st_mode & S_IFMT) == S_IFREG) && file_has_ext(path, exts, n_exts)) { int len = strlen(path) + 1; char **file = mem_alloc(sizeof(char *) + len, MEM_FILE); file[0] = (char *)&file[1]; memcpy(&file[1], path, len); *count = 1; return (const char**)file; } return ((node.st_mode & S_IFMT) == S_IFDIR) ? file_list_dir(count, path, exts, n_exts) : NULL; }