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 );
+}