Browse code

freshclam: improve mirror management

Tomasz Kojm authored on 2010/11/16 00:04:55
Showing 4 changed files
... ...
@@ -1,3 +1,7 @@
1
+Mon Nov 15 16:04:31 CET 2010 (tk)
2
+---------------------------------
3
+ * freshclam: improve mirror management
4
+
1 5
 Fri Nov 12 15:47:09 CET 2010 (tk)
2 6
 ---------------------------------
3 7
  * libclamav: fix possible use of uninitialized values (bb#2291)
... ...
@@ -302,7 +302,7 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
302 302
 		    loadbal_rp = rp;
303 303
 		    strncpy(loadbal_ipaddr, ipaddr, sizeof(loadbal_ipaddr));
304 304
 		} else {
305
-		    if(md->succ < minsucc && md->fail <= minfail) {
305
+		    if(md->succ <= minsucc && md->fail <= minfail) {
306 306
 			minsucc = md->succ;
307 307
 			minfail = md->fail;
308 308
 			loadbal_rp = rp;
... ...
@@ -324,7 +324,12 @@ static int wwwconnect(const char *server, const char *proxy, int pport, char *ip
324 324
 	    }
325 325
 	    rp = loadbal_rp;
326 326
 	    strncpy(ipaddr, loadbal_ipaddr, sizeof(ipaddr));
327
-
327
+#ifdef SUPPORT_IPv6
328
+	    if(rp->ai_family == AF_INET6)
329
+		addr = &((struct sockaddr_in6 *) rp->ai_addr)->sin6_addr;
330
+	    else
331
+#endif
332
+		addr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;
328 333
 	} else if(loadbal_rp == rp) {
329 334
 	    i++;
330 335
 	    continue;
... ...
@@ -920,13 +925,13 @@ static struct cl_cvd *remote_cvdhead(const char *cvdfile, const char *localfile,
920 920
     return cvd;
921 921
 }
922 922
 
923
-static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const char *ims)
923
+static int getfile_mirman(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const char *ims, const char *ipaddr, int sd)
924 924
 {
925 925
 	char cmd[512], uastr[128], buffer[FILEBUFF], *ch;
926 926
 	int bread, fd, totalsize = 0,  rot = 0, totaldownloaded = 0,
927
-	    percentage = 0, sd;
927
+	    percentage = 0;
928 928
 	unsigned int i;
929
-	char *remotename = NULL, *authorization = NULL, *headerline, ipaddr[46];
929
+	char *remotename = NULL, *authorization = NULL, *headerline;
930 930
 	const char *rotation = "|/-\\", *fname;
931 931
 
932 932
 
... ...
@@ -973,24 +978,13 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
973 973
     if(authorization)
974 974
 	free(authorization);
975 975
 
976
-    memset(ipaddr, 0, sizeof(ipaddr));
977
-    if(ip && ip[0]) /* use ip to connect */
978
-	sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
979
-    else
980
-	sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
981
-
982
-    if(sd < 0) {
983
-	return 52;
984
-    } else {
985
-	logg("*Trying to download http://%s/%s (IP: %s)\n", hostname, srcfile, ipaddr);
986
-    }
976
+    logg("*Trying to download http://%s/%s (IP: %s)\n", hostname, srcfile, ipaddr);
987 977
 
988 978
     if(ip && !ip[0])
989 979
 	strcpy(ip, ipaddr);
990 980
 
991 981
     if(send(sd, cmd, strlen(cmd), 0) < 0) {
992 982
 	logg("%cgetfile: Can't write to socket\n", logerr ? '!' : '^');
993
-	closesocket(sd);
994 983
 	return 52;
995 984
     }
996 985
 
... ...
@@ -1007,7 +1001,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1007 1007
 	    logg("%cgetfile: Error while reading database from %s (IP: %s): %s\n", logerr ? '!' : '^', hostname, ipaddr, strerror(errno));
1008 1008
 	    if(mdat)
1009 1009
 		mirman_update(mdat->currip, mdat->af, mdat, 1);
1010
-	    closesocket(sd);
1011 1010
 	    return 52;
1012 1011
 	}
1013 1012
 
... ...
@@ -1026,7 +1019,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1026 1026
 	logg("^getfile: %s not found on remote server (IP: %s)\n", srcfile, ipaddr);
1027 1027
 	if(mdat)
1028 1028
 	    mirman_update(mdat->currip, mdat->af, mdat, 2);
1029
-	closesocket(sd);
1030 1029
 	return 58;
1031 1030
     }
1032 1031
 
... ...
@@ -1034,7 +1026,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1034 1034
     if(strstr(buffer, "HTTP/1.1 304") || strstr(buffer, "HTTP/1.0 304")) { 
1035 1035
 	if(mdat)
1036 1036
 	    mirman_update(mdat->currip, mdat->af, mdat, 0);
1037
-	closesocket(sd);
1038 1037
 	return 1;
1039 1038
     }
1040 1039
 
... ...
@@ -1043,7 +1034,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1043 1043
 	logg("%cgetfile: Unknown response from remote server (IP: %s)\n", logerr ? '!' : '^', ipaddr);
1044 1044
 	if(mdat)
1045 1045
 	    mirman_update(mdat->currip, mdat->af, mdat, 1);
1046
-	closesocket(sd);
1047 1046
 	return 58;
1048 1047
     }
