Module Name:    src
Committed By:   joerg
Date:           Thu Feb 16 20:58:55 UTC 2012

Modified Files:
        src/usr.sbin/makemandb: Makefile makemandb.c

Log Message:
Add support for compressed man pages in all the usual formats.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/makemandb/Makefile
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/makemandb/makemandb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/makemandb/Makefile
diff -u src/usr.sbin/makemandb/Makefile:1.1 src/usr.sbin/makemandb/Makefile:1.2
--- src/usr.sbin/makemandb/Makefile:1.1	Tue Feb  7 19:13:32 2012
+++ src/usr.sbin/makemandb/Makefile	Thu Feb 16 20:58:55 2012
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.1 2012/02/07 19:13:32 joerg Exp $
+# $NetBSD: Makefile,v 1.2 2012/02/16 20:58:55 joerg Exp $
 
 .include <bsd.own.mk>
 
@@ -22,8 +22,8 @@ CPPFLAGS+=-I${MDIST} -I${.OBJDIR}
 MDOCMLOBJDIR!=	cd ${MDOCDIR}/lib/libmandoc && ${PRINTOBJDIR}
 MDOCMLLIB=	${MDOCMLOBJDIR}/libmandoc.a
 
-DPADD.makemandb+= 	${MDOCMLLIB}
-LDADD.makemandb+= 	-L${MDOCMLOBJDIR} -lmandoc
+DPADD.makemandb+= 	${MDOCMLLIB} ${LIBARCHIVE} ${LIBBZ2} ${LIBLZMA}
+LDADD.makemandb+= 	-L${MDOCMLOBJDIR} -lmandoc -larchive -lbz2 -llzma
 DPADD+=		${LIBSQLITE3} ${LIBM} ${LIBZ} ${LIBUTIL}
 LDADD+=		-lsqlite3 -lm -lz -lutil
 

