]> git.cameronkatri.com Git - mandoc.git/blobdiff - mandocdb.c
Back out lorder, which doesn't seem necessary (?). I think this means all
[mandoc.git] / mandocdb.c
index 1925389a47062e8d7736cf3a23d55f04fe7b7d15..ca5ff1300e137615e10d74ccdba4818c7325cf7f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.15 2011/11/27 23:11:37 schwarze Exp $ */
+/*     $Id: mandocdb.c,v 1.23 2011/12/03 18:47:09 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
-#ifdef __linux__
+#if defined(__linux__)
+# include <endian.h>
 # include <db_185.h>
+#elif defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+# include <db.h>
 #else
 # include <db.h>
 #endif
@@ -97,18 +102,15 @@ static     void              dbt_put(DB *, const char *, DBT *, DBT *);
 static void              hash_put(DB *, const struct buf *, uint64_t);
 static void              hash_reset(DB **);
 static void              index_merge(const struct of *, struct mparse *,
-                               struct buf *, struct buf *,
-                               DB *, DB *, const char *, 
-                               DB *, const char *, int, int,
+                               struct buf *, struct buf *, DB *,
+                               DB *, const char *, DB *, const char *,
                                recno_t, const recno_t *, size_t);
 static void              index_prune(const struct of *, DB *, 
                                const char *, DB *, const char *, 
-                               int, recno_t *, recno_t **, size_t *);
-static void              ofile_argbuild(char *[], int, int, int,
-                               struct of **);
+                               recno_t *, recno_t **, size_t *);
+static void              ofile_argbuild(int, char *[], struct of **);
 static int               ofile_dirbuild(const char *, const char *,
-                               const char *, int, int, int,
-                               struct of **);
+                               const char *, int, struct of **);
 static void              ofile_free(struct of *);
 static void              pformatted(DB *, struct buf *, struct buf *,
                                const struct of *);
@@ -258,6 +260,8 @@ static      const pmdoc_nf    mdocs[MDOC_MAX] = {
 };
 
 static const char       *progname;
+static int               use_all;  /* Use all directories and files. */
+static int               verb;  /* Output verbosity level. */
 
 int
 main(int argc, char *argv[])
@@ -268,9 +272,7 @@ main(int argc, char *argv[])
        const char      *dir;
        char             ibuf[MAXPATHLEN], /* index fname */
                         fbuf[MAXPATHLEN];  /* btree fname */
-       int              verb, /* output verbosity */
-                        use_all, /* use all directories and files */
-                        ch, i, flags;
+       int              ch, i, flags;
        DB              *idx, /* index database */
                        *db, /* keyword database */
                        *hash; /* temporary keyword hashtable */
@@ -377,19 +379,27 @@ main(int argc, char *argv[])
                        printf("%s: Opened\n", ibuf);
                }
 
-               ofile_argbuild(argv, argc, use_all, verb, &of);
+               ofile_argbuild(argc, argv, &of);
                if (NULL == of)
                        goto out;
 
                of = of->first;
 
-               index_prune(of, db, fbuf, idx, ibuf, verb,
+               index_prune(of, db, fbuf, idx, ibuf,
                                &maxrec, &recs, &recsz);
 
-               if (OP_UPDATE == op)
+               /*
+                * Go to the root of the respective manual tree
+                * such that .so links work.  In case of failure,
+                * just prod on, even though .so links won't work.
+                */
+
+               if (OP_UPDATE == op) {
+                       chdir(dir);
                        index_merge(of, mp, &dbuf, &buf, hash,
-                                       db, fbuf, idx, ibuf, use_all,
-                                       verb, maxrec, recs, reccur);
+                                       db, fbuf, idx, ibuf,
+                                       maxrec, recs, reccur);
+               }
 
                goto out;
        }
@@ -450,7 +460,7 @@ main(int argc, char *argv[])
                of = NULL;
 
                if ( ! ofile_dirbuild(dirs.paths[i], NULL, NULL,
-                               0, use_all, verb, &of)) 
+                                       0, &of)) 
                        exit((int)MANDOCLEVEL_SYSERR);
 
                if (NULL == of)
