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