=================================================================== RCS file: /cvs/mandoc/mandocdb.c,v retrieving revision 1.15 retrieving revision 1.18 diff -u -p -r1.15 -r1.18 --- mandoc/mandocdb.c 2011/11/27 23:11:37 1.15 +++ mandoc/mandocdb.c 2011/12/01 21:05:49 1.18 @@ -1,4 +1,4 @@ -/* $Id: mandocdb.c,v 1.15 2011/11/27 23:11:37 schwarze Exp $ */ +/* $Id: mandocdb.c,v 1.18 2011/12/01 21:05:49 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef __linux__ # include @@ -97,18 +98,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 +256,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 +268,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 +375,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 +456,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 +464,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 +496,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; @@ -624,9 +635,6 @@ index_merge(const struct of *of, struct mparse *mp, 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 +658,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 +671,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 +687,32 @@ index_prune(const struct of *ofile, DB *db, const char 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; - fn = (char *)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. + */ + for (of = ofile; of; of = of->next) if (0 == strcmp(fn, of->fname)) break; @@ -697,23 +720,31 @@ index_prune(const struct of *ofile, DB *db, const char 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) 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 +752,10 @@ index_prune(const struct of *ofile, DB *db, const char 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 +765,15 @@ index_prune(const struct of *ofile, DB *db, const char (*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 +1375,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 +1467,7 @@ ofile_argbuild(char *argv[], int argc, int use_all, in */ 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 +1533,7 @@ ofile_dirbuild(const char *dir, const char* psec, cons 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 ||