X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/agedu/blobdiff_plain/0313b788487ecaadbe31429ea955fc920d8f6557..6209008bc9868081c17c253886fa20b3bf4b861b:/agedu.c diff --git a/agedu.c b/agedu.c index 68a9799..15b366a 100644 --- a/agedu.c +++ b/agedu.c @@ -24,7 +24,7 @@ #include "du.h" #include "trie.h" #include "index.h" -#include "malloc.h" +#include "alloc.h" #include "html.h" #include "httpd.h" #include "fgetline.h" @@ -66,6 +66,7 @@ struct ctx { struct inclusion_exclusion *inex; int ninex; int crossfs; + int fakeatimes; }; static void dump_line(const char *pathname, const struct trie_file *tf) @@ -102,7 +103,10 @@ static int gotdata(void *vctx, const char *pathname, const struct stat64 *st) return 0; file.size = (unsigned long long)512 * st->st_blocks; - file.atime = st->st_atime; + if (ctx->fakeatimes && S_ISDIR(st->st_mode)) + file.atime = st->st_mtime; + else + file.atime = st->st_atime; /* * Filter based on wildcards. @@ -258,6 +262,10 @@ static void text_query(const void *mappedfile, const char *querydir, * not bother defining logical identifiers for them at all - those * would be automatically generated, since I wouldn't have any * need to specify them manually in another part of the code.) + * + * One other helpful consequence of the enum-based structure here + * is that it causes a compiler error if I accidentally try to + * define the same option (short or long) twice. */ #define OPTHELP(NOVAL, VAL, SHORT, LONG, HELPPFX, HELPARG, HELPLINE, HELPOPT) \ @@ -265,10 +273,10 @@ static void text_query(const void *mappedfile, const char *querydir, HELPPFX("actions") \ VAL(SCAN) SHORT(s) LONG(scan) \ HELPARG("directory") HELPOPT("scan and index a directory") \ - NOVAL(DUMP) SHORT(d) LONG(dump) HELPOPT("dump the index file on stdout") \ + NOVAL(DUMP) SHORT(D) LONG(dump) HELPOPT("dump the index file on stdout") \ VAL(SCANDUMP) SHORT(S) LONG(scan_dump) \ HELPARG("directory") HELPOPT("scan only, generating a dump") \ - NOVAL(LOAD) SHORT(l) LONG(load) \ + NOVAL(LOAD) SHORT(L) LONG(load) \ HELPOPT("load and index a dump file") \ VAL(TEXT) SHORT(t) LONG(text) \ HELPARG("subdir") HELPOPT("print a plain text report on a subdirectory") \ @@ -276,9 +284,11 @@ static void text_query(const void *mappedfile, const char *querydir, HELPARG("subdir") HELPOPT("print an HTML report on a subdirectory") \ NOVAL(HTTPD) SHORT(w) LONG(web) LONG(server) LONG(httpd) \ HELPOPT("serve HTML reports from a temporary web server") \ + NOVAL(REMOVE) SHORT(R) LONG(remove) LONG(delete) LONG(unlink) \ + HELPOPT("remove the index file") \ HELPPFX("options") \ VAL(DATAFILE) SHORT(f) LONG(file) \ - HELPARG("filename") HELPOPT("[all modes] specify index file") \ + HELPARG("filename") HELPOPT("[most modes] specify index file") \ NOVAL(PROGRESS) LONG(progress) LONG(scan_progress) \ HELPOPT("[--scan] report progress on stderr") \ NOVAL(NOPROGRESS) LONG(no_progress) LONG(no_scan_progress) \ @@ -302,7 +312,11 @@ static void text_query(const void *mappedfile, const char *querydir, HELPARG("wildcard") HELPOPT("[--scan] prune files matching pattern") \ VAL(PRUNEPATH) LONG(prune_path) \ HELPARG("wildcard") HELPOPT("[--scan] prune pathnames matching pattern") \ - VAL(TQDEPTH) LONG(depth) LONG(max_depth) LONG(maximum_depth) \ + NOVAL(DIRATIME) LONG(dir_atime) LONG(dir_atimes) \ + HELPOPT("[--scan] keep real atimes on directories") \ + NOVAL(NODIRATIME) LONG(no_dir_atime) LONG(no_dir_atimes) \ + HELPOPT("[--scan] fake atimes on directories") \ + VAL(TQDEPTH) SHORT(d) LONG(depth) LONG(max_depth) LONG(maximum_depth) \ HELPARG("levels") HELPOPT("[--text] recurse to this many levels") \ VAL(MINAGE) SHORT(a) LONG(age) LONG(min_age) LONG(minimum_age) \ HELPARG("age") HELPOPT("[--text] include only files older than this") \ @@ -444,7 +458,7 @@ int main(int argc, char **argv) const struct trie_file *tf; char *filename = PNAME ".dat"; int doing_opts = 1; - enum { TEXT, HTML, SCAN, DUMP, SCANDUMP, LOAD, HTTPD }; + enum { TEXT, HTML, SCAN, DUMP, SCANDUMP, LOAD, HTTPD, REMOVE }; struct action { int mode; char *arg; @@ -462,6 +476,7 @@ int main(int argc, char **argv) int ninex = 0, inexsize = 0; int crossfs = 0; int tqdepth = 1; + int fakediratimes = 1; #ifdef DEBUG_MAD_OPTION_PARSING_MACROS { @@ -677,6 +692,15 @@ int main(int argc, char **argv) actions[nactions].arg = NULL; nactions++; break; + case OPT_REMOVE: + if (nactions >= actionsize) { + actionsize = nactions * 3 / 2 + 16; + actions = sresize(actions, actionsize, struct action); + } + actions[nactions].mode = REMOVE; + actions[nactions].arg = NULL; + nactions++; + break; case OPT_PROGRESS: progress = 2; break; @@ -692,6 +716,12 @@ int main(int argc, char **argv) case OPT_NOCROSSFS: crossfs = 0; break; + case OPT_DIRATIME: + fakediratimes = 0; + break; + case OPT_NODIRATIME: + fakediratimes = 1; + break; case OPT_DATAFILE: filename = optval; break; @@ -893,6 +923,7 @@ int main(int argc, char **argv) ctx->inex = inex; ctx->ninex = ninex; ctx->crossfs = crossfs; + ctx->fakeatimes = fakediratimes; ctx->last_output_update = time(NULL); @@ -954,6 +985,7 @@ int main(int argc, char **argv) p++; c = 0; for (i = 0; i < 2; i++) { + c *= 16; if (*p >= '0' && *p <= '9') c += *p - '0'; else if (*p >= 'A' && *p <= 'F') @@ -973,6 +1005,7 @@ int main(int argc, char **argv) *q = '\0'; triebuild_add(ctx->tb, buf, &tf); sfree(buf); + line++; } } else { du(scandir, gotdata, ctx); @@ -1018,6 +1051,12 @@ int main(int argc, char **argv) return 1; } + if (fakediratimes) { + printf("Faking directory atimes\n"); + trie_fake_dir_atimes(mappedfile); + } + + printf("Building index\n"); ib = indexbuild_new(mappedfile, st.st_size, count); tw = triewalk_new(mappedfile); while ((tf = triewalk_next(tw, NULL)) != NULL) @@ -1160,6 +1199,12 @@ int main(int argc, char **argv) pcfg.oldest = htmloldest; pcfg.newest = htmlnewest; run_httpd(mappedfile, auth, &dcfg, &pcfg); + } else if (mode == REMOVE) { + if (remove(filename) < 0) { + fprintf(stderr, "%s: %s: remove: %s\n", PNAME, filename, + strerror(errno)); + return 1; + } } }