1049 1048
 
... ...
@@ -1069,7 +1059,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1069 1069
 	    logg("!getfile: Can't create new file %s in the current directory\n", destfile);
1070 1070
 
1071 1071
 	logg("Hint: The database directory must be writable for UID %d or GID %d\n", getuid(), getgid());
1072
-	closesocket(sd);
1073 1072
 	return 57;
1074 1073
     }
1075 1074
 
... ...
@@ -1087,7 +1076,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1087 1087
 	    logg("getfile: Can't write %d bytes to %s\n", bread, destfile);
1088 1088
 	    unlink(destfile);
1089 1089
 	    close(fd);
1090
-	    closesocket(sd);
1091 1090
 	    return 57; /* FIXME */
1092 1091
 	}
1093 1092
 
... ...
@@ -1106,7 +1094,6 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1106 1106
             fflush(stdout);
1107 1107
         }
1108 1108
     }
1109
-    closesocket(sd);
1110 1109
     close(fd);
1111 1110
 
1112 1111
     if(bread == -1) {
... ...
@@ -1129,14 +1116,45 @@ static int getfile(const char *srcfile, const char *destfile, const char *hostna
1129 1129
     return 0;
1130 1130
 }
1131 1131
 
1132
-static int getcvd(const char *cvdfile, const char *newfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, unsigned int newver, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist)
1132
+static int getfile(const char *srcfile, const char *destfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const char *ims, const struct optstruct *opts)
1133
+{
1134
+	int ret, sd;
1135
+	char ipaddr[46];
1136
+
1137
+    memset(ipaddr, 0, sizeof(ipaddr));
1138
+    if(ip && ip[0]) /* use ip to connect */
1139
+	sd = wwwconnect(ip, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
1140
+    else
1141
+	sd = wwwconnect(hostname, proxy, port, ipaddr, localip, ctimeout, mdat, logerr, can_whitelist);
1142
+
1143
+    if(sd < 0)
1144
+	return 52;
1145
+
1146
+    if(mdat) {
1147
+	mirman_update_sf(mdat->currip, mdat->af, mdat, 0, 1);
1148
+	mirman_write("mirrors.dat", optget(opts, "DatabaseDirectory")->strarg, mdat);
1149
+    }
1150
+
1151
+    ret = getfile_mirman(srcfile, destfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, ims, ipaddr, sd);
1152
+    closesocket(sd);
1153
+
1154
+    if(mdat) {
1155
+	mirman_update_sf(mdat->currip, mdat->af, mdat, 0, -1);
1156
+	mirman_write("mirrors.dat", optget(opts, "DatabaseDirectory")->strarg, mdat);
1157
+    }
1158
+
1159
+    return ret;
1160
+}
1161
+
1162
+static int getcvd(const char *cvdfile, const char *newfile, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, unsigned int newver, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const struct optstruct *opts)
1133 1163
 {
1134 1164
 	struct cl_cvd *cvd;
1135 1165
 	int ret;
1136 1166
 
1137 1167
 
1138 1168
     logg("*Retrieving http://%s/%s\n", hostname, cvdfile);
1139
-    if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
1169
+
1170
+    if((ret = getfile(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL, opts))) {
1140 1171
         logg("%cCan't download %s from %s\n", logerr ? '!' : '^', cvdfile, hostname);
1141 1172
         unlink(newfile);
1142 1173
         return ret;
... ...
@@ -1201,7 +1219,7 @@ static int chdir_tmp(const char *dbname, const char *tmpdir)
1201 1201
     return 0;
1202 1202
 }
1203 1203
 
1204
-static int getpatch(const char *dbname, const char *tmpdir, int version, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist)
1204
+static int getpatch(const char *dbname, const char *tmpdir, int version, const char *hostname, char *ip, const char *localip, const char *proxy, int port, const char *user, const char *pass, const char *uas, int ctimeout, int rtimeout, struct mirdat *mdat, int logerr, unsigned int can_whitelist, const struct optstruct *opts)
1205 1205
 {
1206 1206
 	char *tempname, patch[32], olddir[512];
1207 1207
 	int ret, fd;
... ...
@@ -1219,7 +1237,7 @@ static int getpatch(const char *dbname, const char *tmpdir, int version, const c
1219 1219
     snprintf(patch, sizeof(patch), "%s-%d.cdiff", dbname, version);
1220 1220
 
1221 1221
     logg("*Retrieving http://%s/%s\n", hostname, patch);
1222
-    if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL))) {
1222
+    if((ret = getfile(patch, tempname, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, logerr, can_whitelist, NULL, opts))) {
1223 1223
 	if(ret == 53)
1224 1224
 	    logg("Empty script %s, need to download entire database\n", patch);
1225 1225
 	else
... ...
@@ -1731,7 +1749,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1731 1731
 
1732 1732
     newfile = cli_gentemp(updtmpdir);
1733 1733
     if(nodb) {
1734
-	ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist);
1734
+	ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist, opts);
1735 1735
 	if(ret) {
1736 1736
 	    memset(ip, 0, 16);
1737 1737
 	    free(newfile);
... ...
@@ -1749,7 +1767,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1749 1749
 		    int llogerr = logerr;
1750 1750
 		if(logerr)
1751 1751
 		    llogerr = (j == maxattempts - 1);
1752
-		ret = getpatch(dbname, tmpdir, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, llogerr, can_whitelist);
1752
+		ret = getpatch(dbname, tmpdir, i, hostname, ip, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, mdat, llogerr, can_whitelist, opts);
1753 1753
 		if(ret == 52 || ret == 58) {
1754 1754
 		    memset(ip, 0, 16);
1755 1755
 		    continue;
... ...
@@ -1767,7 +1785,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig
1767 1767
 	    if(ret != 53)
1768 1768
 		logg("^Incremental update failed, trying to download %s\n", cvdfile);
1769 1769
 	    mirman_whitelist(mdat, 2);
1770
-	    ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist);
1770
+	    ret = getcvd(cvdfile, newfile, hostname, ip, localip, proxy, port, user, pass, uas, newver, ctimeout, rtimeout, mdat, logerr, can_whitelist, opts);
1771 1771
 	    if(ret) {
1772 1772
 		free(newfile);
1773 1773
 		return ret;
... ...
@@ -1925,7 +1943,7 @@ static int updatecustomdb(const char *url, int *signo, const struct optstruct *o
1925 1925
 	    Rfc2822DateTime(mtime, sb.st_mtime);
1926 1926
 
1927 1927
 	newfile = cli_gentemp(updtmpdir);
1928
-	ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0, *mtime ? mtime : NULL);
1928
+	ret = getfile(rpath, newfile, host, NULL, localip, proxy, port, user, pass, uas, ctimeout, rtimeout, NULL, logerr, 0, *mtime ? mtime : NULL, opts);
1929 1929
 	if(ret == 1) {
1930 1930
 	    logg("%s is up to date (version: custom database)\n", dbname);
1931 1931
 	    unlink(newfile);
... ...
@@ -2138,7 +2156,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2138 2138
 	if(newver)
2139 2139
 	    free(newver);
2140 2140
 
2141
-	mirman_write("mirrors.dat", &mdat);
2141
+	mirman_write("mirrors.dat", dbdir, &mdat);
2142
+	mirman_free(&mdat);
2142 2143
 	cli_rmdirs(updtmpdir);
2143 2144
 	return ret;
2144 2145
 
... ...
@@ -2153,7 +2172,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2153 2153
 	if(newver)
2154 2154
 	    free(newver);
2155 2155
 
2156
-	mirman_write("mirrors.dat", &mdat);
2156
+	mirman_write("mirrors.dat", dbdir, &mdat);
2157
+	mirman_free(&mdat);
2157 2158
 	cli_rmdirs(updtmpdir);
2158 2159
 	return ret;
2159 2160
 
... ...
@@ -2182,7 +2202,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2182 2182
 	if(newver)
2183 2183
 	    free(newver);
2184 2184
 
2185
-	mirman_write("mirrors.dat", &mdat);
2185
+	mirman_write("mirrors.dat", dbdir, &mdat);
2186
+	mirman_free(&mdat);
2186 2187
 	cli_rmdirs(updtmpdir);
2187 2188
 	return ret;
2188 2189
     } else if(ret == 0)
... ...
@@ -2209,7 +2230,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2209 2209
 	if(newver)
2210 2210
 	    free(newver);
2211 2211
 
2212
-	mirman_write("mirrors.dat", &mdat);
2212
+	mirman_write("mirrors.dat", dbdir, &mdat);
2213
+	mirman_free(&mdat);
2213 2214
 	cli_rmdirs(updtmpdir);
2214 2215
 	return ret;
2215 2216
     } else if(ret == 0)
... ...
@@ -2223,7 +2245,8 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2223 2223
 	    if((ret = updatedb(opt->strarg, hostname, ipaddr, &signo, opts, NULL, localip, outdated, &mdat, logerr, 1)) > 50) {
2224 2224
 		if(newver)
2225 2225
 		    free(newver);
2226
-		mirman_write("mirrors.dat", &mdat);
2226
+		mirman_write("mirrors.dat", dbdir, &mdat);
2227
+		mirman_free(&mdat);
2227 2228
 		cli_rmdirs(updtmpdir);
2228 2229
 		return ret;
2229 2230
 	    } else if(ret == 0)
... ...
@@ -2232,6 +2255,10 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2232 2232
 	}
2233 2233
     }
2234 2234
 
2235
+    mirman_write("mirrors.dat", dbdir, &mdat);
2236
+    mirman_free(&mdat);
2237
+    cli_rmdirs(updtmpdir);
2238
+
2235 2239
     /* custom dbs */
2236 2240
     if((opt = optget(opts, "DatabaseCustomURL"))->enabled) {
2237 2241
 	while(opt) {
... ...
@@ -2241,9 +2268,6 @@ int downloadmanager(const struct optstruct *opts, const char *hostname, const ch
2241 2241
 	}
2242 2242
     }
2243 2243
 
2244
-    mirman_write("mirrors.dat", &mdat);
2245
-    cli_rmdirs(updtmpdir);
2246
-
2247 2244
     if(updated) {
2248 2245
 	if(optget(opts, "HTTPProxyServer")->enabled || !ipaddr[0]) {
2249 2246
 	    logg("Database updated (%d signatures) from %s\n", signo, hostname);
... ...
@@ -152,7 +152,7 @@ int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **m
152 152
     return 0;
153 153
 }
154 154
 
155
-int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
155
+static int mirman_update_int(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken, int succ, int fail)
156 156
 {
157 157
 	unsigned int i, found = 0;
158 158
 
... ...
@@ -169,24 +169,32 @@ int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
169 169
 
170 170
     if(found) {
171 171
 	mdat->mirtab[i].atime = 0; /* will be updated in mirman_write() */
172
-	if(broken)
173
-	    mdat->mirtab[i].fail++;
174
-	else
175
-	    mdat->mirtab[i].succ++;
176
-
177
-	if(broken == 2) {
178
-	    mdat->mirtab[i].ignore = 2;
172
+	if(succ || fail) {
173
+	    mdat->mirtab[i].fail += fail;
174
+	    if(mdat->mirtab[i].fail < 0)
175
+		mdat->mirtab[i].fail = 0;
176
+	    mdat->mirtab[i].succ += succ;
177
+	    if(mdat->mirtab[i].succ < 0)
178
+		mdat->mirtab[i].succ = 0;
179 179
 	} else {
180
-	    /*
181
-	     * If the total number of failures is less than 3 then never
182
-	     * mark a permanent failure, in other case use the real status.
183
-	     */
184
-	    if(mdat->mirtab[i].fail < 3)
185
-		mdat->mirtab[i].ignore = 0;
180
+	    if(broken)
181
+		mdat->mirtab[i].fail++;
186 182
 	    else
187
-		mdat->mirtab[i].ignore = broken;
183
+		mdat->mirtab[i].succ++;
184
+
185
+	    if(broken == 2) {
186
+		mdat->mirtab[i].ignore = 2;
187
+	    } else {
188
+		/*
189
+		 * If the total number of failures is less than 3 then never
190
+		 * mark a permanent failure, in other case use the real status.
191
+		 */
192
+		if(mdat->mirtab[i].fail < 3)
193
+		    mdat->mirtab[i].ignore = 0;
194
+		else
195
+		    mdat->mirtab[i].ignore = broken;
196
+	    }
188 197
 	}
189
-
190 198
     } else {
191 199
 	mdat->mirtab = (struct mirdat_ip *) realloc(mdat->mirtab, (mdat->num + 1) * sizeof(struct mirdat_ip));
192 200
 	if(!mdat->mirtab) {
... ...
@@ -200,20 +208,32 @@ int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
200 200
 	    memcpy(mdat->mirtab[mdat->num].ip6, ip, 4 * sizeof(uint32_t));
201 201
 	}
202 202
 	mdat->mirtab[mdat->num].atime = 0;
203
-	mdat->mirtab[mdat->num].succ = 0;
204
-	mdat->mirtab[mdat->num].fail = 0;
203
+	mdat->mirtab[mdat->num].succ = (succ > 0) ? succ : 0;
204
+	mdat->mirtab[mdat->num].fail = (fail > 0) ? fail : 0;
205 205
 	mdat->mirtab[mdat->num].ignore = (broken == 2) ? 2 : 0;
206 206
 	memset(&mdat->mirtab[mdat->num].res, 0xff, sizeof(mdat->mirtab[mdat->num].res));
207
-	if(broken)
208
-	    mdat->mirtab[mdat->num].fail++;
209
-	else
210
-	    mdat->mirtab[mdat->num].succ++;
207
+	if(!succ && !fail) {
208
+	    if(broken)
209
+		mdat->mirtab[mdat->num].fail++;
210
+	    else
211
+		mdat->mirtab[mdat->num].succ++;
212
+	}
211 213
 	mdat->num++;
212 214
     }
213 215
 
214 216
     return 0;
215 217
 }
216 218
 
219
+int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken)
220
+{
221
+    return mirman_update_int(ip, af, mdat, broken, 0, 0);
222
+}
223
+
224
+int mirman_update_sf(uint32_t *ip, int af, struct mirdat *mdat, int succ, int fail)
225
+{
226
+    return mirman_update_int(ip, af, mdat, 0, succ, fail);
227
+}
228
+
217 229
 void mirman_list(const struct mirdat *mdat)
218 230
 {
219 231
 	unsigned int i;
... ...
@@ -252,18 +272,20 @@ void mirman_whitelist(struct mirdat *mdat, unsigned int mode)
252 252
 	    mdat->mirtab[i].ignore = 0;
253 253
 }
254 254
 
255
-int mirman_write(const char *file, struct mirdat *mdat)
255
+int mirman_write(const char *file, const char *dir, struct mirdat *mdat)
256 256
 {
257 257
 	int fd;
258 258
 	unsigned int i;
259
+	char path[512];
259 260
 
261
+    snprintf(path, sizeof(path), "%s/%s", dir, file);
262
+    path[sizeof(path) - 1] = 0;
260 263
 
261 264
     if(!mdat->num)
262 265
 	return 0;
263 266
 
264
-    if((fd = open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) == -1) {
265
-	logg("!Can't open %s for writing\n", file);
266
-	mirman_free(mdat);
267
+    if((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600)) == -1) {
268
+	logg("!Can't open %s for writing\n", path);
267 269
 	return -1;
268 270
     }
269 271
 
... ...
@@ -272,13 +294,11 @@ int mirman_write(const char *file, struct mirdat *mdat)
272 272
 	    mdat->mirtab[i].atime = (uint32_t) time(NULL);
273 273
 
274 274
     if(write(fd, mdat->mirtab, mdat->num * sizeof(struct mirdat_ip)) == -1) {
275
-	logg("!Can't write to %s\n", file);
276
-	mirman_free(mdat);
275
+	logg("!Can't write to %s\n", path);
277 276
 	close(fd);
278 277
 	return -1;
279 278
     }
280 279
 
281
-    mirman_free(mdat);
282 280
     close(fd);
283 281
     return 0;
284 282
 }
... ...
@@ -43,9 +43,10 @@ struct mirdat {
43 43
 int mirman_read(const char *file, struct mirdat *mdat, uint8_t active);
44 44
 int mirman_check(uint32_t *ip, int af, struct mirdat *mdat, struct mirdat_ip **md);
45 45
 int mirman_update(uint32_t *ip, int af, struct mirdat *mdat, uint8_t broken);
46
+int mirman_update_sf(uint32_t *ip, int af, struct mirdat *mdat, int succ, int fail);
46 47
 void mirman_list(const struct mirdat *mdat);
47 48
 void mirman_whitelist(struct mirdat *mdat, unsigned int mode);
48
-int mirman_write(const char *file, struct mirdat *mdat);
49
+int mirman_write(const char *file, const char *dir, struct mirdat *mdat);
49 50
 void mirman_free(struct mirdat *mdat);
50 51
 
51 52
 #endif