Index: src/usr.sbin/makemandb/makemandb.c
diff -u src/usr.sbin/makemandb/makemandb.c:1.4 src/usr.sbin/makemandb/makemandb.c:1.5
--- src/usr.sbin/makemandb/makemandb.c:1.4	Wed Feb 15 23:36:10 2012
+++ src/usr.sbin/makemandb/makemandb.c	Thu Feb 16 20:58:55 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: makemandb.c,v 1.4 2012/02/15 23:36:10 joerg Exp $	*/
+/*	$NetBSD: makemandb.c,v 1.5 2012/02/16 20:58:55 joerg Exp $	*/
 /*
  * Copyright (c) 2011 Abhinav Upadhyay <er.abhinav.upadh...@gmail.com>
  * Copyright (c) 2011 Kristaps Dzonsons <krist...@bsd.lv>
@@ -17,7 +17,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: makemandb.c,v 1.4 2012/02/15 23:36:10 joerg Exp $");
+__RCSID("$NetBSD: makemandb.c,v 1.5 2012/02/16 20:58:55 joerg Exp $");
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -26,6 +26,7 @@ __RCSID("$NetBSD: makemandb.c,v 1.4 2012
 #include <ctype.h>
 #include <dirent.h>
 #include <err.h>
+#include <archive.h>
 #include <libgen.h>
 #include <md5.h>
 #include <stdio.h>
@@ -94,12 +95,13 @@ typedef struct mandb_rec {
 static void append(secbuff *sbuff, const char *src);
 static void init_secbuffs(mandb_rec *);
 static void free_secbuffs(mandb_rec *);
-static int check_md5(const char *, sqlite3 *, const char *, char **);
+static int check_md5(const char *, sqlite3 *, const char *, char **, void *, size_t);
 static void cleanup(mandb_rec *);
 static void set_section(const struct mdoc *, const struct man *, mandb_rec *);
 static void set_machine(const struct mdoc *, mandb_rec *);
 static int insert_into_db(sqlite3 *, mandb_rec *);
-static	void begin_parse(const char *, struct mparse *, mandb_rec *);
+static	void begin_parse(const char *, struct mparse *, mandb_rec *,
+			 const void *, size_t len);
 static void pmdoc_node(const struct mdoc_node *, mandb_rec *);
 static void pmdoc_Nm(const struct mdoc_node *, mandb_rec *);
 static void pmdoc_Nd(const struct mdoc_node *, mandb_rec *);
@@ -591,6 +593,59 @@ update_existing_entry(sqlite3 *db, const
 	sqlite3_finalize(inner_stmt);
 }
 
+/* read_and_decompress --
+ *	Reads the given file into memory. If it is compressed, decompres
+ *	it before returning to the caller.
+ */
+static int
+read_and_decompress(const char *file, void **buf, size_t *len)
+{
+	size_t off;
+	ssize_t r;
+	struct archive *a;
+	struct archive_entry *ae;
+
+	if ((a = archive_read_new()) == NULL)
+		errx(EXIT_FAILURE, "memory allocation failed");
+
+	if (archive_read_support_compression_all(a) != ARCHIVE_OK ||
+	    archive_read_support_format_raw(a) != ARCHIVE_OK ||
+	    archive_read_open_filename(a, file, 65536) != ARCHIVE_OK ||
+	    archive_read_next_header(a, &ae) != ARCHIVE_OK)
+		goto archive_error;
+	*len = 65536;
+	*buf = emalloc(*len);
+	off = 0;
+	for (;;) {
+		r = archive_read_data(a, (char *)*buf + off, *len - off);
+		if (r == ARCHIVE_OK) {
+			archive_read_close(a);
+			*len = off;
+			return 0;
+		}
+		if (r <= 0) {
+			free(*buf);
+			break;
+		}
+		off += r;
+		if (off == *len) {
+			*len *= 2;
+			if (*len < off) {
+				warnx("File too large: %s", file);
+				free(*buf);
+				archive_read_close(a);
+				return -1;
+			}
+			*buf = erealloc(*buf, *len);
+		}
+	}
+
+archive_error:
+	warnx("Error while reading `%s': %s", file, archive_error_string(a));
+	archive_read_close(a);
+	return -1;
+}
+
 /* update_db --
  *	Does an incremental updation of the database by checking the file_cache.
  *	It parses and adds the pages which are present in file_cache,
@@ -605,7 +660,9 @@ update_db(sqlite3 *db, struct mparse *mp
 	sqlite3_stmt *stmt = NULL;
 	const char *file;
 	char *errmsg = NULL;
-	char *buf = NULL;
+	char *md5sum;
+	void *buf;
+	size_t buflen;
 	int new_count = 0;	/* Counter for newly indexed/updated pages */
 	int total_count = 0;	/* Counter for total number of pages */
 	int err_count = 0;	/* Counter for number of failed pages */
@@ -623,14 +680,21 @@ update_db(sqlite3 *db, struct mparse *mp
 		errx(EXIT_FAILURE, "Could not query file cache");
 	}
 
