#include "io.h" #include "utils.h" #include "memory.h" #include #include #include #include StringView path_concat_ss(StringPool *sp, StringView* a, StringView* b) { if(a == NULL) DIE("a must be a valid string!"); if(b == NULL) DIE("b must be a valid string!"); if(a->len <= 0 || b->len <= 0) DIE("a and b must not be empty! (a:%d, b:%d)", a->len, b->len); if(a->buf[a->len - 1] == '/') return string_createcat_ss(sp, a, b); StringView slash = (StringView){.buf = "/", .len = 1}; StringView ts = string_createcat_ss(sp, a, &slash); return string_createcat_ss(sp, &ts, b); } // Utilize DFS for recursive directory search. size_t dir_get_recursive(DirOpContext* doc, StringView* p) { assert(doc != NULL); if(p == NULL) DIE("p cannot be null!"); if(p->len <= 0) DIE("p must not be empty!"); DIR* d = opendir(p->buf); if(d == NULL) DIE("could not open directory!"); size_t count = 0; while(d) { errno = 0; struct dirent* de = readdir(d); if(de == NULL && errno != 0) DIE("failed to read directory: \"%s\"", p); if(de == NULL) break; if(de->d_type != DT_DIR && de->d_type != DT_REG) continue; if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, ".git") == 0) continue; StringView res = (StringView){.buf = de->d_name, strlen(de->d_name)}; StringView fpath = path_concat_ss(doc->sp, p, &res); DirEntry* file = (DirEntry*)arena_alloc(doc->a_f, sizeof(DirEntry)); file->path = fpath; file->type = de->d_type; count++; switch(de->d_type) { case DT_REG: LOG_DEBUG("Added entry: \"%.*s\" to memory location @ %p.", fpath.len, fpath.buf, file); break; case DT_DIR: LOG_DEBUG("Added directory directory entry \"%.*s\" to memory location @ %p. Entering directory...", fpath.len, fpath.buf, file); count += dir_get_recursive(doc, &fpath); break; default: continue; } } LOG_DEBUG("Directory complete: %s", p->buf); closedir(d); return count; }