diff src/content.c @ 188:f1bacee93ca6 noffle

[svn] * src/client.c,src/client.h,src/fetch.c,src/noffle.c,src/server.c: robustness - instead of retruning simple Passed/Failed statuses from connection functions, return an integer status instead. This allows Noffle to distinguish between a connection failure, an unrecoverable protocol error and a recoverable problem. As a concrete instance, Noffle will no longer abort the connection if a group is removed from the upstream server. Also beef up error detection a bit. * src/content.c: instead of overwriting the existing content file(s) when updating - which leaves a window where Noffle is vulnerable to failure which will leave the content file corrupted (yes, it happened to me), write a new content file and rename it over the old file only when it has been written and closed with no errors reported.
author bears
date Wed, 12 Sep 2001 21:33:44 +0100
parents fed1334d766b
children 60a70c16d79c
line wrap: on
line diff
--- a/src/content.c	Sat Sep 01 16:57:45 2001 +0100
+++ b/src/content.c	Wed Sep 12 21:33:44 2001 +0100
@@ -1,7 +1,7 @@
 /*
   content.c
 
-  $Id: content.c 300 2001-08-05 08:24:22Z bears $
+  $Id: content.c 307 2001-09-12 20:33:44Z bears $
 */
 
 #if HAVE_CONFIG_H
@@ -10,6 +10,7 @@
 
 #include <stdio.h>
 #include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -188,20 +189,26 @@
     int i;
     FILE *f;
     const Over *ov, *ov_next;
+    Str tmpfname;
+    Bool writeErr;
 
     /* If nowt has changed, do nowt. */
     if ( ! cont.dirty )
 	return;
     
-    /* Save the overview */
-    if ( ! ( f = fopen( cont.file, "w" ) ) )
+    /* Save the overview to temporary file in same dir. */
+    snprintf( tmpfname, MAXCHAR, "%s/overview/%s.%d",
+	      Cfg_spoolDir(), cont.name, (int) getpid() ); 
+    if ( ! ( f = fopen( tmpfname, "w" ) ) )
     {
-        Log_err( "Could not open %s for writing", cont.file );
+        Log_err( "Could not open %s for writing", tmpfname );
         return;
     }
-    Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", cont.file, cont.size );
+    Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", tmpfname, cont.size );
     anythingWritten = FALSE;
     cont.first = -1;
+    writeErr = FALSE;
+    
     for ( i = 0; i < cont.size; ++i )
     {
 	ov = cont.elem[ i ];
@@ -223,21 +230,28 @@
 		 || ( ov_next != NULL &&
 		      Ov_numb( ov_next ) - Ov_numb( ov ) == 1 ) )
             {
+		anythingWritten = TRUE;
                 if ( ! Ov_write( ov, f ) )
                 {
-                    Log_err( "Writing of overview line failed" );
+                    Log_err( "Writing of overview line to %s failed: %s",
+			     tmpfname, strerror( errno ) );
+		    writeErr = TRUE;
                     break;
                 }
                 else
 		{
-                    anythingWritten = TRUE;
 		    if  ( cont.first < 0 )
 			cont.first = cont.vecFirst + i;
 		}
             }
         }
     }
-    fclose( f );
+    if ( fclose( f ) != 0 )
+    {
+	Log_err( "Close of content file %s failed: %s",
+		 tmpfname, strerror( errno ) );
+	writeErr = TRUE;
+    }
 
     /*
       If empty, remove the overview file and set set first to one
@@ -245,11 +259,22 @@
      */
     if ( ! anythingWritten )
     {
-	unlink( cont.file );
-	cont.first = cont.last + 1;
+	if ( unlink( cont.file ) < 0 )
+	    Log_err( "Unlink of %s failed: %s", cont.file, strerror( errno ) );
+	else
+	{
+	    cont.dirty = FALSE;
+	    cont.first = cont.last + 1;
+	}
     }
-
-    cont.dirty = FALSE;
+    else if ( ! writeErr )
+    {
+	if ( rename( tmpfname, cont.file ) < 0 )
+	    Log_err( "Rename of content file %s to %s failed: %s",
+		     tmpfname, cont.file, strerror( errno ) );
+	else
+	    cont.dirty = FALSE;
+    }
 }
 
 const Over *