/* * handle an mmaped file. */ static int apprentice_compile(RMagic *ms, struct r_magic **magicp, ut32 *nmagicp, const char *fn) { int fd; char *dbname; int rv = -1; dbname = mkdbname(fn, 1); if (!dbname) goto out; if ((fd = r_sandbox_open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) { file_error(ms, errno, "cannot open `%s'", dbname); goto out; } if (write(fd, ar, sizeof (ar)) != (ssize_t)sizeof (ar)) { file_error(ms, errno, "error writing `%s'", dbname); goto beach; } if (lseek(fd, (off_t)sizeof (struct r_magic), SEEK_SET) != sizeof (struct r_magic)) { file_error(ms, errno, "error seeking `%s'", dbname); goto beach; } if (write(fd, *magicp, (sizeof (struct r_magic) * *nmagicp)) != (ssize_t)(sizeof (struct r_magic) * *nmagicp)) { file_error(ms, errno, "error writing `%s'", dbname); goto beach; } rv = 0; beach: (void)close(fd); out: free(dbname); return rv; }
/* * handle a compiled file. */ static int apprentice_map(RMagic *ms, struct r_magic **magicp, ut32 *nmagicp, const char *fn) { int fd; struct stat st; ut32 *ptr; ut32 version; int needsbyteswap; char *dbname = NULL; void *mm = NULL; dbname = mkdbname (fn, 0); if (!dbname) goto error2; if ((fd = r_sandbox_open (dbname, O_RDONLY|O_BINARY, 0)) == -1) goto error2; if (fstat(fd, &st) == -1) { file_error (ms, errno, "cannot stat `%s'", dbname); goto error1; } if (st.st_size < 8) { file_error (ms, 0, "file `%s' is too small", dbname); goto error1; } #ifdef QUICK if ((mm = mmap (0, (size_t)st.st_size, PROT_READ, //OPENBSDBUG |PROT_WRITE, MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) { file_error (ms, errno, "cannot map `%s'"); //, dbname); goto error1; } #define RET 2 #else if (!(mm = malloc ((size_t)st.st_size))) { file_oomem(ms, (size_t)st.st_size); goto error1; } if (read (fd, mm, (size_t)st.st_size) != (size_t)st.st_size) { file_badread(ms); goto error1; } #define RET 1 #endif *magicp = mm; (void)close (fd); fd = -1; ptr = (ut32 *)(void *)*magicp; if (*ptr != MAGICNO) { if (swap4(*ptr) != MAGICNO) { //OPENBSDBUG file_error(ms, 0, "bad magic in `%s'"); file_error(ms, 0, "bad magic in `%s'", dbname); goto error1; } needsbyteswap = 1; } else needsbyteswap = 0; version = needsbyteswap? swap4(ptr[1]): ptr[1]; if (version != VERSIONNO) { file_error(ms, 0, "File %d.%d supports only %d version magic " "files. `%s' is version %d", FILE_VERSION_MAJOR, patchlevel, VERSIONNO, dbname, version); goto error1; } *nmagicp = (ut32)(st.st_size / sizeof (struct r_magic)); if (*nmagicp > 0) (*nmagicp)--; (*magicp)++; if (needsbyteswap) byteswap (*magicp, *nmagicp); free (dbname); return RET; error1: if (fd != -1) (void)close (fd); if (mm) { #ifdef QUICK (void)munmap((void *)mm, (size_t)st.st_size); #else free(mm); #endif } else { *magicp = NULL; *nmagicp = 0; } error2: free (dbname); return -1; }
/* scan for the page, print any matches */ static void do_apropos (MYDBM_FILE dbf, const char * const *pages, int num_pages, int *found) { datum key, cont; char **lowpages; int *found_here; int (*combine) (int, int *); int i; #ifndef BTREE datum nextkey; #else /* BTREE */ int end; #endif /* !BTREE */ lowpages = XNMALLOC (num_pages, char *); for (i = 0; i < num_pages; ++i) { lowpages[i] = lower (pages[i]); debug ("lower(%s) = \"%s\"\n", pages[i], lowpages[i]); } found_here = XNMALLOC (num_pages, int); combine = require_all ? all_set : any_set; #ifndef BTREE key = MYDBM_FIRSTKEY (dbf); while (MYDBM_DPTR (key)) { cont = MYDBM_FETCH (dbf, key); #else /* BTREE */ end = btree_nextkeydata (dbf, &key, &cont); while (!end) { #endif /* !BTREE */ char *tab; struct mandata info; memset (&info, 0, sizeof (info)); /* bug#4372, NULL pointer dereference in MYDBM_DPTR (cont), * fix by [email protected] (J.H.M.Dassen), thanx Ray. * cjwatson: In that case, complain and exit, otherwise we * might loop (bug #95052). */ if (!MYDBM_DPTR (cont)) { debug ("key was %s\n", MYDBM_DPTR (key)); error (FATAL, 0, _("Database %s corrupted; rebuild with " "mandb --create"), database); } if (*MYDBM_DPTR (key) == '$') goto nextpage; if (*MYDBM_DPTR (cont) == '\t') goto nextpage; /* a real page */ split_content (MYDBM_DPTR (cont), &info); /* If there are sections given, does any of them match * either the section or extension of this page? */ if (sections) { char * const *section; int matched = 0; for (section = sections; *section; ++section) { if (STREQ (*section, info.sec) || STREQ (*section, info.ext)) { matched = 1; break; } } if (!matched) goto nextpage; } tab = strrchr (MYDBM_DPTR (key), '\t'); if (tab) *tab = '\0'; memset (found_here, 0, num_pages * sizeof (*found_here)); if (am_apropos) { char *whatis; parse_name ((const char **) lowpages, num_pages, MYDBM_DPTR (key), found, found_here); whatis = info.whatis ? xstrdup (info.whatis) : NULL; if (!combine (num_pages, found_here) && whatis) parse_whatis (pages, lowpages, num_pages, whatis, found, found_here); free (whatis); } else parse_name (pages, num_pages, MYDBM_DPTR (key), found, found_here); if (combine (num_pages, found_here)) display (dbf, &info, MYDBM_DPTR (key)); if (tab) *tab = '\t'; nextpage: #ifndef BTREE nextkey = MYDBM_NEXTKEY (dbf, key); MYDBM_FREE_DPTR (cont); MYDBM_FREE_DPTR (key); key = nextkey; #else /* BTREE */ MYDBM_FREE_DPTR (cont); MYDBM_FREE_DPTR (key); end = btree_nextkeydata (dbf, &key, &cont); #endif /* !BTREE */ info.addr = NULL; /* == MYDBM_DPTR (cont), freed above */ free_mandata_elements (&info); } for (i = 0; i < num_pages; ++i) free (lowpages[i]); free (lowpages); } /* loop through the man paths, searching for a match */ static int search (const char * const *pages, int num_pages) { int *found = XCALLOC (num_pages, int); char *catpath, **mp; int any_found, i; for (mp = manpathlist; *mp; mp++) { MYDBM_FILE dbf; catpath = get_catpath (*mp, SYSTEM_CAT | USER_CAT); if (catpath) { database = mkdbname (catpath); free (catpath); } else database = mkdbname (*mp); debug ("path=%s\n", *mp); dbf = MYDBM_RDOPEN (database); if (dbf && dbver_rd (dbf)) { MYDBM_CLOSE (dbf); dbf = NULL; } if (!dbf) { use_grep (pages, num_pages, *mp, found); continue; } if (am_apropos) do_apropos (dbf, pages, num_pages, found); else { if (regex_opt || wildcard) do_apropos (dbf, pages, num_pages, found); else do_whatis (dbf, pages, num_pages, *mp, found); } free (database); database = NULL; MYDBM_CLOSE (dbf); } chkr_garbage_detector (); any_found = 0; for (i = 0; i < num_pages; ++i) { if (found[i]) any_found = 1; else fprintf (stderr, _("%s: nothing appropriate.\n"), pages[i]); } free (found); return any_found; }