+	buf = NULL;
 	while (sqlite3_step(stmt) == SQLITE_ROW) {
+		free(buf);
 		total_count++;
 		rec->device = sqlite3_column_int64(stmt, 0);
 		rec->inode = sqlite3_column_int64(stmt, 1);
 		rec->mtime = sqlite3_column_int64(stmt, 2);
 		file = (const char *) sqlite3_column_text(stmt, 3);
-		md5_status = check_md5(file, db, "mandb_meta", &buf);
-		assert(buf != NULL);
+		if (read_and_decompress(file, &buf, &buflen)) {
+			err_count++;
+			buf = NULL;
+			continue;
+		}
+		md5_status = check_md5(file, db, "mandb_meta", &md5sum, buf, buflen);
+		assert(md5sum != NULL);
 		if (md5_status == -1) {
 			warnx("An error occurred in checking md5 value"
 			      " for file %s", file);
@@ -646,13 +710,13 @@ update_db(sqlite3 *db, struct mparse *mp
 			struct stat sb;
 			stat(file, &sb);
 			if (S_ISLNK(sb.st_mode)) {
-				free(buf);
+				free(md5sum);
 				link_count++;
 				continue;
 			}
-			update_existing_entry(db, file, buf, rec,
+			update_existing_entry(db, file, md5sum, rec,
 			    &new_count, &link_count, &err_count);
-			free(buf);
+			free(md5sum);
 			continue;
 		}
 
@@ -664,10 +728,10 @@ update_db(sqlite3 *db, struct mparse *mp
 			 */
 			if (mflags.verbosity > 1)
 				printf("Parsing: %s\n", file);
-			rec->md5_hash = buf;
+			rec->md5_hash = md5sum;
 			rec->file_path = estrdup(file);
 			// file_path is freed by insert_into_db itself.
-			begin_parse(file, mp, rec);
+			begin_parse(file, mp, rec, buf, buflen);
 			if (insert_into_db(db, rec) < 0) {
 				warnx("Error in indexing %s", file);
 				err_count++;
@@ -676,7 +740,8 @@ update_db(sqlite3 *db, struct mparse *mp
 			}
 		}
 	}
-	
+	free(buf);
+
 	sqlite3_finalize(stmt);
 	
 	if (mflags.verbosity) {
@@ -715,7 +780,8 @@ update_db(sqlite3 *db, struct mparse *mp
  *  parses the man page using libmandoc
  */
 static void
-begin_parse(const char *file, struct mparse *mp, mandb_rec *rec)
+begin_parse(const char *file, struct mparse *mp, mandb_rec *rec,
+    const void *buf, size_t len)
 {
 	struct mdoc *mdoc;
 	struct man *man;
@@ -723,7 +789,7 @@ begin_parse(const char *file, struct mpa
 
 	rec->xr_found = 0;
 
-	if (mparse_readfd(mp, -1, file) >= MANDOCLEVEL_FATAL) {
+	if (mparse_readmem(mp, buf, len, file) >= MANDOCLEVEL_FATAL) {
 		warnx("%s: Parse failure", file);
 		return;
 	}
@@ -1679,7 +1745,8 @@ insert_into_db(sqlite3 *db, mandb_rec *r
  *  1: If the hash exists in the database.
  */
 static int
-check_md5(const char *file, sqlite3 *db, const char *table, char **buf)
+check_md5(const char *file, sqlite3 *db, const char *table, char **md5sum,
+    void *buf, size_t buflen)
 {
 	int rc = 0;
 	int idx = -1;
@@ -1687,8 +1754,8 @@ check_md5(const char *file, sqlite3 *db,
 	sqlite3_stmt *stmt = NULL;
 
 	assert(file != NULL);
-	*buf = MD5File(file, NULL);
-	if (*buf == NULL) {
+	*md5sum = MD5Data(buf, buflen, NULL);
+	if (*md5sum == NULL) {
 		warn("md5 failed: %s", file);
 		return -1;
 	}
@@ -1698,19 +1765,19 @@ check_md5(const char *file, sqlite3 *db,
 	rc = sqlite3_prepare_v2(db, sqlstr, -1, &stmt, NULL);
 	if (rc != SQLITE_OK) {
 		free(sqlstr);
-		free(*buf);
-		*buf = NULL;
+		free(*md5sum);
+		*md5sum = NULL;
 		return -1;
 	}
 
 	idx = sqlite3_bind_parameter_index(stmt, ":md5_hash");
-	rc = sqlite3_bind_text(stmt, idx, *buf, -1, NULL);
+	rc = sqlite3_bind_text(stmt, idx, *md5sum, -1, NULL);
 	if (rc != SQLITE_OK) {
 		warnx("%s", sqlite3_errmsg(db));
 		sqlite3_finalize(stmt);
 		free(sqlstr);
-		free(*buf);
-		*buf = NULL;
+		free(*md5sum);
+		*md5sum = NULL;
 		return -1;
 	}
 

Reply via email to