0
|
1 /*
|
|
2 content.c
|
|
3
|
1
|
4 $Id: content.c 6 2000-01-04 13:49:50Z enz $
|
0
|
5 */
|
|
6
|
|
7 #include <dirent.h>
|
|
8 #include <fcntl.h>
|
|
9 #include <sys/types.h>
|
|
10 #include <sys/stat.h>
|
|
11 #include <unistd.h>
|
|
12 #include "common.h"
|
|
13 #include "config.h"
|
|
14 #include "log.h"
|
|
15 #include "over.h"
|
|
16 #include "pseudo.h"
|
|
17 #include "util.h"
|
|
18
|
|
19 struct
|
|
20 {
|
|
21 DIR *dir; /* Directory for browsing through all
|
|
22 groups */
|
|
23 int first;
|
|
24 int last;
|
|
25 unsigned int size; /* Number of overviews. */
|
|
26 unsigned int max; /* Size of elem. */
|
|
27 Over **elem; /* Ptr to array with ptrs to overviews.
|
|
28 NULL entries for non-existing article numbers
|
|
29 in group. */
|
|
30 Str name;
|
|
31 Str file;
|
|
32 } cont = { NULL, 1, 0, 0, 0, NULL, "", "" };
|
|
33
|
|
34 void
|
|
35 Cont_app( Over *ov )
|
|
36 {
|
|
37 if ( cont.max < cont.size + 1 )
|
|
38 {
|
|
39 if ( ! ( cont.elem = realloc( cont.elem,
|
|
40 ( cont.max + 500 )
|
|
41 * sizeof( cont.elem[ 0 ] ) ) ) )
|
|
42 {
|
|
43 Log_err( "Could not realloc overview list" );
|
|
44 exit( EXIT_FAILURE );
|
|
45 }
|
|
46 cont.max += 500;
|
|
47 }
|
|
48 if ( cont.first == 0 )
|
|
49 cont.first = 1;
|
|
50 if ( ov )
|
|
51 Ov_setNumb( ov, cont.first + cont.size );
|
|
52 cont.elem[ cont.size++ ] = ov;
|
|
53 cont.last = cont.first + cont.size - 1;
|
|
54 }
|
|
55
|
|
56 Bool
|
|
57 Cont_validNumb( int n )
|
|
58 {
|
|
59 return ( n != 0 && n >= cont.first && n <= cont.last
|
|
60 && cont.elem[ n - cont.first ] );
|
|
61 }
|
|
62
|
|
63 void
|
|
64 Cont_delete( int n )
|
|
65 {
|
|
66 Over **ov;
|
|
67
|
|
68 if ( ! Cont_validNumb( n ) )
|
|
69 return;
|
|
70 ov = &cont.elem[ n - cont.first ];
|
|
71 free( *ov );
|
|
72 *ov = NULL;
|
|
73 }
|
|
74
|
|
75 /* Remove all overviews from content. */
|
|
76 static void
|
|
77 clearCont()
|
|
78 {
|
|
79 int i;
|
|
80
|
|
81 for ( i = 0; i < cont.size; ++i )
|
|
82 del_Over( cont.elem[ i ] );
|
|
83 cont.size = 0;
|
|
84 }
|
|
85
|
|
86 /* Extend content list to size "cnt" and append NULL entries. */
|
|
87 static void
|
|
88 extendCont( int cnt )
|
|
89 {
|
|
90 int i, n;
|
|
91
|
|
92 if ( cont.size < cnt )
|
|
93 {
|
|
94 n = cnt - cont.size;
|
|
95 for ( i = 0; i < n; ++i )
|
|
96 Cont_app( NULL );
|
|
97 }
|
|
98 }
|
|
99
|
|
100 /* Discard all cached overviews, and read in the overviews of a new group
|
|
101 from its overviews file. */
|
|
102 void
|
|
103 Cont_read( const char *name )
|
|
104 {
|
|
105 FILE *f;
|
|
106 Over *ov;
|
1
|
107 int numb;
|
0
|
108 Str line;
|
|
109
|
|
110 /* Delete old overviews and make room for new ones. */
|
|
111 cont.first = 0;
|
|
112 cont.last = 0;
|
|
113 Utl_cpyStr( cont.name, name );
|
|
114 clearCont();
|
|
115
|
|
116 /* read overviews from overview file and store them in the overviews
|
|
117 list */
|
|
118 snprintf( cont.file, MAXCHAR, "%s/overview/%s", Cfg_spoolDir(), name );
|
|
119 f = fopen( cont.file, "r" );
|
|
120 if ( ! f )
|
|
121 {
|
|
122 Log_dbg( "No group overview file: %s", cont.file );
|
|
123 return;
|
|
124 }
|
|
125 Log_dbg( "Reading %s", cont.file );
|
|
126 while ( fgets( line, MAXCHAR, f ) )
|
|
127 {
|
|
128 if ( ! ( ov = Ov_read( line ) ) )
|
|
129 {
|
|
130 Log_err( "Overview corrupted in %s: %s", name, line );
|
|
131 continue;
|
|
132 }
|
|
133 numb = Ov_numb( ov );
|
|
134 if ( numb < cont.first )
|
|
135 {
|
|
136 Log_err( "Wrong ordering in %s: %s", name, line );
|
|
137 continue;
|
|
138 }
|
|
139 if ( cont.first == 0 )
|
|
140 cont.first = numb;
|
|
141 cont.last = numb;
|
|
142 extendCont( numb - cont.first + 1 );
|
|
143 cont.elem[ numb - cont.first ] = ov;
|
|
144 }
|
|
145 fclose( f );
|
|
146 }
|
|
147
|
|
148 void
|
|
149 Cont_write( void )
|
|
150 {
|
|
151 Bool anythingWritten;
|
|
152 int i, first;
|
|
153 FILE *f;
|
|
154 const Over *ov;
|
|
155
|
|
156 first = cont.first;
|
|
157 while ( ! Cont_validNumb( first ) && first <= cont.last )
|
|
158 ++first;
|
|
159 if ( ! ( f = fopen( cont.file, "w" ) ) )
|
|
160 {
|
|
161 Log_err( "Could not open %s for writing", cont.file );
|
|
162 return;
|
|
163 }
|
|
164 Log_dbg( "Writing %s (%lu)", cont.file, cont.size );
|
|
165 anythingWritten = FALSE;
|
|
166 for ( i = 0; i < cont.size; ++i )
|
|
167 {
|
|
168 if ( ( ov = cont.elem[ i ] ) )
|
|
169 {
|
|
170 if ( ! Pseudo_isGeneralInfo( Ov_msgId( ov ) ) )
|
|
171 {
|
|
172 if ( ! Ov_write( ov, f ) )
|
|
173 {
|
|
174 Log_err( "Writing of overview line failed" );
|
|
175 break;
|
|
176 }
|
|
177 else
|
|
178 anythingWritten = TRUE;
|
|
179 }
|
|
180 }
|
|
181 }
|
|
182 fclose( f );
|
|
183 if ( ! anythingWritten )
|
|
184 unlink( cont.file );
|
|
185 }
|
|
186
|
|
187 const Over *
|
|
188 Cont_get( int numb )
|
|
189 {
|
|
190 if ( ! Cont_validNumb( numb ) )
|
|
191 return NULL;
|
|
192 return cont.elem[ numb - cont.first ];
|
|
193 }
|
|
194
|
|
195 int
|
|
196 Cont_first( void ) { return cont.first; }
|
|
197
|
|
198 int
|
|
199 Cont_last( void ) { return cont.last; }
|
|
200
|
|
201 const char *
|
|
202 Cont_grp( void ) { return cont.name; }
|
|
203
|
|
204 Bool
|
|
205 Cont_nextGrp( Str result )
|
|
206 {
|
|
207 struct dirent *d;
|
|
208
|
|
209 ASSERT( cont.dir );
|
|
210 if ( ! ( d = readdir( cont.dir ) ) )
|
|
211 {
|
|
212 cont.dir = NULL;
|
|
213 return FALSE;
|
|
214 }
|
|
215 if ( ! d->d_name )
|
|
216 return FALSE;
|
|
217 Utl_cpyStr( result, d->d_name );
|
|
218 result[ MAXCHAR - 1 ] = '\0';
|
|
219 return TRUE;
|
|
220 }
|
|
221
|
|
222 Bool
|
|
223 Cont_firstGrp( Str result )
|
|
224 {
|
|
225 Str name;
|
|
226
|
|
227 snprintf( name, MAXCHAR, "%s/overview", Cfg_spoolDir() );
|
|
228 if ( ! ( cont.dir = opendir( name ) ) )
|
|
229 {
|
|
230 Log_err( "Cannot open %s", name );
|
|
231 return FALSE;
|
|
232 }
|
|
233 Cont_nextGrp( result ); /* "." */
|
|
234 Cont_nextGrp( result ); /* ".." */
|
|
235 return Cont_nextGrp( result );
|
|
236 }
|