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