+ /*
+ * If prevbuf was a directory name and buf is
+ * something inside that directory, then
+ * trie_before() will be called on prevbuf
+ * itself. Hence we must drop a tag before it,
+ * so that the resulting index is usable.
+ */
+ if ((!prevbuf[i] && (buf[i] == pathsep ||
+ (i > 0 && buf[i-1] == pathsep))))
+ indexbuild_tag(ib);
+
+ /*
+ * Add prevtf to the index.
+ */
+ indexbuild_add(ib, prevtf);
+
+ if (!tf) {
+ /*
+ * Drop an unconditional final tag, and
+ * get out of this loop.
+ */
+ indexbuild_tag(ib);
+ break;
+ }
+
+ /*
+ * If prevbuf was a filename inside some
+ * directory which buf is outside, then
+ * trie_before() will be called on some
+ * pathname either equal to buf or epsilon
+ * less than it. Either way, we're going to
+ * need to drop a tag after prevtf.
+ */
+ if (strchr(prevbuf+i, pathsep) || !tf)
+ indexbuild_tag(ib);
+ }
+
+ triewalk_free(tw);
+ realsize = indexbuild_realsize(ib);
+ indexbuild_free(ib);
+
+ munmap(mappedfile, totalsize);
+ ftruncate(fd, realsize);
+ close(fd);
+ printf("Final index file size = %llu bytes\n",
+ (unsigned long long)realsize);
+ }
+ } else if (mode == TEXT) {
+ char *querydir = actions[action].arg;
+ size_t pathlen;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: open: %s\n", PNAME, filename,
+ strerror(errno));
+ return 1;
+ }
+ if (fstat(fd, &st) < 0) {
+ perror(PNAME ": fstat");
+ return 1;
+ }
+ totalsize = st.st_size;
+ mappedfile = mmap(NULL, totalsize, PROT_READ, MAP_SHARED, fd, 0);
+ if (!mappedfile) {
+ perror(PNAME ": mmap");
+ return 1;
+ }
+ pathsep = trie_pathsep(mappedfile);
+
+ /*
+ * Trim trailing slash, just in case.
+ */
+ pathlen = strlen(querydir);
+ if (pathlen > 0 && querydir[pathlen-1] == pathsep)
+ querydir[--pathlen] = '\0';
+
+ text_query(mappedfile, querydir, textcutoff, showfiles, tqdepth);
+
+ munmap(mappedfile, totalsize);
+ } else if (mode == HTML) {
+ char *querydir = actions[action].arg;
+ size_t pathlen, maxpathlen;
+ char *pathbuf;
+ struct html_config cfg;
+ unsigned long xi;
+ char *html;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: open: %s\n", PNAME, filename,
+ strerror(errno));
+ return 1;
+ }
+ if (fstat(fd, &st) < 0) {
+ perror(PNAME ": fstat");
+ return 1;
+ }
+ totalsize = st.st_size;
+ mappedfile = mmap(NULL, totalsize, PROT_READ, MAP_SHARED, fd, 0);
+ if (!mappedfile) {
+ perror(PNAME ": mmap");
+ return 1;
+ }
+ pathsep = trie_pathsep(mappedfile);
+
+ maxpathlen = trie_maxpathlen(mappedfile);
+ pathbuf = snewn(maxpathlen, char);
+
+ /*
+ * Trim trailing slash, just in case.
+ */
+ pathlen = strlen(querydir);
+ if (pathlen > 0 && querydir[pathlen-1] == pathsep)
+ querydir[--pathlen] = '\0';
+
+ xi = trie_before(mappedfile, querydir);
+ if (xi >= trie_count(mappedfile) ||
+ (trie_getpath(mappedfile, xi, pathbuf),
+ strcmp(pathbuf, querydir))) {
+ fprintf(stderr, "%s: pathname '%s' does not exist in index\n"
+ "%*s(check it is spelled exactly as it is in the "
+ "index, including\n%*sany leading './')\n",
+ PNAME, querydir,
+ (int)(1+sizeof(PNAME)), "",
+ (int)(1+sizeof(PNAME)), "");
+ } else if (!index_has_root(mappedfile, xi)) {
+ fprintf(stderr, "%s: pathname '%s' is"
+ " a file, not a directory\n", PNAME, querydir);
+ } else {
+ cfg.format = NULL;
+ cfg.autoage = htmlautoagerange;
+ cfg.oldest = htmloldest;
+ cfg.newest = htmlnewest;
+ cfg.showfiles = showfiles;
+ html = html_query(mappedfile, xi, &cfg);
+ fputs(html, stdout);
+ }