diff options
Diffstat (limited to 'src/check_mandirs.c')
-rw-r--r-- | src/check_mandirs.c | 275 |
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; |