@@ -458,9 +468,15 @@ main(int argc, char *argv[])
 
                of = of->first;
 
+               /*
+                * Go to the root of the respective manual tree
+                * such that .so links work.  In case of failure,
+                * just prod on, even though .so links won't work.
+                */
+
+               chdir(dirs.paths[i]);
                index_merge(of, mp, &dbuf, &buf, hash, db, fbuf,
-                               idx, ibuf, use_all, verb,
-                               maxrec, recs, reccur);
+                               idx, ibuf, maxrec, recs, reccur);
        }
 
 out:
@@ -484,9 +500,8 @@ out:
 
 void
 index_merge(const struct of *of, struct mparse *mp,
-               struct buf *dbuf, struct buf *buf,
-               DB *hash, DB *db, const char *dbf,
-               DB *idx, const char *idxf, int use_all, int verb,
+               struct buf *dbuf, struct buf *buf, DB *hash,
+               DB *db, const char *dbf, DB *idx, const char *idxf,
                recno_t maxrec, const recno_t *recs, size_t reccur)
 {
        recno_t          rec;
@@ -615,18 +630,13 @@ index_merge(const struct of *of, struct mparse *mp,
                 * into the database.
                 */
 
-               vbuf.rec = rec;
+               vbuf.rec = htobe32(rec);
                seq = R_FIRST;
                while (0 == (ch = (*hash->seq)(hash, &key, &val, seq))) {
                        seq = R_NEXT;
-
-                       vbuf.mask = *(uint64_t *)val.data;
+                       vbuf.mask = htobe64(*(uint64_t *)val.data);
                        val.size = sizeof(struct db_val);
                        val.data = &vbuf;
-
-                       if (verb > 1)
-                               printf("%s: Added keyword: %s\n", 
-                                               fn, (char *)key.data);
                        dbt_put(db, dbf, &key, &val);
                }
                if (ch < 0) {
@@ -650,6 +660,7 @@ index_merge(const struct of *of, struct mparse *mp,
 
                if (verb)
                        printf("%s: Added index\n", fn);
+
                dbt_put(idx, idxf, &key, &val);
        }
 }
@@ -662,11 +673,11 @@ index_merge(const struct of *of, struct mparse *mp,
  */
 static void
 index_prune(const struct of *ofile, DB *db, const char *dbf, 
-               DB *idx, const char *idxf, int verb,
+               DB *idx, const char *idxf,
                recno_t *maxrec, recno_t **recs, size_t *recsz)
 {
        const struct of *of;
-       const char      *fn;
+       const char      *fn, *cp;
        struct db_val   *vbuf;
        unsigned         seq, sseq;
        DBT              key, val;
@@ -678,18 +689,32 @@ index_prune(const struct of *ofile, DB *db, const char *dbf,
        while (0 == (ch = (*idx->seq)(idx, &key, &val, seq))) {
                seq = R_NEXT;
                *maxrec = *(recno_t *)key.data;
-               if (0 == val.size) {
-                       if (reccur >= *recsz) {
-                               *recsz += MANDOC_SLOP;
-                               *recs = mandoc_realloc(*recs, 
-                                       *recsz * sizeof(recno_t));
-                       }
-                       (*recs)[(int)reccur] = *maxrec;
-                       reccur++;
-                       continue;
-               }
+               cp = val.data;
+
+               /* Deleted records are zero-sized.  Skip them. */
+
+               if (0 == val.size)
+                       goto cont;
+
+               /*
+                * Make sure we're sane.
+                * Read past our mdoc/man/cat type to the next string,
+                * then make sure it's bounded by a NUL.
+                * Failing any of these, we go into our error handler.
+                */
+
+               if (NULL == (fn = memchr(cp, '\0', val.size)))
+                       break;
+               if (++fn - cp >= (int)val.size)
+                       break;
+               if (NULL == memchr(fn, '\0', val.size - (fn - cp)))
+                       break;
+
+               /* 
+                * Search for the file in those we care about.
+                * XXX: build this into a tree.  Too slow.
+                */
 
-               fn = (char *)val.data;
                for (of = ofile; of; of = of->next)
                        if (0 == strcmp(fn, of->fname))
                                break;
@@ -697,23 +722,31 @@ index_prune(const struct of *ofile, DB *db, const char *dbf,
                if (NULL == of)
                        continue;
 
+               /*
+                * Search through the keyword database, throwing out all
+                * references to our file.
+                */
+
                sseq = R_FIRST;
                while (0 == (ch = (*db->seq)(db, &key, &val, sseq))) {
                        sseq = R_NEXT;
-                       assert(sizeof(struct db_val) == val.size);
+                       if (sizeof(struct db_val) != val.size)
+                               break;
+
                        vbuf = val.data;
-                       if (*maxrec != vbuf->rec)
+                       if (*maxrec != betoh32(vbuf->rec))
                                continue;
-                       if (verb)
-                               printf("%s: Deleted keyword: %s\n", 
-                                               fn, (char *)key.data);
-                       ch = (*db->del)(db, &key, R_CURSOR);
-                       if (ch < 0)
+
+                       if ((ch = (*db->del)(db, &key, R_CURSOR)) < 0)
                                break;
                }
+
                if (ch < 0) {
                        perror(dbf);
                        exit((int)MANDOCLEVEL_SYSERR);
+               } else if (1 != ch) {
+                       fprintf(stderr, "%s: Corrupt database\n", dbf);
+                       exit((int)MANDOCLEVEL_SYSERR);
                }
 
                if (verb)
@@ -721,11 +754,10 @@ index_prune(const struct of *ofile, DB *db, const char *dbf,
 
                val.size = 0;
                ch = (*idx->put)(idx, &key, &val, R_CURSOR);
-               if (ch < 0) {
-                       perror(idxf);
-                       exit((int)MANDOCLEVEL_SYSERR);
-               }
 
+               if (ch < 0)
+                       break;
+cont:
                if (reccur >= *recsz) {
                        *recsz += MANDOC_SLOP;
                        *recs = mandoc_realloc
@@ -735,6 +767,15 @@ index_prune(const struct of *ofile, DB *db, const char *dbf,
                (*recs)[(int)reccur] = *maxrec;
                reccur++;
        }
+
+       if (ch < 0) {
+               perror(idxf);
+               exit((int)MANDOCLEVEL_SYSERR);
+       } else if (1 != ch) {
+               fprintf(stderr, "%s: Corrupt index\n", idxf);
+               exit((int)MANDOCLEVEL_SYSERR);
+       }
+
        (*maxrec)++;
 }
 
@@ -1336,8 +1377,7 @@ pformatted(DB *hash, struct buf *buf, struct buf *dbuf,
 }
 
 static void
-ofile_argbuild(char *argv[], int argc, int use_all, int verb,
-               struct of **of)
+ofile_argbuild(int argc, char *argv[], struct of **of)
 {
        char             buf[MAXPATHLEN];
        char            *sec, *arch, *title, *p;
@@ -1429,7 +1469,7 @@ ofile_argbuild(char *argv[], int argc, int use_all, int verb,
  */
 static int
 ofile_dirbuild(const char *dir, const char* psec, const char *parch,
-               int p_src_form, int use_all, int verb, struct of **of)
+               int p_src_form, struct of **of)
 {
        char             buf[MAXPATHLEN];
        struct stat      sb;
@@ -1495,7 +1535,7 @@ ofile_dirbuild(const char *dir, const char* psec, const char *parch,
                                printf("%s: Scanning\n", buf);
 
                        if ( ! ofile_dirbuild(buf, sec, arch,
-                                       src_form, use_all, verb, of))
+                                       src_form, of))
                                return(0);
                }
                if (DT_REG != dp->d_type ||