Mercurial > noffle
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 *