Mercurial > noffle
view src/fetchlist.c @ 232:6767c6f3218f noffle
[svn] * src/fetchlist.c: Write fetchlist to new file and update if written
correctly. Stops fetchlist being trashed on disc full. Also add
fetchlist dirty flag to save unnecessary rewrites.
author | bears |
---|---|
date | Fri, 08 Feb 2002 17:06:01 +0000 |
parents | fed1334d766b |
children | f8a91e2b4060 |
line wrap: on
line source
/* fetchlist.c $Id: fetchlist.c 363 2002-02-08 17:06:01Z bears $ */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include <errno.h> #include <unistd.h> #include "fetchlist.h" #include "configfile.h" #include "log.h" #include "util.h" #include "portable.h" struct Elem { Str name; FetchMode mode; }; static struct Fetchlist { struct Elem *elem; int size; int max; Bool dirty; } fetchlist = { NULL, 0, 0, FALSE }; static void clearList( void ) { fetchlist.size = 0; fetchlist.dirty = FALSE; } static int compareElem( const void *elem1, const void *elem2 ) { const struct Elem* e1 = (const struct Elem*)elem1; const struct Elem* e2 = (const struct Elem*)elem2; return strcmp( e1->name, e2->name ); } static struct Elem * searchElem( const char *name ) { int i; for ( i = 0; i < fetchlist.size; ++i ) if ( strcmp( name, fetchlist.elem[ i ].name ) == 0 ) return &fetchlist.elem[ i ]; return NULL; } static void appGrp( const char *name, FetchMode mode ) { struct Elem elem; if ( fetchlist.max < fetchlist.size + 1 ) { if ( ! ( fetchlist.elem = realloc( fetchlist.elem, ( fetchlist.max + 50 ) * sizeof( fetchlist.elem[ 0 ] ) ) ) ) { Log_err( "Could not realloc fetchlist" ); exit( EXIT_FAILURE ); } fetchlist.max += 50; } strcpy( elem.name, name ); elem.mode = mode; fetchlist.elem[ fetchlist.size++ ] = elem; } void Fetchlist_read( void ) { FILE *f; Str file; char *p; FetchMode mode = OVER; Bool valid; int ret; Str line, grp, modeStr; Log_dbg( LOG_DBG_FETCH, "Reading %s", file ); snprintf( file, MAXCHAR, "%s/fetchlist", Cfg_spoolDir() ); clearList(); if ( ! ( f = fopen( file, "r" ) ) ) { Log_inf( "No file %s", file ); return; } while ( fgets( line, MAXCHAR, f ) ) { p = Utl_stripWhiteSpace( line ); if ( *p == '#' || *p == '\0' ) continue; ret = sscanf( p, "%s %s", grp, modeStr ); valid = TRUE; if ( ret < 1 || ret > 2 ) valid = FALSE; else if ( ret >= 2 ) { if ( strcmp( modeStr, "full" ) == 0 ) mode = FULL; else if ( strcmp( modeStr, "thread" ) == 0 ) mode = THREAD; else if ( strcmp( modeStr, "over" ) == 0 ) mode = OVER; else valid = FALSE; } if ( ! valid ) { Log_err( "Invalid entry in %s: %s", file, line ); continue; } appGrp( grp, mode ); } if ( ferror( f ) ) Log_err( "Error reading %s: %s", file, strerror( errno ) ); if ( fclose( f ) != 0 ) Log_err( "Error closing %s; %s", file, strerror( errno ) ); } Bool Fetchlist_write( void ) { int i; FILE *f; Str file, tmpfname; const char *modeStr = ""; Bool res; /* Any changes? */ if ( ! fetchlist.dirty ) return TRUE; qsort( fetchlist.elem, (size_t)fetchlist.size, sizeof( fetchlist.elem[ 0 ] ), compareElem ); snprintf( file, MAXCHAR, "%s/fetchlist", Cfg_spoolDir() ); snprintf( tmpfname, MAXCHAR, "%s/.#%d.fetchlist", Cfg_spoolDir(), (int) getpid() ); if ( ! ( f = fopen( tmpfname, "w" ) ) ) { Log_err( "Could not open %s for writing", file ); return FALSE; } res = TRUE; for ( i = 0; i < fetchlist.size; ++i ) { switch ( fetchlist.elem[ i ].mode ) { case FULL: modeStr = "full"; break; case THREAD: modeStr = "thread"; break; case OVER: modeStr = "over"; break; } fprintf( f, "%s %s\n", fetchlist.elem[ i ].name, modeStr ); if ( ferror( f ) ) { Log_err( "Error writing %s: %s", tmpfname, strerror( errno ) ); clearerr( f ); res = FALSE; } } if ( fclose( f ) != 0 ) { Log_err( "Error closing %s: %s", tmpfname, strerror( errno ) ); res = FALSE; } if ( res ) { if ( rename( tmpfname, file ) < 0 ) { Log_err( "Rename of %s to %s failed: %s", tmpfname, file, strerror( errno ) ); res = FALSE; } } return res; } int Fetchlist_size( void ) { return fetchlist.size; } Bool Fetchlist_contains( const char *name ) { return ( searchElem( name ) != NULL ); } Bool Fetchlist_element( const char **name, FetchMode *mode, int idx ) { if ( idx < 0 || idx >= fetchlist.size ) return FALSE; *name = fetchlist.elem[ idx ].name; *mode = fetchlist.elem[ idx ].mode; return TRUE; } Bool Fetchlist_add( const char *name, FetchMode mode ) { struct Elem *elem = searchElem( name ); fetchlist.dirty = TRUE; if ( elem == NULL ) { appGrp( name, mode ); return TRUE; } strcpy( elem->name, name ); elem->mode = mode; return FALSE; } Bool Fetchlist_remove( const char *name ) { struct Elem *elem = searchElem( name ); if ( elem == NULL ) return FALSE; fetchlist.dirty = TRUE; *elem = fetchlist.elem[ fetchlist.size - 1 ]; --fetchlist.size; return TRUE; }