comparison 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
comparison
equal deleted inserted replaced
187:166008a80f03 188:f1bacee93ca6
1 /* 1 /*
2 content.c 2 content.c
3 3
4 $Id: content.c 300 2001-08-05 08:24:22Z bears $ 4 $Id: content.c 307 2001-09-12 20:33:44Z bears $
5 */ 5 */
6 6
7 #if HAVE_CONFIG_H 7 #if HAVE_CONFIG_H
8 #include <config.h> 8 #include <config.h>
9 #endif 9 #endif
10 10
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <dirent.h> 12 #include <dirent.h>
13 #include <errno.h>
13 #include <fcntl.h> 14 #include <fcntl.h>
14 #include <sys/types.h> 15 #include <sys/types.h>
15 #include <sys/stat.h> 16 #include <sys/stat.h>
16 #include <unistd.h> 17 #include <unistd.h>
17 #include "common.h" 18 #include "common.h"
186 { 187 {
187 Bool anythingWritten; 188 Bool anythingWritten;
188 int i; 189 int i;
189 FILE *f; 190 FILE *f;
190 const Over *ov, *ov_next; 191 const Over *ov, *ov_next;
192 Str tmpfname;
193 Bool writeErr;
191 194
192 /* If nowt has changed, do nowt. */ 195 /* If nowt has changed, do nowt. */
193 if ( ! cont.dirty ) 196 if ( ! cont.dirty )
194 return; 197 return;
195 198
196 /* Save the overview */ 199 /* Save the overview to temporary file in same dir. */
197 if ( ! ( f = fopen( cont.file, "w" ) ) ) 200 snprintf( tmpfname, MAXCHAR, "%s/overview/%s.%d",
198 { 201 Cfg_spoolDir(), cont.name, (int) getpid() );
199 Log_err( "Could not open %s for writing", cont.file ); 202 if ( ! ( f = fopen( tmpfname, "w" ) ) )
203 {
204 Log_err( "Could not open %s for writing", tmpfname );
200 return; 205 return;
201 } 206 }
202 Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", cont.file, cont.size ); 207 Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", tmpfname, cont.size );
203 anythingWritten = FALSE; 208 anythingWritten = FALSE;
204 cont.first = -1; 209 cont.first = -1;
210 writeErr = FALSE;
211
205 for ( i = 0; i < cont.size; ++i ) 212 for ( i = 0; i < cont.size; ++i )
206 { 213 {
207 ov = cont.elem[ i ]; 214 ov = cont.elem[ i ];
208 if ( ov ) 215 if ( ov )
209 { 216 {
221 */ 228 */
222 if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) ) 229 if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) )
223 || ( ov_next != NULL && 230 || ( ov_next != NULL &&
224 Ov_numb( ov_next ) - Ov_numb( ov ) == 1 ) ) 231 Ov_numb( ov_next ) - Ov_numb( ov ) == 1 ) )
225 { 232 {
233 anythingWritten = TRUE;
226 if ( ! Ov_write( ov, f ) ) 234 if ( ! Ov_write( ov, f ) )
227 { 235 {
228 Log_err( "Writing of overview line failed" ); 236 Log_err( "Writing of overview line to %s failed: %s",
237 tmpfname, strerror( errno ) );
238 writeErr = TRUE;
229 break; 239 break;
230 } 240 }
231 else 241 else
232 { 242 {
233 anythingWritten = TRUE;
234 if ( cont.first < 0 ) 243 if ( cont.first < 0 )
235 cont.first = cont.vecFirst + i; 244 cont.first = cont.vecFirst + i;
236 } 245 }
237 } 246 }
238 } 247 }
239 } 248 }
240 fclose( f ); 249 if ( fclose( f ) != 0 )
250 {
251 Log_err( "Close of content file %s failed: %s",
252 tmpfname, strerror( errno ) );
253 writeErr = TRUE;
254 }
241 255
242 /* 256 /*
243 If empty, remove the overview file and set set first to one 257 If empty, remove the overview file and set set first to one
244 beyond last to flag said emptiness. 258 beyond last to flag said emptiness.
245 */ 259 */
246 if ( ! anythingWritten ) 260 if ( ! anythingWritten )
247 { 261 {
248 unlink( cont.file ); 262 if ( unlink( cont.file ) < 0 )
249 cont.first = cont.last + 1; 263 Log_err( "Unlink of %s failed: %s", cont.file, strerror( errno ) );
250 } 264 else
251 265 {
252 cont.dirty = FALSE; 266 cont.dirty = FALSE;
267 cont.first = cont.last + 1;
268 }
269 }
270 else if ( ! writeErr )
271 {
272 if ( rename( tmpfname, cont.file ) < 0 )
273 Log_err( "Rename of content file %s to %s failed: %s",
274 tmpfname, cont.file, strerror( errno ) );
275 else
276 cont.dirty = FALSE;
277 }
253 } 278 }
254 279
255 const Over * 280 const Over *
256 Cont_get( int numb ) 281 Cont_get( int numb )
257 { 282 {