comparison 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
comparison
equal deleted inserted replaced
231:e7ee1bb9887b 232:6767c6f3218f
1 /* 1 /*
2 fetchlist.c 2 fetchlist.c
3 3
4 $Id: fetchlist.c 300 2001-08-05 08:24:22Z bears $ 4 $Id: fetchlist.c 363 2002-02-08 17:06:01Z 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
10 10
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <errno.h>
13 #include <unistd.h>
12 #include "fetchlist.h" 14 #include "fetchlist.h"
13 #include "configfile.h" 15 #include "configfile.h"
14 #include "log.h" 16 #include "log.h"
15 #include "util.h" 17 #include "util.h"
16 #include "portable.h" 18 #include "portable.h"
24 static struct Fetchlist 26 static struct Fetchlist
25 { 27 {
26 struct Elem *elem; 28 struct Elem *elem;
27 int size; 29 int size;
28 int max; 30 int max;
29 } fetchlist = { NULL, 0, 0 }; 31 Bool dirty;
30 32 } fetchlist = { NULL, 0, 0, FALSE };
31 static const char *
32 getFile( void )
33 {
34 static Str file;
35 snprintf( file, MAXCHAR, "%s/fetchlist", Cfg_spoolDir() );
36 return file;
37 }
38 33
39 static void 34 static void
40 clearList( void ) 35 clearList( void )
41 { 36 {
42 fetchlist.size = 0; 37 fetchlist.size = 0;
38 fetchlist.dirty = FALSE;
43 } 39 }
44 40
45 static int 41 static int
46 compareElem( const void *elem1, const void *elem2 ) 42 compareElem( const void *elem1, const void *elem2 )
47 { 43 {
85 81
86 void 82 void
87 Fetchlist_read( void ) 83 Fetchlist_read( void )
88 { 84 {
89 FILE *f; 85 FILE *f;
90 const char *file = getFile(); 86 Str file;
91 char *p; 87 char *p;
92 FetchMode mode = OVER; 88 FetchMode mode = OVER;
93 Bool valid; 89 Bool valid;
94 int ret; 90 int ret;
95 Str line, grp, modeStr; 91 Str line, grp, modeStr;
96 92
97 Log_dbg( LOG_DBG_FETCH, "Reading %s", file ); 93 Log_dbg( LOG_DBG_FETCH, "Reading %s", file );
94 snprintf( file, MAXCHAR, "%s/fetchlist", Cfg_spoolDir() );
98 clearList(); 95 clearList();
99 if ( ! ( f = fopen( file, "r" ) ) ) 96 if ( ! ( f = fopen( file, "r" ) ) )
100 { 97 {
101 Log_inf( "No file %s", file ); 98 Log_inf( "No file %s", file );
102 return; 99 return;
126 Log_err( "Invalid entry in %s: %s", file, line ); 123 Log_err( "Invalid entry in %s: %s", file, line );
127 continue; 124 continue;
128 } 125 }
129 appGrp( grp, mode ); 126 appGrp( grp, mode );
130 } 127 }
131 fclose( f ); 128 if ( ferror( f ) )
129 Log_err( "Error reading %s: %s", file, strerror( errno ) );
130 if ( fclose( f ) != 0 )
131 Log_err( "Error closing %s; %s", file, strerror( errno ) );
132 } 132 }
133 133
134 Bool 134 Bool
135 Fetchlist_write( void ) 135 Fetchlist_write( void )
136 { 136 {
137 int i; 137 int i;
138 FILE *f; 138 FILE *f;
139 const char *file = getFile(); 139 Str file, tmpfname;
140 const char *modeStr = ""; 140 const char *modeStr = "";
141 141 Bool res;
142
143 /* Any changes? */
144 if ( ! fetchlist.dirty )
145 return TRUE;
146
142 qsort( fetchlist.elem, (size_t)fetchlist.size, 147 qsort( fetchlist.elem, (size_t)fetchlist.size,
143 sizeof( fetchlist.elem[ 0 ] ), compareElem ); 148 sizeof( fetchlist.elem[ 0 ] ), compareElem );
144 if ( ! ( f = fopen( file, "w" ) ) ) 149
150 snprintf( file, MAXCHAR, "%s/fetchlist", Cfg_spoolDir() );
151 snprintf( tmpfname, MAXCHAR, "%s/.#%d.fetchlist",
152 Cfg_spoolDir(), (int) getpid() );
153
154 if ( ! ( f = fopen( tmpfname, "w" ) ) )
145 { 155 {
146 Log_err( "Could not open %s for writing", file ); 156 Log_err( "Could not open %s for writing", file );
147 return FALSE; 157 return FALSE;
148 } 158 }
159 res = TRUE;
149 for ( i = 0; i < fetchlist.size; ++i ) 160 for ( i = 0; i < fetchlist.size; ++i )
150 { 161 {
151 switch ( fetchlist.elem[ i ].mode ) 162 switch ( fetchlist.elem[ i ].mode )
152 { 163 {
153 case FULL: 164 case FULL:
156 modeStr = "thread"; break; 167 modeStr = "thread"; break;
157 case OVER: 168 case OVER:
158 modeStr = "over"; break; 169 modeStr = "over"; break;
159 } 170 }
160 fprintf( f, "%s %s\n", fetchlist.elem[ i ].name, modeStr ); 171 fprintf( f, "%s %s\n", fetchlist.elem[ i ].name, modeStr );
161 } 172 if ( ferror( f ) )
162 fclose( f ); 173 {
163 return TRUE; 174 Log_err( "Error writing %s: %s", tmpfname, strerror( errno ) );
175 clearerr( f );
176 res = FALSE;
177 }
178 }
179 if ( fclose( f ) != 0 )
180 {
181 Log_err( "Error closing %s: %s", tmpfname, strerror( errno ) );
182 res = FALSE;
183 }
184
185 if ( res )
186 {
187 if ( rename( tmpfname, file ) < 0 )
188 {
189 Log_err( "Rename of %s to %s failed: %s", tmpfname, file,
190 strerror( errno ) );
191 res = FALSE;
192 }
193 }
194
195 return res;
164 } 196 }
165 197
166 int 198 int
167 Fetchlist_size( void ) 199 Fetchlist_size( void )
168 { 200 {
187 219
188 Bool 220 Bool
189 Fetchlist_add( const char *name, FetchMode mode ) 221 Fetchlist_add( const char *name, FetchMode mode )
190 { 222 {
191 struct Elem *elem = searchElem( name ); 223 struct Elem *elem = searchElem( name );
224 fetchlist.dirty = TRUE;
192 if ( elem == NULL ) 225 if ( elem == NULL )
193 { 226 {
194 appGrp( name, mode ); 227 appGrp( name, mode );
195 return TRUE; 228 return TRUE;
196 } 229 }
203 Fetchlist_remove( const char *name ) 236 Fetchlist_remove( const char *name )
204 { 237 {
205 struct Elem *elem = searchElem( name ); 238 struct Elem *elem = searchElem( name );
206 if ( elem == NULL ) 239 if ( elem == NULL )
207 return FALSE; 240 return FALSE;
241 fetchlist.dirty = TRUE;
208 *elem = fetchlist.elem[ fetchlist.size - 1 ]; 242 *elem = fetchlist.elem[ fetchlist.size - 1 ];
209 --fetchlist.size; 243 --fetchlist.size;
210 return TRUE; 244 return TRUE;
211 } 245 }