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.
This commit is contained in:
Xavier Del Campo Romero 2023-10-10 23:53:42 +02:00
parent 91f1a38d5c
commit 1d2ce3f9c2
Signed by: xavi
GPG Key ID: 84FF3612A9BF43F2
1 changed files with 82 additions and 23 deletions

105
page.c
View File

@ -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;