X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/agedu/blobdiff_plain/b49db535793898495dc9ee9a05f86c65a2af3190..a8a4d6d837f5029124d26483e4b3a390de69823e:/html.c diff --git a/html.c b/html.c index 4390668..d316d1e 100644 --- a/html.c +++ b/html.c @@ -18,13 +18,13 @@ struct html { char *path2; char *href; size_t hreflen; - const char *format; + const char *format, *rootpage; unsigned long long thresholds[MAXCOLOUR]; char *titletexts[MAXCOLOUR+1]; time_t now; }; -static void vhtprintf(struct html *ctx, char *fmt, va_list ap) +static void vhtprintf(struct html *ctx, const char *fmt, va_list ap) { va_list ap2; int size, size2; @@ -50,7 +50,7 @@ static void vhtprintf(struct html *ctx, char *fmt, va_list ap) ctx->buflen += size; } -static void htprintf(struct html *ctx, char *fmt, ...) +static void htprintf(struct html *ctx, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -176,7 +176,21 @@ static unsigned long long fetch_size(const void *t, unsigned long xi1, unsigned long xi2, unsigned long long atime) { - return index_query(t, xi2, atime) - index_query(t, xi1, atime); + if (xi2 - xi1 == 1) { + /* + * We are querying an individual file, so we should not + * depend on the index entries either side of the node, + * since they almost certainly don't both exist. Instead, + * just look up the file's size and atime in the main trie. + */ + const struct trie_file *f = trie_getfile(t, xi1); + if (f->atime < atime) + return f->size; + else + return 0; + } else { + return index_query(t, xi2, atime) - index_query(t, xi1, atime); + } } static void htescape(struct html *ctx, const char *s, int n, int italics) @@ -235,7 +249,7 @@ static void end_colour_bar(struct html *ctx) } struct vector { - int want_href; + int want_href, essential; char *name; int literal; /* should the name be formatted in fixed-pitch? */ unsigned long index; @@ -261,17 +275,23 @@ int vec_compare(const void *av, const void *bv) return -1; else if (a->index > b->index) return +1; + else if (a->essential < b->essential) + return +1; + else if (a->essential > b->essential) + return -1; return 0; } static struct vector *make_vector(struct html *ctx, char *path, - int want_href, char *name, int literal) + int want_href, int essential, + char *name, int literal) { unsigned long xi1, xi2; struct vector *vec = snew(struct vector); int i; vec->want_href = want_href; + vec->essential = essential; vec->name = name ? dupstr(name) : NULL; vec->literal = literal; @@ -297,12 +317,46 @@ static void print_heading(struct html *ctx, const char *title) "%s\n\n", title); } +static void compute_display_size(unsigned long long size, + const char **fmt, double *display_size) +{ + static const char *const fmts[] = { + "%g b", "%g Kb", "%#.1f Mb", "%#.1f Gb", "%#.1f Tb", + "%#.1f Pb", "%#.1f Eb", "%#.1f Zb", "%#.1f Yb" + }; + int shift = 0; + unsigned long long tmpsize; + double denominator; + + tmpsize = size; + denominator = 1.0; + while (tmpsize >= 1024 && shift < lenof(fmts)-1) { + tmpsize >>= 10; + denominator *= 1024.0; + shift++; + } + *display_size = size / denominator; + *fmt = fmts[shift]; +} + +static void make_filename(char *buf, size_t buflen, + const char *format, const char *rootpage, + unsigned long index) +{ + if (index == 0 && rootpage) + snprintf(buf, buflen, "%s", rootpage); + else + snprintf(buf, buflen, format, index); +} + #define PIXEL_SIZE 600 /* FIXME: configurability? */ static void write_report_line(struct html *ctx, struct vector *vec) { unsigned long long size, asize, divisor; + double display_size; int pix, newpix; int i; + const char *unitsfmt; /* * A line with literally zero space usage should not be @@ -313,7 +367,7 @@ static void write_report_line(struct html *ctx, struct vector *vec) * case we must fiddle about to prevent divisions by zero in * the code below. */ - if (!vec->sizes[MAXCOLOUR] && vec->want_href) + if (!vec->sizes[MAXCOLOUR] && !vec->essential) return; divisor = ctx->totalsize; if (!divisor) { @@ -324,9 +378,11 @@ static void write_report_line(struct html *ctx, struct vector *vec) * Find the total size of this subdirectory. */ size = vec->sizes[MAXCOLOUR]; + compute_display_size(size, &unitsfmt, &display_size); htprintf(ctx, "\n" - "%lluMb\n", - ((size + ((1<<20)-1)) >> 20)); /* convert to Mb, rounding up */ + ""); + htprintf(ctx, unitsfmt, display_size); + htprintf(ctx, "\n"); /* * Generate a colour bar. @@ -358,7 +414,9 @@ static void write_report_line(struct html *ctx, struct vector *vec) int doing_href = 0; if (ctx->format && vec->want_href) { - snprintf(ctx->href, ctx->hreflen, ctx->format, vec->index); + make_filename(ctx->href, ctx->hreflen, + ctx->format, ctx->rootpage, + vec->index); htprintf(ctx, "", ctx->href); doing_href = 1; } @@ -386,7 +444,7 @@ int strcmptrailingpathsep(const char *a, const char *b) } char *html_query(const void *t, unsigned long index, - const struct html_config *cfg) + const struct html_config *cfg, int downlink) { struct html actx, *ctx = &actx; char *path, *path2, *p, *q, *href; @@ -405,6 +463,7 @@ char *html_query(const void *t, unsigned long index, ctx->buflen = ctx->bufsize = 0; ctx->t = t; ctx->format = cfg->format; + ctx->rootpage = cfg->rootpage; htprintf(ctx, "\n"); path = snewn(1+trie_maxpathlen(t), char); @@ -461,7 +520,7 @@ char *html_query(const void *t, unsigned long index, index2 = trie_before(t, path); trie_getpath(t, index2, path2); if (!strcmptrailingpathsep(path, path2) && cfg->format) { - snprintf(href, hreflen, cfg->format, index2); + make_filename(href, hreflen, cfg->format, cfg->rootpage, index2); if (!*href) /* special case that we understand */ strcpy(href, "./"); htprintf(ctx, "", href); @@ -516,7 +575,7 @@ char *html_query(const void *t, unsigned long index, } htprintf(ctx, "

