Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/files.h

163 lines
4.1 KiB
C
Raw Normal View History

2025-09-02 14:43:36 +02:00
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;
}