source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Allow checking that databases are up to date even when you have
@ 2014-03-18 16:56 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2014-03-18 16:56 UTC (permalink / raw)
  To: source

Log Message:
-----------
Allow checking that databases are up to date even when you have no write
permission on the databases, as requested by espie@ quite some time ago.
But make sure to not slow database generation down when you do have write
permission, and to not delay error reporting in -Q mode.

Modified Files:
--------------
    mdocml:
        mandocdb.c

Revision Data
-------------
Index: mandocdb.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandocdb.c,v
retrieving revision 1.114
retrieving revision 1.115
diff -Lmandocdb.c -Lmandocdb.c -u -p -r1.114 -r1.115
--- mandocdb.c
+++ mandocdb.c
@@ -20,6 +20,7 @@
 #endif
 
 #include <sys/stat.h>
+#include <sys/wait.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -168,6 +169,7 @@ static	int	 set_basedir(const char *);
 static	int	 treescan(void);
 static	size_t	 utf8(unsigned int, char [7]);
 
+static	char		 tempfilename[32];
 static	char		*progname;
 static	int		 nodb; /* no database changes */
 static	int		 quick; /* abort the parse early */
@@ -1874,6 +1876,8 @@ static void
 dbclose(int real)
 {
 	size_t		 i;
+	int		 status;
+	pid_t		 child;
 
 	if (nodb)
 		return;
@@ -1889,9 +1893,59 @@ dbclose(int real)
 	if (real)
 		return;
 
-	if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {
+	if ('\0' == *tempfilename) {
+		if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {
+			exitcode = (int)MANDOCLEVEL_SYSERR;
+			say(MANDOC_DB, "%s", strerror(errno));
+		}
+		return;
+	}
+
+	switch (child = fork()) {
+	case (-1):
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say("fork cmp", "%s", strerror(errno));
+		return;
+	case (0):
+		execlp("cmp", "cmp", "-s",
+		    tempfilename, MANDOC_DB, NULL);
+		say("exec cmp", "%s", strerror(errno));
+		exit(0);
+	default:
+		break;
+	}
+	if (-1 == waitpid(child, &status, 0)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say("wait cmp", "%s", strerror(errno));
+	} else if (WIFSIGNALED(status)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say("cmp", "Died from a signal");
+	} else if (WEXITSTATUS(status)) {
 		exitcode = (int)MANDOCLEVEL_SYSERR;
-		say(MANDOC_DB, NULL);
+		say(MANDOC_DB,
+		    "Data changed, but cannot replace database");
+	}
+
+	*strrchr(tempfilename, '/') = '\0';
+	switch (child = fork()) {
+	case (-1):
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say("fork rm", "%s", strerror(errno));
+		return;
+	case (0):
+		execlp("rm", "rm", "-rf", tempfilename, NULL);
+		say("exec rm", "%s", strerror(errno));
+		exit((int)MANDOCLEVEL_SYSERR);
+	default:
+		break;
+	}
+	if (-1 == waitpid(child, &status, 0)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say("wait rm", "%s", strerror(errno));
+	} else if (WIFSIGNALED(status) || WEXITSTATUS(status)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say(tempfilename,
+		    "Cannot remove temporary directory");
 	}
 }
 
@@ -1906,42 +1960,62 @@ dbclose(int real)
 static int
 dbopen(int real)
 {
-	const char	*file, *sql;
+	const char	*sql;
 	int		 rc, ofl;
 
 	if (nodb) 
 		return(1);
 
+	*tempfilename = '\0';
 	ofl = SQLITE_OPEN_READWRITE;
-	if (0 == real) {
-		file = MANDOC_DB "~";
-		if (-1 == remove(file) && ENOENT != errno) {
+
+	if (real) {
+		rc = sqlite3_open_v2(MANDOC_DB, &db, ofl, NULL);
+		if (SQLITE_OK != rc) {
 			exitcode = (int)MANDOCLEVEL_SYSERR;
-			say(file, NULL);
+			say(MANDOC_DB, "%s", sqlite3_errmsg(db));
 			return(0);
 		}
-		ofl |= SQLITE_OPEN_EXCLUSIVE;
-	} else
-		file = MANDOC_DB;
+		goto prepare_statements;
+	}
 
-	rc = sqlite3_open_v2(file, &db, ofl, NULL);
+	ofl |= SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE;
+
+	remove(MANDOC_DB "~");
+	rc = sqlite3_open_v2(MANDOC_DB "~", &db, ofl, NULL);
 	if (SQLITE_OK == rc) 
-		goto prepare_statements;
-	if (SQLITE_CANTOPEN != rc) {
+		goto create_tables;
+	if (quick) {
 		exitcode = (int)MANDOCLEVEL_SYSERR;
-		say(file, NULL);
+		say(MANDOC_DB "~", "%s", sqlite3_errmsg(db));
 		return(0);
 	}
 
-	sqlite3_close(db);
-	db = NULL;
-
-	if (SQLITE_OK != (rc = sqlite3_open(file, &db))) {
+	if (strlcpy(tempfilename, "/tmp/mandocdb.XXXXXX",
+	    sizeof(tempfilename)) >= sizeof(tempfilename)) {
 		exitcode = (int)MANDOCLEVEL_SYSERR;
-		say(file, NULL);
+		say("/tmp/mandocdb.XXXXXX", "Filename too long");
+		return(0);
+	}
+	if (NULL == mkdtemp(tempfilename)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say(tempfilename, "%s", strerror(errno));
+		return(0);
+	}
+	if (strlcat(tempfilename, "/" MANDOC_DB,
+	    sizeof(tempfilename)) >= sizeof(tempfilename)) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say(tempfilename, "Filename too long");
+		return(0);
+	}
+	rc = sqlite3_open_v2(tempfilename, &db, ofl, NULL);
+	if (SQLITE_OK != rc) {
+		exitcode = (int)MANDOCLEVEL_SYSERR;
+		say(tempfilename, "%s", sqlite3_errmsg(db));
 		return(0);
 	}
 
+create_tables:
 	sql = "CREATE TABLE \"mpages\" (\n"
 	      " \"form\" INTEGER NOT NULL,\n"
 	      " \"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL\n"
@@ -1964,7 +2038,7 @@ dbopen(int real)
 
 	if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, NULL)) {
 		exitcode = (int)MANDOCLEVEL_SYSERR;
-		say(file, "%s", sqlite3_errmsg(db));
+		say(MANDOC_DB, "%s", sqlite3_errmsg(db));
 		return(0);
 	}
 
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2014-03-18 16:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-18 16:56 mdocml: Allow checking that databases are up to date even when you have schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).