summaryrefslogtreecommitdiffstats
path: root/mandocdb.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2016-10-18 14:15:33 +0000
committerIngo Schwarze <schwarze@openbsd.org>2016-10-18 14:15:33 +0000
commit847d2bc41ca817d3ecffb8324642581ebebc4313 (patch)
tree9ac3e91df736f3f03dbc48afeb73fb1084bf84af /mandocdb.c
parent57d53ffecb010493c40c9773b2cf63e4f9a54716 (diff)
downloadmandoc-847d2bc41ca817d3ecffb8324642581ebebc4313.tar.gz
Simplify and correct support for reproducible builds, such that database
entries come in a well-defined order even in the presence of MLINKS. Do this by using the compar() argument of fts_open(3) rather than trying to sort later, which missed some cases. This also shortens the code by a few lines. Diff from Ed Maste <emaste @ FreeBSD>, adapted to our tree and tweaked a bit by me, final version confirmed by Ed.
Diffstat (limited to 'mandocdb.c')
-rw-r--r--mandocdb.c60
1 files changed, 25 insertions, 35 deletions
diff --git a/mandocdb.c b/mandocdb.c
index 60eadc11..f8f91256 100644
--- a/mandocdb.c
+++ b/mandocdb.c
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2016 Ed Maste <emaste@freebsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -84,6 +85,7 @@ struct mpage {
char *arch; /* architecture from file content */
char *title; /* title from file content */
char *desc; /* description from file content */
+ struct mpage *next; /* singly linked list */
struct mlink *mlinks; /* singly linked list */
int name_head_done;
enum form form; /* format from file content */
@@ -118,11 +120,11 @@ static void dbadd_mlink(const struct mlink *mlink);
static void dbprune(struct dba *);
static void dbwrite(struct dba *);
static void filescan(const char *);
+static int fts_compare(const FTSENT **, const FTSENT **);
static void mlink_add(struct mlink *, const struct stat *);
static void mlink_check(struct mpage *, struct mlink *);
static void mlink_free(struct mlink *);
static void mlinks_undupe(struct mpage *);
-int mpages_compare(const void *, const void *);
static void mpages_free(void);
static void mpages_merge(struct dba *, struct mparse *);
static void parse_cat(struct mpage *, int);
@@ -169,6 +171,7 @@ static int write_utf8; /* write UTF-8 output; else ASCII */
static int exitcode; /* to be returned by main */
static enum op op; /* operational mode */
static char basedir[PATH_MAX]; /* current base directory */
+static struct mpage *mpage_head; /* list of distinct manual pages */
static struct ohash mpages; /* table of distinct manual pages */
static struct ohash mlinks; /* table of directory entries */
static struct ohash names; /* table of all names */
@@ -540,6 +543,16 @@ usage:
}
/*
+ * To get a singly linked list in alpha order while inserting entries
+ * at the beginning, process directory entries in reverse alpha order.
+ */
+static int
+fts_compare(const FTSENT **a, const FTSENT **b)
+{
+ return -strcmp((*a)->fts_name, (*b)->fts_name);
+}
+
+/*
* Scan a directory tree rooted at "basedir" for manpages.
* We use fts(), scanning directory parts along the way for clues to our
* section and architecture.
@@ -569,8 +582,8 @@ treescan(void)
argv[0] = ".";
argv[1] = (char *)NULL;
- f = fts_open((char * const *)argv,
- FTS_PHYSICAL | FTS_NOCHDIR, NULL);
+ f = fts_open((char * const *)argv, FTS_PHYSICAL | FTS_NOCHDIR,
+ fts_compare);
if (f == NULL) {
exitcode = (int)MANDOCLEVEL_SYSERR;
say("", "&fts_open");
@@ -936,6 +949,8 @@ mlink_add(struct mlink *mlink, const struct stat *st)
mpage->inodev.st_ino = inodev.st_ino;
mpage->inodev.st_dev = inodev.st_dev;
mpage->form = FORM_NONE;
+ mpage->next = mpage_head;
+ mpage_head = mpage;
ohash_insert(&mpages, slot, mpage);
} else
mlink->next = mpage->mlinks;
@@ -959,20 +974,18 @@ mpages_free(void)
{
struct mpage *mpage;
struct mlink *mlink;
- unsigned int slot;
- mpage = ohash_first(&mpages, &slot);
- while (NULL != mpage) {
- while (NULL != (mlink = mpage->mlinks)) {
+ while ((mpage = mpage_head) != NULL) {
+ while ((mlink = mpage->mlinks) != NULL) {
mpage->mlinks = mlink->next;
mlink_free(mlink);
}
+ mpage_head = mpage->next;
free(mpage->sec);
free(mpage->arch);
free(mpage->title);
free(mpage->desc);
free(mpage);
- mpage = ohash_next(&mpages, &slot);
}
}
@@ -1086,30 +1099,18 @@ mlink_check(struct mpage *mpage, struct mlink *mlink)
static void
mpages_merge(struct dba *dba, struct mparse *mp)
{
- struct mpage **mplist, *mpage, *mpage_dest;
+ struct mpage *mpage, *mpage_dest;
struct mlink *mlink, *mlink_dest;
struct roff_man *man;
char *sodest;
char *cp;
int fd;
- unsigned int ip, npages, pslot;
- npages = ohash_entries(&mpages);
- mplist = mandoc_reallocarray(NULL, npages, sizeof(*mplist));
- ip = 0;
- mpage = ohash_first(&mpages, &pslot);
- while (mpage != NULL) {
+ for (mpage = mpage_head; mpage != NULL; mpage = mpage->next) {
mlinks_undupe(mpage);
- if (mpage->mlinks != NULL)
- mplist[ip++] = mpage;
- mpage = ohash_next(&mpages, &pslot);
- }
- npages = ip;
- qsort(mplist, npages, sizeof(*mplist), mpages_compare);
+ if ((mlink = mpage->mlinks) == NULL)
+ continue;
- for (ip = 0; ip < npages; ip++) {
- mpage = mplist[ip];
- mlink = mpage->mlinks;
name_mask = NAME_MASK;
mandoc_ohash_init(&names, 4, offsetof(struct str, key));
mandoc_ohash_init(&strings, 6, offsetof(struct str, key));
@@ -1218,17 +1219,6 @@ nextpage:
ohash_delete(&strings);
ohash_delete(&names);
}
- free(mplist);
-}
-
-int
-mpages_compare(const void *vp1, const void *vp2)
-{
- const struct mpage *mp1, *mp2;
-
- mp1 = *(const struct mpage **)vp1;
- mp2 = *(const struct mpage **)vp2;
- return strcmp(mp1->mlinks->file, mp2->mlinks->file);
}
static void