Add the --files option, to list individual files in the various
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 29 Jun 2009 18:05:02 +0000 (18:05 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Mon, 29 Jun 2009 18:05:02 +0000 (18:05 +0000)
reporting modes.

git-svn-id: svn://svn.tartarus.org/sgt/agedu@8604 cda61777-01e9-0310-a592-d414129be87e

agedu.but
agedu.c
html.c
html.h
trie.c
trie.h

index 8ef9264..3fc1a23 100644 (file)
--- a/agedu.but
+++ b/agedu.but
@@ -457,6 +457,16 @@ things as disused when they're not, so you will have more candidates
 to go through by hand looking for data you don't need), but may be
 better than nothing if your last-access times are unhelpful.
 
+The following option affects all the modes that generate reports:
+the web server mode \cw{-w}, the stand-alone HTML generation mode
+\cw{-H} and the text report mode \cw{-t}.
+
+\dt \cw{--files}
+
+\dd This option causes \cw{agedu}'s reports to list the individual
+files in each directory, instead of just giving a combined report
+for everything that's not in a subdirectory.
+
 The following options affect the web server mode \cw{-w}, and in one
 case also the stand-alone HTML generation mode \cw{-H}:
 
diff --git a/agedu.c b/agedu.c
index 7f36956..2b9fcdd 100644 (file)
--- a/agedu.c
+++ b/agedu.c
@@ -159,12 +159,12 @@ static void scan_error(void *vctx, const char *fmt, ...)
 }
 
 static void text_query(const void *mappedfile, const char *querydir,
-                      time_t t, int depth)
+                      time_t t, int showfiles, int depth)
 {
     size_t maxpathlen;
     char *pathbuf;
     unsigned long xi1, xi2;
-    unsigned long long s1, s2;
+    unsigned long long size;
 
     maxpathlen = trie_maxpathlen(mappedfile);
     pathbuf = snewn(maxpathlen + 1, char);
@@ -179,16 +179,32 @@ static void text_query(const void *mappedfile, const char *querydir,
     xi1 = trie_before(mappedfile, querydir);
     xi2 = trie_before(mappedfile, pathbuf);
 
-    if (xi2 - xi1 == 1)
+    if (!showfiles && xi2 - xi1 == 1)
        return;                        /* file, or empty dir => no display */
 
     /*
      * Now do the lookups in the age index.
      */
-    s1 = index_query(mappedfile, xi1, t);
-    s2 = index_query(mappedfile, xi2, t);
+    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(mappedfile, xi1);
+       if (f->atime < t)
+           size = f->size;
+       else
+           size = 0;
+    } else {
+       unsigned long long s1, s2;
+       s1 = index_query(mappedfile, xi1, t);
+       s2 = index_query(mappedfile, xi2, t);
+       size = s2 - s1;
+    }
 
-    if (s1 == s2)
+    if (size == 0)
        return;                        /* no space taken up => no display */
 
     if (depth > 0) {
@@ -199,14 +215,14 @@ static void text_query(const void *mappedfile, const char *querydir,
        xi1++;
        while (xi1 < xi2) {
            trie_getpath(mappedfile, xi1, pathbuf);
-           text_query(mappedfile, pathbuf, t, depth-1);
+           text_query(mappedfile, pathbuf, t, showfiles, depth-1);
            make_successor(pathbuf);
            xi1 = trie_before(mappedfile, pathbuf);
        }
     }
 
     /* Display in units of 1Kb */
-    printf("%-11llu %s\n", (s2 - s1) / 1024, querydir);
+    printf("%-11llu %s\n", (size) / 1024, querydir);
 }
 
 /*
@@ -320,6 +336,8 @@ static void text_query(const void *mappedfile, const char *querydir,
         HELPOPT("[--scan,--load] fake atimes on directories") \
     NOVAL(MTIME) LONG(mtime) \
         HELPOPT("[--scan] use mtime instead of atime") \
+    NOVAL(SHOWFILES) LONG(files) \
+        HELPOPT("[--web,--html,--text] list individual files") \
     VAL(AGERANGE) SHORT(r) LONG(age_range) LONG(range) LONG(ages) \
         HELPARG("age[-age]") HELPOPT("[--web,--html] set limits of colour coding") \
     VAL(SERVERADDR) LONG(address) LONG(addr) LONG(server_address) \
@@ -482,6 +500,7 @@ int main(int argc, char **argv)
     int tqdepth = 1;
     int fakediratimes = 1;
     int mtime = 0;
+    int showfiles = 0;
 
 #ifdef DEBUG_MAD_OPTION_PARSING_MACROS
     {
@@ -732,6 +751,9 @@ int main(int argc, char **argv)
                  case OPT_NODIRATIME:
                    fakediratimes = 1;
                    break;
+                 case OPT_SHOWFILES:
+                   showfiles = 1;
+                   break;
                  case OPT_MTIME:
                    mtime = 1;
                    break;
@@ -1223,7 +1245,7 @@ int main(int argc, char **argv)
            if (pathlen > 0 && querydir[pathlen-1] == pathsep)
                querydir[--pathlen] = '\0';
 
-           text_query(mappedfile, querydir, textcutoff, tqdepth);
+           text_query(mappedfile, querydir, textcutoff, showfiles, tqdepth);
 
            munmap(mappedfile, totalsize);
        } else if (mode == HTML) {
@@ -1280,6 +1302,7 @@ int main(int argc, char **argv)
                cfg.autoage = htmlautoagerange;
                cfg.oldest = htmloldest;
                cfg.newest = htmlnewest;
+               cfg.showfiles = showfiles;
                html = html_query(mappedfile, xi, &cfg);
                fputs(html, stdout);
            }
@@ -1347,6 +1370,7 @@ int main(int argc, char **argv)
            pcfg.autoage = htmlautoagerange;
            pcfg.oldest = htmloldest;
            pcfg.newest = htmlnewest;
+           pcfg.showfiles = showfiles;
            run_httpd(mappedfile, auth, &dcfg, &pcfg);
            munmap(mappedfile, totalsize);
        } else if (mode == REMOVE) {
diff --git a/html.c b/html.c
index 4390668..22cdc17 100644 (file)
--- a/html.c
+++ b/html.c
@@ -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;
 
@@ -313,7 +333,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) {
@@ -542,7 +562,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 +583,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, (xj2 - xj1 > 1), 0,
+                                 path2 + subdirpos, 1);
        for (i = 0; i <= MAXCOLOUR; i++)
            vecs[0]->sizes[i] -= vecs[nvecs]->sizes[i];
        nvecs++;
diff --git a/html.h b/html.h
index 63aacb9..d99af0a 100644 (file)
--- a/html.h
+++ b/html.h
@@ -21,6 +21,12 @@ struct html_config {
      */
     int autoage;
     time_t oldest, newest;
+
+    /*
+     * Specify whether to show individual files as well as
+     * directories in the report.
+     */
+    int showfiles;
 };
 
 /*
diff --git a/trie.c b/trie.c
index 48302db..ad0cd84 100644 (file)
--- a/trie.c
+++ b/trie.c
@@ -593,7 +593,36 @@ void trie_getpath(const void *t, unsigned long n, char *buf)
            assert(i < sw->len);
        }
     }
-}    
+}
+
+const struct trie_file *trie_getfile(const void *t, unsigned long n)
+{
+    const struct trie_header *hdr = NODE(t, 0, trie_header);
+    off_t off = hdr->root;
+
+    while (1) {
+       const struct trie_common *node = NODE(t, off, trie_common);
+       if (node->type == TRIE_LEAF) {
+           const struct trie_leaf *leaf = NODE(t, off, trie_leaf);
+           return &leaf->file;
+       } else if (node->type == TRIE_STRING) {
+           const struct trie_string *st = NODE(t, off, trie_string);
+           off = st->subnode;
+       } else if (node->type == TRIE_SWITCH) {
+           const struct trie_switch *sw = NODE(t, off, trie_switch);
+           int i;
+
+           for (i = 0; i < sw->len; i++) {
+               if (n < sw->sw[i].subcount) {
+                   off = sw->sw[i].subnode;
+                   break;
+               } else
+                   n -= sw->sw[i].subcount;
+           }
+           assert(i < sw->len);
+       }
+    }
+}
 
 unsigned long trie_count(const void *t)
 {
diff --git a/trie.h b/trie.h
index 727d976..ea24ef8 100644 (file)
--- a/trie.h
+++ b/trie.h
@@ -91,6 +91,11 @@ unsigned long trie_before(const void *t, const char *pathname);
 void trie_getpath(const void *t, unsigned long n, char *buf);
 
 /*
+ * Return the trie_file * for the nth entry in the trie.
+ */
+const struct trie_file *trie_getfile(const void *t, unsigned long n);
+
+/*
  * Return the total number of entries in the whole trie.
  */
 unsigned long trie_count(const void *t);