diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2016-10-18 14:15:33 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2016-10-18 14:15:33 +0000 |
commit | 847d2bc41ca817d3ecffb8324642581ebebc4313 (patch) | |
tree | 9ac3e91df736f3f03dbc48afeb73fb1084bf84af /mandocdb.c | |
parent | 57d53ffecb010493c40c9773b2cf63e4f9a54716 (diff) | |
download | mandoc-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.c | 60 |
1 files changed, 25 insertions, 35 deletions
@@ -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 |