Return list of dirs and files from OPDS request

This commit is contained in:
2026-05-14 21:40:16 +02:00
parent 538cfdafa5
commit 317a4d576b

View File

@@ -25,6 +25,27 @@ static enum MHD_Result send_response(struct MHD_Connection *connection, int stat
return ret;
}
typedef struct {
bool is_dir;
SV name;
} Library_Entry;
typedef struct {
Library_Entry *elems;
size_t count;
size_t capacity;
} Library_Entries;
int compare_library_entries(const void *a, const void *b) {
Library_Entry lea = *(Library_Entry*)a;
Library_Entry leb = *(Library_Entry*)b;
if (lea.is_dir && !leb.is_dir) return -1;
if (!lea.is_dir && leb.is_dir) return 1;
return noh_sv_compare(lea.name, leb.name);
}
static enum MHD_Result handle_opds(struct MHD_Connection *connection, SV url, SV base_path, SV username) {
Noh_String fs_path = {0};
noh_string_append_sv(&fs_path, base_path);
@@ -38,21 +59,49 @@ static enum MHD_Result handle_opds(struct MHD_Connection *connection, SV url, SV
DIR *dir = opendir(fs_path.elems);
if (dir) {
noh_log(NOH_INFO, "Exists.");
Library_Entries list = {0};
noh_arena_save(&temp);
struct dirent *entry = noh_arena_alloc(&temp, sizeof(struct dirent));
while ((entry = readdir(dir)) != NULL) {
(void)entry;
noh_log(NOH_INFO, "Entry..");
SV name = sv(entry->d_name);
int type = entry->d_type;
if (type != DT_DIR && type != DT_REG) continue;
if (noh_sv_eq(name, sv(".")) || noh_sv_eq(name, sv(".."))) continue;
if (type == DT_REG && !noh_sv_ends_with_ci(name, sv(".epub"))) continue;
Library_Entry le = {
.is_dir = type == DT_DIR,
.name = noh_sv_copy_cstr(&temp, entry->d_name),
};
noh_da_append(&list, le);
}
// Sort entries, folders first, then by name.
if (list.count > 1)
qsort(list.elems, list.count, sizeof(list.elems[0]), compare_library_entries);
// Print sorted entries.
Noh_String response = {0};
for (size_t i = 0; i < list.count; i++) {
Library_Entry *le = &list.elems[i];
noh_string_append_cstr(&response,
noh_arena_sprintf(
&temp,
"Entry: %s '"Nsv_Fmt"'.\n", le->is_dir ? "Dir" : "File", Nsv_Arg(le->name)));
}
return send_response(connection, 200, noh_sv_from_string(&response));
noh_da_free(&list);
noh_arena_reset(&temp);
closedir(dir);
} else if (errno == ENOENT) {
closedir(dir);
return send_response(connection, 404, sv("That directory does not exist."));
return send_response(connection, 404, sv(""));
} else {
noh_log(NOH_ERROR, "Opening directory failed.");