From 5b7d9f7b2bd46194a2c1c13ca20ea660492ba50b Mon Sep 17 00:00:00 2001 From: ThoNohT Date: Fri, 15 May 2026 15:18:14 +0200 Subject: [PATCH] Fully implement building entries Including name and full path --- src/main.c | 79 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/src/main.c b/src/main.c index 56c1433..6fd1b78 100644 --- a/src/main.c +++ b/src/main.c @@ -50,11 +50,57 @@ int compare_library_entries(const void *a, const void *b) { return noh_sv_compare(lea.name, leb.name); } +#define build_path(first, ...) build_path_((first), __VA_ARGS__, NULL) +Noh_String build_path_(SV *first, ...) { + va_list args; + SV *elem_ = first; + va_start(args, first); + bool start = true; + Noh_String result = {0}; + + while (elem_ != NULL) { + SV elem = *elem_; + while (elem.count > 0) { + SV component = noh_sv_chop_by_delim(&elem, '/'); + if (noh_sv_eq(component, sv(".."))) continue; + + if (component.count > 0) { + if (start) start = false; else noh_string_append_cstr(&result, "/"); + noh_string_append_sv(&result, component); + } + } + + elem_ = va_arg(args, SV *); + } + va_end(args); + + return result; +} + +SV path_to_name(SV path) { + while (true) { + SV component = noh_sv_chop_by_delim(&path, '/'); + if (path.count == 0) return component; + } +} + +void set_modified_time(Library_Entry *entry) { + struct stat attr; + if (stat(noh_arena_sprintf(&temp, Nsv_Fmt, entry->full_path), &attr) == 0) { + struct tm *timeinfo = localtime(&attr.st_mtime); + entry->modified_at = *timeinfo; + } else { + entry->modified_at = (struct tm){0}; + } +} + /** * Creates a Library entry from a dirent structure. */ bool create_entry(struct dirent *dir_entry, const char *parent_path, Library_Entry *result) { SV name = sv(dir_entry->d_name); + SV parent_path_sv = sv(parent_path); + Noh_String full_path = build_path(&parent_path_sv, &name); int type = dir_entry->d_type; // Check if the entry is relevant. @@ -62,24 +108,17 @@ bool create_entry(struct dirent *dir_entry, const char *parent_path, Library_Ent if (noh_sv_eq(name, sv(".")) || noh_sv_eq(name, sv(".."))) return false; if (type == DT_REG && !noh_sv_ends_with_ci(name, sv(".epub"))) return false; - // Allocate and populate library entry. + // Set entry data. result->is_dir = type == DT_DIR; + result->full_path = noh_sv_from_string(&full_path); result->name = noh_sv_copy_cstr(&temp, dir_entry->d_name); - - // Load modified time. - struct stat attr; - if (stat(noh_arena_sprintf(&temp, "%s/"Nsv_Fmt, parent_path, Nsv_Arg(name)), &attr) == 0) { - struct tm *timeinfo = localtime(&attr.st_mtime); - result->modified_at = *timeinfo; - } else { - result->modified_at = (struct tm){0}; - } + set_modified_time(result); return true; } char *format_library_entry(Library_Entry entry, char time_buffer[80]) { - strftime(time_buffer, 80, "%Y-%m-%d %H:%M:%S", &entry.modified_at); + strftime(time_buffer, 80, "%Y-%m-%d %H.%M.%S", &entry.modified_at); return noh_arena_sprintf( &temp, @@ -121,29 +160,23 @@ static Noh_String create_feed_response(Library_Entry self_path, Library_Entries } 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); - noh_string_append_cstr(&fs_path, "/"); - noh_string_append_sv(&fs_path, username); - noh_string_append_cstr(&fs_path, "/"); - noh_string_append_sv(&fs_path, url); - noh_string_append_null(&fs_path); + noh_arena_save(&temp); + Noh_String fs_path = build_path(&base_path, &username, &url); Library_Entry self_entry = { .is_dir = true, .full_path = noh_sv_from_string(&fs_path), + .name = path_to_name(noh_sv_from_string(&fs_path)), .modified_at = {0}, }; - (void)self_entry; - - noh_log(NOH_INFO, "Physical path: "Nsv_Fmt, Nsv_Arg(self_entry.name)); + set_modified_time(&self_entry); + noh_log(NOH_INFO, "Physical path: "Nsv_Fmt, Nsv_Arg(self_entry.full_path)); DIR *dir = opendir(fs_path.elems); if (dir) { Library_Entries list = {0}; // Build up list of entries. - noh_arena_save(&temp); struct dirent *entry = noh_arena_alloc(&temp, sizeof(struct dirent)); while ((entry = readdir(dir)) != NULL) { Library_Entry result = {0}; @@ -167,10 +200,12 @@ static enum MHD_Result handle_opds(struct MHD_Connection *connection, SV url, SV } else if (errno == ENOENT) { closedir(dir); + noh_arena_reset(&temp); return send_response(connection, 404, sv(""), false); } else { noh_log(NOH_ERROR, "Opening directory failed."); + noh_arena_reset(&temp); return send_response(connection, 500, sv(""), false); } }