comparison src/content.c @ 223:ffb1848a39db noffle

[svn] * src/util.c: Improve (correct) error detection when updating timestamp file. * src/content.h, src/content.c: Return Boolean success/fail from Cont_write. Also ensure cont.first isn't polluted in the event of a failed update. * src/client.c,src/control.c,src/fetch.c,src/noffle.c,src/post.c, src/pseudo.c: If Cont_write fails, don't do actions that need it to have worked. Typically, don't update first and last article numbers in group database. * src/server.c: If groupinfo.lastupdate is unreadable or corrupt, spot this and report it and give an explicit error when processing NNTP NEWGROUPS command.
author bears
date Sun, 09 Dec 2001 12:31:57 +0000
parents d9f314014f7a
children c48d7e881a21
comparison
equal deleted inserted replaced
222:bf290632d29e 223:ffb1848a39db
1 /* 1 /*
2 content.c 2 content.c
3 3
4 $Id: content.c 338 2001-11-29 22:16:06Z bears $ 4 $Id: content.c 342 2001-12-09 12:31:57Z 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
181 if ( cont.last < grpLast ) 181 if ( cont.last < grpLast )
182 extendCont( grpLast - cont.first + 1 ); 182 extendCont( grpLast - cont.first + 1 );
183 } 183 }
184 } 184 }
185 185
186 void 186 Bool
187 Cont_write( void ) 187 Cont_write( void )
188 { 188 {
189 Bool anythingWritten; 189 Bool anythingWritten;
190 int i; 190 int i;
191 FILE *f; 191 FILE *f;
192 const Over *ov, *ov_next; 192 const Over *ov, *ov_next;
193 Str tmpfname; 193 Str tmpfname;
194 Bool writeErr; 194 Bool writeErr;
195 int first;
195 196
196 /* If nowt has changed, do nowt. */ 197 /* If nowt has changed, do nowt. */
197 if ( ! cont.dirty ) 198 if ( ! cont.dirty )
198 return; 199 return TRUE;
199 200
200 /* Save the overview to temporary file in same dir. */ 201 /* Save the overview to temporary file in same dir. */
201 /* old tmpfnames will be expired at noffle.c:expireContents() */ 202 /* old tmpfnames will be expired at noffle.c:expireContents() */
202 snprintf( tmpfname, MAXCHAR, "%s/overview/.#%d.%s", 203 snprintf( tmpfname, MAXCHAR, "%s/overview/.#%d.%s",
203 Cfg_spoolDir(), (int) getpid(), cont.name ); 204 Cfg_spoolDir(), (int) getpid(), cont.name );
204 if ( ! ( f = fopen( tmpfname, "w" ) ) ) 205 if ( ! ( f = fopen( tmpfname, "w" ) ) )
205 { 206 {
206 Log_err( "Could not open %s for writing", tmpfname ); 207 Log_err( "Could not open %s for writing", tmpfname );
207 return; 208 return FALSE;
208 } 209 }
209 Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", tmpfname, cont.size ); 210 Log_dbg( LOG_DBG_NEWSBASE, "Writing %s (%lu)", tmpfname, cont.size );
210 anythingWritten = FALSE; 211 anythingWritten = FALSE;
211 cont.first = -1; 212 first = -1;
212 writeErr = FALSE; 213 writeErr = FALSE;
213 214
214 for ( i = 0; i < cont.size; ++i ) 215 for ( i = 0; i < cont.size; ++i )
215 { 216 {
216 ov = cont.elem[ i ]; 217 ov = cont.elem[ i ];
230 */ 231 */
231 if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) ) 232 if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) )
232 || ( ov_next != NULL && 233 || ( ov_next != NULL &&
233 Ov_numb( ov_next ) - Ov_numb( ov ) == 1 ) ) 234 Ov_numb( ov_next ) - Ov_numb( ov ) == 1 ) )
234 { 235 {
235 anythingWritten = TRUE; 236 anythingWritten = TRUE;
236 if ( ! Ov_write( ov, f ) ) 237 if ( ! Ov_write( ov, f ) )
237 { 238 {
238 Log_err( "Writing of overview line to %s failed: %s", 239 Log_err( "Writing of overview line to %s failed: %s",
239 tmpfname, strerror( errno ) ); 240 tmpfname, strerror( errno ) );
240 writeErr = TRUE; 241 writeErr = TRUE;
241 break; 242 break;
242 } 243 }
243 else 244 else
244 { 245 {
245 if ( cont.first < 0 ) 246 if ( first < 0 )
246 cont.first = cont.vecFirst + i; 247 first = cont.vecFirst + i;
247 } 248 }
248 } 249 }
249 } 250 }
250 } 251 }
251 if ( fclose( f ) != 0 ) 252 if ( fclose( f ) != 0 )
253 Log_err( "Close of content file %s failed: %s", 254 Log_err( "Close of content file %s failed: %s",
254 tmpfname, strerror( errno ) ); 255 tmpfname, strerror( errno ) );
255 writeErr = TRUE; 256 writeErr = TRUE;
256 } 257 }
257 258
259 if ( writeErr )
260 {
261 /* Write error - leave everything as at present */
262 return FALSE;
263 }
264
258 /* 265 /*
259 If empty, remove the overview file and set set first to one 266 If empty, remove the overview file and set first to one
260 beyond last to flag said emptiness. 267 beyond last to flag said emptiness.
261 */ 268 */
262 if ( ! anythingWritten ) 269 if ( ! anythingWritten )
263 { 270 {
264 if ( unlink( tmpfname ) < 0 ) 271 if ( unlink( tmpfname ) < 0 )
265 Log_err( "Unlink of %s failed: %s", tmpfname, strerror( errno ) ); 272 Log_err( "Unlink of %s failed: %s", tmpfname, strerror( errno ) );
266 if ( unlink( cont.file ) < 0 ) 273 if ( unlink( cont.file ) < 0 )
274 {
267 Log_err( "Unlink of %s failed: %s", cont.file, strerror( errno ) ); 275 Log_err( "Unlink of %s failed: %s", cont.file, strerror( errno ) );
276 return FALSE;
277 }
268 else 278 else
269 { 279 {
270 cont.dirty = FALSE; 280 cont.dirty = FALSE;
271 cont.first = cont.last + 1; 281 cont.first = cont.last + 1;
272 } 282 }
273 } 283 }
274 else if ( ! writeErr ) 284 else
275 { 285 {
276 if ( rename( tmpfname, cont.file ) < 0 ) 286 if ( rename( tmpfname, cont.file ) < 0 )
287 {
277 Log_err( "Rename of content file %s to %s failed: %s", 288 Log_err( "Rename of content file %s to %s failed: %s",
278 tmpfname, cont.file, strerror( errno ) ); 289 tmpfname, cont.file, strerror( errno ) );
290 return FALSE;
291 }
279 else 292 else
293 {
294 ASSERT( first != -1 );
280 cont.dirty = FALSE; 295 cont.dirty = FALSE;
281 } 296 cont.first = first;
297 }
298 }
299
300 return TRUE;
282 } 301 }
283 302
284 const Over * 303 const Over *
285 Cont_get( int numb ) 304 Cont_get( int numb )
286 { 305 {