Key to colour coding (mouse over for more detail):\n"); htprintf(ctx, "

"); begin_colour_bar(ctx); htprintf(ctx, "%s\n", agebuf1); for (i = 0; i < MAXCOLOUR; i++) @@ -542,7 +601,7 @@ char *html_query(const void *t, unsigned long index, vecsize = 64; vecs = snewn(vecsize, struct vector *); nvecs = 1; - vecs[0] = make_vector(ctx, path, 0, NULL, 0); + vecs[0] = make_vector(ctx, path, 0, 1, NULL, 0); print_heading(ctx, "Overall"); write_report_line(ctx, vecs[0]); @@ -563,14 +622,15 @@ char *html_query(const void *t, unsigned long index, trie_getpath(t, xi1, path2); get_indices(t, ctx->path2, &xj1, &xj2); xi1 = xj2; - if (xj2 - xj1 <= 1) + if (!cfg->showfiles && xj2 - xj1 <= 1) continue; /* skip individual files */ if (nvecs >= vecsize) { vecsize = nvecs * 3 / 2 + 64; vecs = sresize(vecs, vecsize, struct vector *); } assert(strlen(path2) > pathlen); - vecs[nvecs] = make_vector(ctx, path2, 1, path2 + subdirpos, 1); + vecs[nvecs] = make_vector(ctx, path2, downlink && (xj2 - xj1 > 1), 0, + path2 + subdirpos, 1); for (i = 0; i <= MAXCOLOUR; i++) vecs[0]->sizes[i] -= vecs[nvecs]->sizes[i]; nvecs++; @@ -602,3 +662,68 @@ char *html_query(const void *t, unsigned long index, return ctx->buf; } + +int html_dump(const void *t, unsigned long index, unsigned long endindex, + int maxdepth, const struct html_config *cfg, + const char *pathprefix) +{ + /* + * Determine the filename for this file. + */ + assert(cfg->format != NULL); + int prefixlen = strlen(pathprefix); + int fnmax = strlen(pathprefix) + strlen(cfg->format) + 100; + char filename[fnmax]; + strcpy(filename, pathprefix); + make_filename(filename + prefixlen, fnmax - prefixlen, + cfg->format, cfg->rootpage, index); + + /* + * Create the HTML itself. Don't write out downlinks from our + * deepest level. + */ + char *html = html_query(t, index, cfg, maxdepth != 0); + + /* + * Write it out. + */ + FILE *fp = fopen(filename, "w"); + if (!fp) { + fprintf(stderr, "%s: %s: open: %s\n", PNAME, + filename, strerror(errno)); + return 1; + } + if (fputs(html, fp) < 0) { + fprintf(stderr, "%s: %s: write: %s\n", PNAME, + filename, strerror(errno)); + fclose(fp); + return 1; + } + if (fclose(fp) < 0) { + fprintf(stderr, "%s: %s: fclose: %s\n", PNAME, + filename, strerror(errno)); + return 1; + } + + /* + * Recurse. + */ + if (maxdepth != 0) { + unsigned long subindex, subendindex; + int newdepth = (maxdepth > 0 ? maxdepth - 1 : maxdepth); + char path[1+trie_maxpathlen(t)]; + + index++; + while (index < endindex) { + trie_getpath(t, index, path); + get_indices(t, path, &subindex, &subendindex); + index = subendindex; + if (subendindex - subindex > 1) { + if (html_dump(t, subindex, subendindex, newdepth, + cfg, pathprefix)) + return 1; + } + } + } + return 0; +}