On Sun, Mar 6, 2011 at 6:52 PM, Martin Steigerwald <[email protected]> wrote:
> Am Sunday 06 March 2011 schrieb Thibaut VARENE:

>> As stated before, the correct solution would be to add another layer of
>> checks during daemon startup, which would assert that the file it's
>> reading is valid (i.e. to begin with "not empty" and "has parseable
>> data"), and fall back to the backup copy otherwise. This, by design,
>> is the correct approach and has /none/ of the drawbacks of your
>> fsync() patch.
>>
>> I would gladly review such a patch.
>
> But thats at least an offer. And it would help BSD as well. Let's see what
> I will do when there will be the next rainy day during my holidays in
> Sevilla.
>
> But until then I likely have a version that works and I will fork it that
> way as long as it serves the purpose of keeping my uptime records data
> safe in a easy and simple way. This is likely to fix the issue *now*, not
> somewhen in the future. And at least I have done something efficient about
> it in the time I had at my hand.

w/e

Here's an ugly half-cooked, built but otherwise TOTALLY UNTESTED
braindump patch that tries to implement The Right Thing (tm).

Would you be kind enough to test it? I don't crash my systems as often
as you do, and they're setup in a way that apparently makes it
impossible for me to reproduce this bug.

-- 
Thibaut VARENE
http://www.parisc-linux.org/~varenet/
diff -Nru uptimed-0.3.16.orig/libuptimed/urec.c uptimed-0.3.16/libuptimed/urec.c
--- uptimed-0.3.16.orig/libuptimed/urec.c	2009-01-02 00:46:00.000000000 +0100
+++ uptimed-0.3.16/libuptimed/urec.c	2011-03-06 21:01:28.000000000 +0100
@@ -215,20 +215,46 @@
 	time_t utime, btime;
 	long l_utime, l_btime;
 	char buf[256], sys[SYSMAX+1];
+	struct stat filestat, filestatold;
+	int useold = 0;
 	
-	f = fopen(FILE_RECORDS, "r");
-	if (!f) {
-		f = fopen(FILE_RECORDS".old", "r");
-		if (!f) return;
+	if (stat(FILE_RECORDS, &filestat))
+		useold = 1;
+	if (stat(FILE_RECORDS".old", &filestatold))
+		useold = -1;
+
+	/* assume that backupdb larger than normal db means normal is corrupted */
+	if (!useold && (filestat.st_size <= filestatold.st_size))
+		useold = 1;
 
-		printf("uptimed: reading from backup database %s.old\n", FILE_RECORDS);
+dbtry:
+	switch (useold) {
+		case 0:
+			f = fopen(FILE_RECORDS, "r");
+			break;
+		case 1:
+			f = fopen(FILE_RECORDS".old", "r");
+			printf("uptimed: reading from backup database %s.old\n", FILE_RECORDS);
+			break;
+		default:
+			/* this should probably terminate uptimed somehow */
+			printf("uptimed: no useable database found.\n");
+			return;
+	}
+			
+	if (!f) {
+		printf("uptimed: error opening database for reading.\n");
+		return;
 	}
 	
 	fgets(str, sizeof(str), f);
 	while (!feof(f)) {
 		/* Check for validity of input string. */
 		if (sscanf(str, "%ld:%ld:%[^]\n]", &l_utime, &l_btime, buf) != 3) {
-			/* Skip this entry. Do we want feedback here? */
+			/* database is corrupted */
+			fclose(f);
+			useold++;
+			goto dbtry;
 		} else {
 			utime = (time_t)l_utime;
 			btime = (time_t)l_btime;
diff -Nru uptimed-0.3.16.orig/libuptimed/urec.h uptimed-0.3.16/libuptimed/urec.h
--- uptimed-0.3.16.orig/libuptimed/urec.h	2009-01-02 00:46:00.000000000 +0100
+++ uptimed-0.3.16/libuptimed/urec.h	2011-03-06 20:48:49.000000000 +0100
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 
 #ifdef PLATFORM_LINUX
 #include <sys/sysinfo.h>

Reply via email to