summaryrefslogtreecommitdiff
path: root/src/check_mandirs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/check_mandirs.c')
-rw-r--r--src/check_mandirs.c275
1 files changed, 119 insertions, 156 deletions
diff --git a/src/check_mandirs.c b/src/check_mandirs.c
index 2a7ce412..8ed87d7f 100644
--- a/src/check_mandirs.c
+++ b/src/check_mandirs.c
@@ -62,8 +62,10 @@
#include "manconfig.h"
#include "appendstr.h"
+#include "compression.h"
#include "debug.h"
#include "fatal.h"
+#include "filenames.h"
#include "glcontainers.h"
#include "orderfiles.h"
#include "security.h"
@@ -73,7 +75,6 @@
#include "db_storage.h"
#include "descriptions.h"
-#include "filenames.h"
#include "globbing.h"
#include "lexgrog.h"
#include "manp.h"
@@ -88,7 +89,7 @@ gl_map_t whatis_map = NULL;
struct whatis {
char *whatis;
- gl_list_t trace;
+ char *filters;
};
static void whatis_free (const void *value)
@@ -96,7 +97,7 @@ static void whatis_free (const void *value)
struct whatis *whatis = (struct whatis *) value;
free (whatis->whatis);
- gl_list_free (whatis->trace);
+ free (whatis->filters);
free (whatis);
}
@@ -156,185 +157,150 @@ static bool ensure_db_open (MYDBM_FILE dbf)
void test_manfile (MYDBM_FILE dbf, const char *file, const char *path)
{
char *manpage_base;
- const char *ult;
+ const struct ult_value *ult;
struct lexgrog lg;
- char *manpage;
- struct mandata info, *exists;
+ struct mandata *info, *exists;
+ struct compression *comp;
struct stat buf;
size_t len;
- gl_list_t ult_trace = NULL;
const struct whatis *whatis;
+ debug ("\ntest_manfile: considering %s\n", file);
+
memset (&lg, 0, sizeof (struct lexgrog));
- memset (&info, 0, sizeof (struct mandata));
- manpage = filename_info (file, &info, NULL);
- if (!manpage)
+ info = filename_info (file, quiet < 2);
+ if (!info)
return;
- manpage_base = manpage + strlen (manpage) + 1;
+ manpage_base = info->name; /* steal memory */
+ info->name = NULL;
- len = strlen (manpage) + 1; /* skip over directory name */
- len += strlen (manpage + len) + 1; /* skip over base name */
- len += strlen (manpage + len); /* skip over section ext */
+ comp = comp_info (file, true);
+ if (comp) {
+ len = strlen (comp->stem);
+ free (comp->stem);
+ } else
+ len = strlen (file);
/* to get mtime info */
(void) lstat (file, &buf);
- info.mtime = get_stat_mtime (&buf);
+ info->mtime = get_stat_mtime (&buf);
/* check that our file actually contains some data */
if (buf.st_size == 0) {
/* man-db pre 2.3 place holder ? */
- free (manpage);
+ free_mandata_struct (info);
return;
}
- /* See if we already have it, before going any further. This will
- * save both an ult_src() and a find_name(), amongst other wastes of
- * time.
+ /* Check for multiple pages whose details match except for having
+ * different compression extensions.
*/
- exists = dblookup_exact (dbf, manpage_base, info.ext, true);
+ exists = dblookup_exact (dbf, manpage_base, info->ext, true);
+ if (exists && !STREQ (exists->comp, info->comp ? info->comp : "-")) {
+ char *abs_filename;
- /* Ensure we really have the actual page. Gzip keeps the mtime the
- * same when it compresses, so we have to compare compression
- * extensions as well.
- */
- if (exists) {
- if (strcmp (exists->comp, info.comp ? info.comp : "-") == 0) {
- if (timespec_cmp (exists->mtime, info.mtime) == 0 &&
- exists->id < WHATIS_MAN) {
- free_mandata_struct (exists);
- free (manpage);
- return;
- }
+ /* If the cached file still exists, then we have a collision:
+ * two pages that only differ by compression extension.
+ */
+ abs_filename = make_filename (path, NULL, exists, "man");
+ if (!abs_filename) {
+ if (!opt_test)
+ dbdelete (dbf, manpage_base, exists);
} else {
- char *abs_filename;
-
- /* see if the cached file actually exists. It's
- evident at this point that we have multiple
- comp extensions */
- abs_filename = make_filename (path, NULL,
- exists, "man");
- if (!abs_filename) {
- if (!opt_test)
- dbdelete (dbf, manpage_base, exists);
- } else {
- gripe_multi_extensions (path, exists->sec,
- manpage_base,
- exists->ext);
- free (abs_filename);
- free_mandata_struct (exists);
- free (manpage);
- return;
- }
+ gripe_multi_extensions (path, exists->sec,
+ manpage_base, exists->ext);
+ free (abs_filename);
+ free_mandata_struct (exists);
+ free_mandata_struct (info);
+ return;
}
- free_mandata_struct (exists);
- }
-
- /* Check if it happens to be a symlink/hardlink to something already
- * in our cache. This just does some extra checks to avoid scanning
- * links quite so many times.
- */
- {
- /* Avoid too much noise in debug output */
- bool save_debug = debug_level;
- debug_level = false;
- ult = ult_src (file, path, &buf, SOFT_LINK | HARD_LINK, NULL);
- debug_level = save_debug;
- }
-
- if (!ult) {
- /* already warned about this, don't do so again */
- debug ("test_manfile(): bad link %s\n", file);
- free (manpage);
- return;
}
+ free_mandata_struct (exists);
- if (!whatis_map)
- whatis_map = new_string_map (GL_HASH_MAP, whatis_free);
-
- whatis = gl_map_get (whatis_map, ult);
- if (!whatis) {
- if (!STRNEQ (ult, file, len))
- debug ("\ntest_manfile(): link not in cache:\n"
- " source = %s\n"
- " target = %s\n", file, ult);
- /* Trace the file to its ultimate source, otherwise we'll be
- * looking for whatis info in files containing only '.so
- * manx/foo.x', which will give us an unobtainable whatis
- * for the entry. */
- ult_trace = new_string_list (GL_ARRAY_LIST, true);
- ult = ult_src (file, path, &buf,
- SO_LINK | SOFT_LINK | HARD_LINK, ult_trace);
- }
+ /* Trace the file to its ultimate source, otherwise we'll be
+ * looking for whatis info in files containing only '.so
+ * manx/foo.x', which will give us an unobtainable whatis
+ * for the entry. */
+ ult = ult_src (file, path, &buf, SO_LINK | SOFT_LINK | HARD_LINK);
if (!ult) {
if (quiet < 2)
error (0, 0,
_("warning: %s: bad symlink or ROFF `.so' request"),
file);
- free (manpage);
+ free_mandata_struct (info);
return;
}
pages++; /* pages seen so far */
- if (strncmp (ult, file, len) == 0)
- info.id = ULT_MAN; /* ultimate source file */
+ if (strncmp (ult->path, file, len) == 0)
+ info->id = ULT_MAN; /* ultimate source file */
else
- info.id = SO_MAN; /* .so, sym or hard linked file */
+ info->id = SO_MAN; /* .so, sym or hard linked file */
/* Ok, here goes: Use a hash tree to store the ult_srcs with
* their whatis. Anytime after, check the hash tree, if it's there,
* use it. This saves us a find_name() which is a real hog.
*
- * Use the full path in ult as the hash key so we don't have to
- * clear the hash between calls.
+ * Use the full path in ult->path as the hash key so we don't have
+ * to clear the hash between calls.
*/
- if (whatis)
+ if (!whatis_map)
+ whatis_map = new_string_map (GL_HASH_MAP, whatis_free);
+
+ whatis = gl_map_get (whatis_map, ult->path);
+ if (whatis) {
lg.whatis = whatis->whatis ? xstrdup (whatis->whatis) : NULL;
- else {
+ lg.filters =
+ whatis->filters ? xstrdup (whatis->filters) : NULL;
+ } else {
/* Cache miss; go and get the whatis info in its raw state. */
char *file_base = base_name (file);
struct whatis *new_whatis;
+ if (!STRNEQ (ult->path, file, len))
+ debug ("test_manfile: link not in cache:\n"
+ " source = %s\n"
+ " target = %s\n", file, ult->path);
+
lg.type = MANPAGE;
drop_effective_privs ();
- find_name (ult, file_base, &lg, NULL);
+ find_name (ult->path, file_base, &lg, NULL);
free (file_base);
regain_effective_privs ();
new_whatis = XMALLOC (struct whatis);
new_whatis->whatis = lg.whatis ? xstrdup (lg.whatis) : NULL;
- /* We filled out ult_trace above. */
- new_whatis->trace = ult_trace;
- gl_map_put (whatis_map, xstrdup (ult), new_whatis);
- whatis = new_whatis;
+ new_whatis->filters = lg.filters ? xstrdup (lg.filters) : NULL;
+ gl_map_put (whatis_map, xstrdup (ult->path), new_whatis);
}
debug ("\"%s\"\n", lg.whatis);
/* split up the raw whatis data and store references */
- info.pointer = NULL; /* direct page, so far */
- info.filter = lg.filters;
+ info->pointer = NULL; /* direct page, so far */
+ info->filter = lg.filters;
if (lg.whatis) {
gl_list_t descs = parse_descriptions (manpage_base, lg.whatis);
if (!opt_test)
- store_descriptions (dbf, descs, &info, path,
- manpage_base, whatis->trace);
+ store_descriptions (dbf, descs, info, path,
+ manpage_base, ult->trace);
gl_list_free (descs);
} else if (quiet < 2) {
- (void) stat (ult, &buf);
+ (void) stat (ult->path, &buf);
if (buf.st_size == 0)
error (0, 0, _("warning: %s: ignoring empty file"),
- ult);
+ ult->path);
else
error (0, 0,
_("warning: %s: whatis parse for %s(%s) failed"),
- ult, manpage_base, info.ext);
+ ult->path, manpage_base, info->ext);
}
- free (manpage);
+ free_mandata_struct (info);
free (lg.whatis);
}
@@ -701,7 +667,7 @@ void purge_pointers (MYDBM_FILE dbf, const char *name)
while (MYDBM_DPTR (key) != NULL) {
datum content, nextkey;
- struct mandata entry;
+ struct mandata *entry = NULL;
char *nicekey, *tab;
#pragma GCC diagnostic push
@@ -731,19 +697,20 @@ void purge_pointers (MYDBM_FILE dbf, const char *name)
goto pointers_contentnext;
#pragma GCC diagnostic pop
- split_content (dbf, MYDBM_DPTR (content), &entry);
- if (entry.id != SO_MAN && entry.id != WHATIS_MAN)
+ entry = split_content (dbf, MYDBM_DPTR (content));
+ if (entry->id != SO_MAN && entry->id != WHATIS_MAN)
goto pointers_contentnext;
- if (STREQ (entry.pointer, name)) {
+ if (STREQ (entry->pointer, name)) {
if (!opt_test)
- dbdelete (dbf, nicekey, &entry);
+ dbdelete (dbf, nicekey, entry);
else
debug ("%s(%s): pointer vanished, "
- "would delete\n", nicekey, entry.ext);
+ "would delete\n", nicekey, entry->ext);
}
pointers_contentnext:
+ free_mandata_struct (entry);
free (nicekey);
MYDBM_FREE_DPTR (content);
pointers_next:
@@ -757,18 +724,15 @@ pointers_next:
* (which may return inexact extension matches in some cases). It may turn
* out that this is better handled in look_for_file() itself.
*/
-static int count_glob_matches (const char *name, const char *ext,
- gl_list_t source, struct timespec db_mtime)
+static int count_glob_matches (const char *ext, gl_list_t source,
+ struct timespec db_mtime)
{
const char *walk;
int count = 0;
GL_LIST_FOREACH (source, walk) {
- struct mandata info;
+ struct mandata *info;
struct stat statbuf;
- char *buf;
-
- memset (&info, 0, sizeof (struct mandata));
if (stat (walk, &statbuf) == -1) {
debug ("count_glob_matches: excluding %s "
@@ -782,12 +746,11 @@ static int count_glob_matches (const char *name, const char *ext,
continue;
}
- buf = filename_info (walk, &info, name);
- if (buf) {
- if (STREQ (ext, info.ext))
+ info = filename_info (walk, quiet < 2);
+ if (info) {
+ if (STREQ (ext, info->ext))
++count;
- free (info.name);
- free (buf);
+ free_mandata_struct (info);
}
}
@@ -807,7 +770,7 @@ static int purge_normal (MYDBM_FILE dbf, const char *name,
*/
t.tv_sec = -1;
t.tv_nsec = -1;
- if (count_glob_matches (name, info->ext, found, t))
+ if (count_glob_matches (info->ext, found, t))
return 0;
if (!opt_test)
@@ -820,14 +783,14 @@ static int purge_normal (MYDBM_FILE dbf, const char *name,
}
/* Decide whether to purge a reference to a WHATIS_MAN or WHATIS_CAT page. */
-static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat,
+static int purge_whatis (MYDBM_FILE dbf, const char *path, bool cat,
const char *name, struct mandata *info,
gl_list_t found, struct timespec db_mtime)
{
/* TODO: On some systems, the cat page extension differs from the
* man page extension, so this may be too strict.
*/
- if (count_glob_matches (name, info->ext, found, db_mtime)) {
+ if (count_glob_matches (info->ext, found, db_mtime)) {
/* If the page exists and didn't beforehand, then presumably
* we're about to rescan, which will replace the WHATIS_MAN
* entry with something better. However, there have been
@@ -873,8 +836,7 @@ static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat,
t.tv_sec = -1;
t.tv_nsec = -1;
- count = count_glob_matches (info->pointer, info->ext,
- real_found, t);
+ count = count_glob_matches (info->ext, real_found, t);
gl_list_free (real_found);
if (count)
return 0;
@@ -889,12 +851,12 @@ static int purge_whatis (MYDBM_FILE dbf, const char *path, int cat,
}
/* Check that multi keys are correctly constructed. */
-static int check_multi_key (const char *name, const char *content)
+static bool check_multi_key (const char *name, const char *content)
{
const char *walk, *next;
if (!*content)
- return 0;
+ return false;
for (walk = content; walk && *walk; walk = next) {
/* The name in the multi key should only differ from the
@@ -914,7 +876,7 @@ static int check_multi_key (const char *name, const char *content)
debug ("%s: broken multi key \"%s\", "
"forcing a rescan\n", name, content);
force_rescan = true;
- return 1;
+ return true;
}
/* If the name was valid, skip over the extension and
@@ -924,7 +886,7 @@ static int check_multi_key (const char *name, const char *content)
next = walk ? strchr (walk + 1, '\t') : NULL;
}
- return 0;
+ return false;
}
/* Go through the database and purge references to man pages that no longer
@@ -965,7 +927,7 @@ int purge_missing (MYDBM_FILE dbf, const char *manpath, const char *catpath)
while (MYDBM_DPTR (key) != NULL) {
datum content, nextkey;
- struct mandata entry;
+ struct mandata *entry;
char *nicekey, *tab;
bool save_debug;
gl_list_t found;
@@ -1014,39 +976,40 @@ int purge_missing (MYDBM_FILE dbf, const char *manpath, const char *catpath)
}
#pragma GCC diagnostic pop
- split_content (dbf, MYDBM_DPTR (content), &entry);
+ entry = split_content (dbf, MYDBM_DPTR (content));
save_debug = debug_level;
debug_level = false; /* look_for_file() is quite noisy */
- if (entry.id <= WHATIS_MAN)
- found = look_for_file (manpath, entry.ext,
- entry.name ? entry.name
- : nicekey,
- 0, LFF_MATCHCASE);
+ if (entry->id <= WHATIS_MAN)
+ found = look_for_file (manpath, entry->ext,
+ entry->name ? entry->name
+ : nicekey,
+ false, LFF_MATCHCASE);
else
- found = look_for_file (catpath, entry.ext,
- entry.name ? entry.name
- : nicekey,
- 1, LFF_MATCHCASE);
+ found = look_for_file (catpath, entry->ext,
+ entry->name ? entry->name
+ : nicekey,
+ true, LFF_MATCHCASE);
debug_level = save_debug;
/* Now actually decide whether to purge, depending on the
* type of entry.
*/
- if (entry.id == ULT_MAN || entry.id == SO_MAN ||
- entry.id == STRAY_CAT)
- count += purge_normal (dbf, nicekey, &entry, found);
- else if (entry.id == WHATIS_MAN)
- count += purge_whatis (dbf, manpath, 0, nicekey,
- &entry, found, db_mtime);
- else /* entry.id == WHATIS_CAT */
- count += purge_whatis (dbf, catpath, 1, nicekey,
- &entry, found, db_mtime);
+ if (entry->id == ULT_MAN || entry->id == SO_MAN ||
+ entry->id == STRAY_CAT)
+ count += purge_normal (dbf, nicekey, entry, found);
+ else if (entry->id == WHATIS_MAN)
+ count += purge_whatis (dbf, manpath, false, nicekey,
+ entry, found, db_mtime);
+ else /* entry->id == WHATIS_CAT */
+ count += purge_whatis (dbf, catpath, true, nicekey,
+ entry, found, db_mtime);
gl_list_free (found);
free (nicekey);
- free_mandata_elements (&entry);
+ free_mandata_struct (entry);
+ MYDBM_FREE_DPTR (content);
nextkey = MYDBM_NEXTKEY (dbf, key);
MYDBM_FREE_DPTR (key);
key = nextkey;