Mercurial > noffle
diff content.c @ 0:04124a4423d4 noffle
[svn] Initial revision
author | enz |
---|---|
date | Tue, 04 Jan 2000 11:35:42 +0000 |
parents | |
children | 912123d43a87 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content.c Tue Jan 04 11:35:42 2000 +0000 @@ -0,0 +1,238 @@ +/* + content.c + + $Id: content.c 3 2000-01-04 11:35:42Z enz $ +*/ + +#include <dirent.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include "common.h" +#include "config.h" +#include "log.h" +#include "over.h" +#include "pseudo.h" +#include "util.h" + +struct +{ + DIR *dir; /* Directory for browsing through all + groups */ + int first; + int last; + unsigned int size; /* Number of overviews. */ + unsigned int max; /* Size of elem. */ + Over **elem; /* Ptr to array with ptrs to overviews. + NULL entries for non-existing article numbers + in group. */ + Str name; + Str file; +} cont = { NULL, 1, 0, 0, 0, NULL, "", "" }; + +void +Cont_app( Over *ov ) +{ + if ( cont.max < cont.size + 1 ) + { + if ( ! ( cont.elem = realloc( cont.elem, + ( cont.max + 500 ) + * sizeof( cont.elem[ 0 ] ) ) ) ) + { + Log_err( "Could not realloc overview list" ); + exit( EXIT_FAILURE ); + } + cont.max += 500; + } + if ( cont.first == 0 ) + cont.first = 1; + if ( ov ) + Ov_setNumb( ov, cont.first + cont.size ); + cont.elem[ cont.size++ ] = ov; + cont.last = cont.first + cont.size - 1; +} + +Bool +Cont_validNumb( int n ) +{ + return ( n != 0 && n >= cont.first && n <= cont.last + && cont.elem[ n - cont.first ] ); +} + +void +Cont_delete( int n ) +{ + Over **ov; + + if ( ! Cont_validNumb( n ) ) + return; + ov = &cont.elem[ n - cont.first ]; + free( *ov ); + *ov = NULL; +} + +/* Remove all overviews from content. */ +static void +clearCont() +{ + int i; + + for ( i = 0; i < cont.size; ++i ) + del_Over( cont.elem[ i ] ); + cont.size = 0; +} + +/* Extend content list to size "cnt" and append NULL entries. */ +static void +extendCont( int cnt ) +{ + int i, n; + + if ( cont.size < cnt ) + { + n = cnt - cont.size; + for ( i = 0; i < n; ++i ) + Cont_app( NULL ); + } +} + +/* Discard all cached overviews, and read in the overviews of a new group + from its overviews file. */ +void +Cont_read( const char *name ) +{ + FILE *f; + Over *ov; + int cnt, numb; + Str line; + + /* Delete old overviews and make room for new ones. */ + cont.first = 0; + cont.last = 0; + Utl_cpyStr( cont.name, name ); + clearCont(); + + /* read overviews from overview file and store them in the overviews + list */ + snprintf( cont.file, MAXCHAR, "%s/overview/%s", Cfg_spoolDir(), name ); + if ( cnt == 0 ) + return; + f = fopen( cont.file, "r" ); + if ( ! f ) + { + Log_dbg( "No group overview file: %s", cont.file ); + return; + } + Log_dbg( "Reading %s", cont.file ); + while ( fgets( line, MAXCHAR, f ) ) + { + if ( ! ( ov = Ov_read( line ) ) ) + { + Log_err( "Overview corrupted in %s: %s", name, line ); + continue; + } + numb = Ov_numb( ov ); + if ( numb < cont.first ) + { + Log_err( "Wrong ordering in %s: %s", name, line ); + continue; + } + if ( cont.first == 0 ) + cont.first = numb; + cont.last = numb; + extendCont( numb - cont.first + 1 ); + cont.elem[ numb - cont.first ] = ov; + } + fclose( f ); +} + +void +Cont_write( void ) +{ + Bool anythingWritten; + int i, first; + FILE *f; + const Over *ov; + + first = cont.first; + while ( ! Cont_validNumb( first ) && first <= cont.last ) + ++first; + if ( ! ( f = fopen( cont.file, "w" ) ) ) + { + Log_err( "Could not open %s for writing", cont.file ); + return; + } + Log_dbg( "Writing %s (%lu)", cont.file, cont.size ); + anythingWritten = FALSE; + for ( i = 0; i < cont.size; ++i ) + { + if ( ( ov = cont.elem[ i ] ) ) + { + if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) ) ) + { + if ( ! Ov_write( ov, f ) ) + { + Log_err( "Writing of overview line failed" ); + break; + } + else + anythingWritten = TRUE; + } + } + } + fclose( f ); + if ( ! anythingWritten ) + unlink( cont.file ); +} + +const Over * +Cont_get( int numb ) +{ + if ( ! Cont_validNumb( numb ) ) + return NULL; + return cont.elem[ numb - cont.first ]; +} + +int +Cont_first( void ) { return cont.first; } + +int +Cont_last( void ) { return cont.last; } + +const char * +Cont_grp( void ) { return cont.name; } + +Bool +Cont_nextGrp( Str result ) +{ + struct dirent *d; + + ASSERT( cont.dir ); + if ( ! ( d = readdir( cont.dir ) ) ) + { + cont.dir = NULL; + return FALSE; + } + if ( ! d->d_name ) + return FALSE; + Utl_cpyStr( result, d->d_name ); + result[ MAXCHAR - 1 ] = '\0'; + return TRUE; +} + +Bool +Cont_firstGrp( Str result ) +{ + Str name; + + snprintf( name, MAXCHAR, "%s/overview", Cfg_spoolDir() ); + if ( ! ( cont.dir = opendir( name ) ) ) + { + Log_err( "Cannot open %s", name ); + return FALSE; + } + Cont_nextGrp( result ); /* "." */ + Cont_nextGrp( result ); /* ".." */ + return Cont_nextGrp( result ); +}