Mercurial > noffle
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 } |