From 1d2ce3f9c235f0b6524bbedad0b2ff0abb838888 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Tue, 10 Oct 2023 23:53:42 +0200 Subject: [PATCH] List number of files and directories Sometimes, users want to know how many files and/or directories reside on a directory. Now, slcl prints such information below the logout form. --- page.c | 105 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 82 insertions(+), 23 deletions(-) diff --git a/page.c b/page.c index 8cf24de..f3856a9 100644 --- a/page.c +++ b/page.c @@ -48,6 +48,11 @@ #define MAXSIZEFMT "18446744073709551615.0 XiB" #define RM_FORM_ID "rm" +struct element_stats +{ + unsigned long long n_dirs, n_files; +}; + static int prepare_rm_checkbox(struct html_node *const n, const struct stat *const sb, const char *const name) { @@ -334,7 +339,8 @@ end: } static int add_element(struct html_node *const n, const char *const dir, - const char *const res, const char *const name, const bool chbx) + const char *const res, const char *const name, const bool chbx, + struct element_stats *const st) { int ret = -1; enum {RM_CHECKBOX, NAME, SIZE, DATE, SHARE, PREVIEW, COLUMNS}; @@ -364,6 +370,7 @@ static int add_element(struct html_node *const n, const char *const dir, } struct stat sb; + const bool parentdir = !strcmp(name, ".."); if (stat(path.str, &sb)) { @@ -371,7 +378,15 @@ static int add_element(struct html_node *const n, const char *const dir, __func__, path.str, strerror(errno)); goto end; } - else if (chbx && strcmp(name, "..") + else if (st && !parentdir) + { + if (S_ISDIR(sb.st_mode)) + st->n_dirs++; + else if (S_ISREG(sb.st_mode)) + st->n_files++; + } + + if (chbx && !parentdir && prepare_rm_checkbox(td[RM_CHECKBOX], &sb, name)) { fprintf(stderr, "%s: prepare_rm_checkbox failed\n", __func__); @@ -1036,11 +1051,12 @@ end: } static struct html_node *resource_layout(const char *const dir, - const struct page_quota *const q, struct html_node **const table) + const struct page_quota *const q, struct html_node **const body, + struct html_node **const table) { const char *const fdir = dir + strlen("/user"); struct html_node *const html = html_node_alloc("html"), - *ret = NULL, *head, *body, *div; + *ret = NULL, *head, *div; if (!html) { @@ -1052,12 +1068,12 @@ static struct html_node *resource_layout(const char *const dir, fprintf(stderr, "%s: html_node_add_child head failed\n", __func__); goto end; } - else if (!(body = html_node_add_child(html, "body"))) + else if (!(*body = html_node_add_child(html, "body"))) { fprintf(stderr, "%s: html_node_add_child body failed\n", __func__); goto end; } - else if (!(div = html_node_add_child(body, "div"))) + else if (!(div = html_node_add_child(*body, "div"))) { fprintf(stderr, "%s: html_node_add_child div failed\n", __func__); goto end; @@ -1072,41 +1088,36 @@ static struct html_node *resource_layout(const char *const dir, fprintf(stderr, "%s: common_head failed\n", __func__); goto end; } - else if (prepare_search_form(body, fdir)) + else if (prepare_search_form(*body, fdir)) { fprintf(stderr, "%s: prepare_search_form failed\n", __func__); goto end; } - else if (prepare_upload_form(body, fdir)) + else if (prepare_upload_form(*body, fdir)) { fprintf(stderr, "%s: prepare_upload_form failed\n", __func__); goto end; } - else if (prepare_mkdir_form(body, fdir)) + else if (prepare_mkdir_form(*body, fdir)) { fprintf(stderr, "%s: prepare_upload_form failed\n", __func__); goto end; } - else if (prepare_rm_form(body, fdir)) + else if (prepare_rm_form(*body, fdir)) { fprintf(stderr, "%s: prepare_upload_form failed\n", __func__); goto end; } - else if (q && prepare_quota_form(body, q)) + else if (q && prepare_quota_form(*body, q)) { fprintf(stderr, "%s: prepare_quota_form failed\n", __func__); goto end; } - else if (prepare_logout_form(body)) + else if (prepare_logout_form(*body)) { fprintf(stderr, "%s: prepare_logout_form failed\n", __func__); goto end; } - else if (prepare_footer(body)) - { - fprintf(stderr, "%s: prepare_footer failed\n", __func__); - goto end; - } ret = html; @@ -1119,7 +1130,8 @@ end: } static int add_elements(const char *const root, const char *const res, - const char *const dir, struct html_node *const table) + const char *const dir, struct html_node *const table, + struct element_stats *const st) { int ret = -1; struct dirent **pde = NULL; @@ -1131,6 +1143,8 @@ static int add_elements(const char *const root, const char *const res, goto end; } + *st = (const struct element_stats){0}; + for (int i = 0; i < n; i++) { const struct dirent *const de = pde[i]; @@ -1139,7 +1153,7 @@ static int add_elements(const char *const root, const char *const res, if (!strcmp(name, ".") || (!strcmp(name, "..") && !strcmp(root, res))) continue; - else if (add_element(table, dir, res, name, true)) + else if (add_element(table, dir, res, name, true, st)) { fprintf(stderr, "%s: add_element failed\n", __func__); goto end; @@ -1157,12 +1171,47 @@ end: return ret; } +static int prepare_element_stats(struct html_node *const n, + const struct element_stats *const st) +{ + int ret = -1; + struct html_node *const p = html_node_add_child(n, "div"); + struct dynstr d; + + dynstr_init(&d); + + if (!p) + { + fprintf(stderr, "%s: html_node_add_child failed\n", __func__); + goto end; + } + else if (dynstr_append(&d, "%llu directories, %llu files", + st->n_dirs, st->n_files)) + { + fprintf(stderr, "%s: dynstr_append failed\n", __func__); + goto end; + } + else if (html_node_set_value(p, d.str)) + { + fprintf(stderr, "%s: html_node_set_value failed\n", __func__); + goto end; + } + + ret = 0; + +end: + dynstr_free(&d); + return ret; +} + + static int list_dir(const struct page_resource *const pr) { int ret = -1; struct dynstr out; - struct html_node *table, - *const html = resource_layout(pr->dir, pr->q, &table); + struct html_node *table, *body, + *const html = resource_layout(pr->dir, pr->q, &body, &table); + struct element_stats st; dynstr_init(&out); @@ -1171,11 +1220,21 @@ static int list_dir(const struct page_resource *const pr) fprintf(stderr, "%s: resource_layout failed\n", __func__); goto end; } - else if (add_elements(pr->root, pr->res, pr->dir, table)) + else if (add_elements(pr->root, pr->res, pr->dir, table, &st)) { fprintf(stderr, "%s: read_elements failed\n", __func__); goto end; } + else if (prepare_element_stats(body, &st)) + { + fprintf(stderr, "%s: prepare_element_stats failed\n", __func__); + goto end; + } + else if (prepare_footer(body)) + { + fprintf(stderr, "%s: prepare_footer failed\n", __func__); + goto end; + } else if (dynstr_append(&out, DOCTYPE_TAG)) { fprintf(stderr, "%s: dynstr_prepend failed\n", __func__); @@ -1757,7 +1816,7 @@ static int add_search_results(struct html_node *const n, { const struct page_search_result *const r = &s->results[i]; - if (add_element(table, "/user/", s->root, r->name, false)) + if (add_element(table, "/user/", s->root, r->name, false, NULL)) { fprintf(stderr, "%s: add_element failed\n", __func__); return -1;