162 lines
4.1 KiB
C
162 lines
4.1 KiB
C
|
|
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;
|
|
}
|