git-svn: trunk@2131
Tomasz Kojm authored on 2006/07/27 21:24:44... | ... |
@@ -1,3 +1,9 @@ |
1 |
+Thu Jul 27 14:21:01 CEST 2006 (tk) |
|
2 |
+---------------------------------- |
|
3 |
+ * sigtool/sigtool.c: --build: automatically create and verify cdiff file |
|
4 |
+ --unpack-current, --verify-cdiff: add support for |
|
5 |
+ incremental directories |
|
6 |
+ |
|
1 | 7 |
Thu Jul 27 14:18:57 CEST 2006 (tk) |
2 | 8 |
---------------------------------- |
3 | 9 |
* shared/misc.c: add dircopy() |
... | ... |
@@ -314,14 +314,17 @@ static int writeinfo(const char *db, const char *header) |
314 | 314 |
return 0; |
315 | 315 |
} |
316 | 316 |
|
317 |
+static int diffdirs(const char *old, const char *new, const char *patch); |
|
318 |
+static int verifycdiff(const char *diff, const char *cvd, const char *incdir); |
|
319 |
+ |
|
317 | 320 |
static int build(struct optstruct *opt) |
318 | 321 |
{ |
319 |
- int ret; |
|
322 |
+ int ret, inc = 1; |
|
320 | 323 |
size_t bytes; |
321 | 324 |
unsigned int sigs = 0, lines = 0, version, real_header; |
322 | 325 |
struct stat foo; |
323 |
- char buffer[FILEBUFF], *tarfile, *gzfile, header[513], |
|
324 |
- smbuff[30], builder[32], *pt, *dbdir; |
|
326 |
+ char buffer[FILEBUFF], *tarfile, *gzfile, header[513], smbuff[32], |
|
327 |
+ builder[32], *pt, *dbname, olddb[512], patch[32], broken[32]; |
|
325 | 328 |
struct cl_node *root = NULL; |
326 | 329 |
FILE *tar, *cvd; |
327 | 330 |
gzFile *gz; |
... | ... |
@@ -351,8 +354,6 @@ static int build(struct optstruct *opt) |
351 | 351 |
return -1; |
352 | 352 |
} |
353 | 353 |
|
354 |
- cl_debug(); /* enable debug messages in libclamav */ |
|
355 |
- |
|
356 | 354 |
if((ret = cl_loaddbdir(".", &root, &sigs))) { |
357 | 355 |
mprintf("!build: Can't load database: %s\n", cl_strerror(ret)); |
358 | 356 |
return -1; |
... | ... |
@@ -381,10 +382,22 @@ static int build(struct optstruct *opt) |
381 | 381 |
} |
382 | 382 |
|
383 | 383 |
/* try to read cvd header of current database */ |
384 |
- dbdir = freshdbdir(); |
|
385 |
- snprintf(buffer, sizeof(buffer), "%s/%s", dbdir, opt_arg(opt, "build")); |
|
386 |
- free(dbdir); |
|
387 |
- if(!(oldcvd = cl_cvdhead(buffer))) { |
|
384 |
+ dbname = opt_arg(opt, "build"); |
|
385 |
+ if(strstr(dbname, "main")) |
|
386 |
+ dbname = "main"; |
|
387 |
+ else |
|
388 |
+ dbname = "daily"; |
|
389 |
+ |
|
390 |
+ pt = freshdbdir(); |
|
391 |
+ snprintf(olddb, sizeof(olddb), "%s/%s.inc/%s.info", pt, dbname, dbname); |
|
392 |
+ if(stat(olddb, &foo) == -1) { |
|
393 |
+ inc = 0; |
|
394 |
+ snprintf(olddb, sizeof(olddb), "%s/%s.cvd", pt, dbname); |
|
395 |
+ } |
|
396 |
+ |
|
397 |
+ free(pt); |
|
398 |
+ |
|
399 |
+ if(!(oldcvd = cl_cvdhead(olddb))) { |
|
388 | 400 |
mprintf("^build: CAN'T READ CVD HEADER OF CURRENT DATABASE %s\n", buffer); |
389 | 401 |
sleep(3); |
390 | 402 |
} |
... | ... |
@@ -440,13 +453,7 @@ static int build(struct optstruct *opt) |
440 | 440 |
/* add current time */ |
441 | 441 |
sprintf(header + strlen(header), ":%d", (int) timet); |
442 | 442 |
|
443 |
- pt = opt_arg(opt, "build"); |
|
444 |
- if(strstr(pt, "main")) |
|
445 |
- pt = "main"; |
|
446 |
- else |
|
447 |
- pt = "daily"; |
|
448 |
- |
|
449 |
- if(writeinfo(pt, header) == -1) { |
|
443 |
+ if(writeinfo(dbname, header) == -1) { |
|
450 | 444 |
mprintf("!build: Can't generate info file\n"); |
451 | 445 |
return -1; |
452 | 446 |
} |
... | ... |
@@ -472,6 +479,10 @@ static int build(struct optstruct *opt) |
472 | 472 |
"main.rmd", "daily.rmd", "main.fp", |
473 | 473 |
"daily.fp", "daily.info", "main.info", NULL }; |
474 | 474 |
args[2] = tarfile; |
475 |
+ if(!opt_check(opt, "debug")) { |
|
476 |
+ close(1); |
|
477 |
+ close(2); |
|
478 |
+ } |
|
475 | 479 |
execv("/bin/tar", args); |
476 | 480 |
mprintf("!build: Can't execute tar\n"); |
477 | 481 |
perror("tar"); |
... | ... |
@@ -616,19 +627,108 @@ static int build(struct optstruct *opt) |
616 | 616 |
|
617 | 617 |
mprintf("Database %s created\n", pt); |
618 | 618 |
|
619 |
- return 0; |
|
619 |
+ /* generate patch */ |
|
620 |
+ mprintf("Generating cdiff...\n"); |
|
621 |
+ if(inc) { |
|
622 |
+ pt = freshdbdir(); |
|
623 |
+ snprintf(olddb, sizeof(olddb), "%s/%s.inc", pt, dbname); |
|
624 |
+ free(pt); |
|
625 |
+ } else { |
|
626 |
+ pt = freshdbdir(); |
|
627 |
+ snprintf(olddb, sizeof(olddb), "%s/%s.cvd", pt, dbname); |
|
628 |
+ free(pt); |
|
629 |
+ |
|
630 |
+ pt = cli_gentemp(NULL); |
|
631 |
+ if(mkdir(pt, 0700)) { |
|
632 |
+ mprintf("!build: Can't create temporary directory %s\n", pt); |
|
633 |
+ return -1; |
|
634 |
+ } |
|
635 |
+ if(cvd_unpack(olddb, pt) == -1) { |
|
636 |
+ mprintf("!build: Can't unpack CVD file %s\n", olddb); |
|
637 |
+ rmdirs(pt); |
|
638 |
+ free(pt); |
|
639 |
+ return -1; |
|
640 |
+ } |
|
641 |
+ strncpy(olddb, pt, sizeof(olddb)); |
|
642 |
+ } |
|
643 |
+ |
|
644 |
+ pt = cli_gentemp(NULL); |
|
645 |
+ if(mkdir(pt, 0700)) { |
|
646 |
+ mprintf("!build: Can't create temporary directory %s\n", pt); |
|
647 |
+ free(pt); |
|
648 |
+ if(!inc) |
|
649 |
+ rmdirs(olddb); |
|
650 |
+ return -1; |
|
651 |
+ } |
|
652 |
+ if(cvd_unpack(opt_arg(opt, "build"), pt) == -1) { |
|
653 |
+ mprintf("!build: Can't unpack CVD file %s\n", opt_arg(opt, "build")); |
|
654 |
+ rmdirs(pt); |
|
655 |
+ free(pt); |
|
656 |
+ if(!inc) |
|
657 |
+ rmdirs(olddb); |
|
658 |
+ return -1; |
|
659 |
+ } |
|
660 |
+ |
|
661 |
+ if(!strcmp(dbname, "main")) |
|
662 |
+ snprintf(patch, sizeof(patch), "main-%u.cdiff", version); |
|
663 |
+ else |
|
664 |
+ snprintf(patch, sizeof(patch), "daily-%u.cdiff", version); |
|
665 |
+ |
|
666 |
+ ret = diffdirs(olddb, pt, patch); |
|
667 |
+ |
|
668 |
+ rmdirs(pt); |
|
669 |
+ free(pt); |
|
670 |
+ |
|
671 |
+ if(ret == -1) { |
|
672 |
+ if(!inc) |
|
673 |
+ rmdirs(olddb); |
|
674 |
+ return -1; |
|
675 |
+ } |
|
676 |
+ |
|
677 |
+ ret = verifycdiff(patch, NULL, olddb); |
|
678 |
+ |
|
679 |
+ if(!inc) |
|
680 |
+ rmdirs(olddb); |
|
681 |
+ |
|
682 |
+ if(ret == -1) { |
|
683 |
+ snprintf(broken, sizeof(broken), "%s.broken", patch); |
|
684 |
+ if(rename(patch, broken)) { |
|
685 |
+ unlink(patch); |
|
686 |
+ mprintf("!Generated file is incorrect, removed"); |
|
687 |
+ } else { |
|
688 |
+ mprintf("!Generated file is incorrect, renamed to %s\n", broken); |
|
689 |
+ } |
|
690 |
+ } |
|
691 |
+ |
|
692 |
+ return ret; |
|
620 | 693 |
} |
621 | 694 |
|
622 | 695 |
static int unpack(struct optstruct *opt) |
623 | 696 |
{ |
624 | 697 |
char *name, *dbdir; |
698 |
+ struct stat sb; |
|
625 | 699 |
|
626 | 700 |
|
627 | 701 |
if(opt_check(opt, "unpack-current")) { |
628 | 702 |
dbdir = freshdbdir(); |
629 |
- name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 2, sizeof(char)); |
|
630 |
- sprintf(name, "%s/%s", dbdir, opt_arg(opt, "unpack-current")); |
|
703 |
+ name = mcalloc(strlen(dbdir) + strlen(opt_arg(opt, "unpack-current")) + 32, sizeof(char)); |
|
704 |
+ sprintf(name, "%s/%s.inc", dbdir, opt_arg(opt, "unpack-current")); |
|
705 |
+ if(stat(name, &sb) != -1) { |
|
706 |
+ |
|
707 |
+ if(dircopy(name, ".") == -1) { |
|
708 |
+ mprintf("!unpack: Can't copy incremental directory %s to local directory\n", name); |
|
709 |
+ free(name); |
|
710 |
+ free(dbdir); |
|
711 |
+ return -1; |
|
712 |
+ } |
|
713 |
+ |
|
714 |
+ return 0; |
|
715 |
+ |
|
716 |
+ } else { |
|
717 |
+ sprintf(name, "%s/%s.cvd", dbdir, opt_arg(opt, "unpack-current")); |
|
718 |
+ } |
|
631 | 719 |
free(dbdir); |
720 |
+ |
|
632 | 721 |
} else |
633 | 722 |
name = strdup(opt_arg(opt, "unpack")); |
634 | 723 |
|
... | ... |
@@ -1044,9 +1144,10 @@ static int compare(const char *oldpath, const char *newpath, FILE *diff) |
1044 | 1044 |
return 0; |
1045 | 1045 |
} |
1046 | 1046 |
|
1047 |
-static int verifycdiff(const char *diff, const char *cvd) |
|
1047 |
+static int verifycdiff(const char *diff, const char *cvd, const char *incdir) |
|
1048 | 1048 |
{ |
1049 |
- char *tempdir, cwd[512], buff[1024], info[32], *pt, *md5; |
|
1049 |
+ char *tempdir, cwd[512], buff[1024], info[32], *md5, *pt; |
|
1050 |
+ const char *cpt; |
|
1050 | 1051 |
FILE *fh; |
1051 | 1052 |
int ret = 0, fd; |
1052 | 1053 |
|
... | ... |
@@ -1063,11 +1164,20 @@ static int verifycdiff(const char *diff, const char *cvd) |
1063 | 1063 |
return -1; |
1064 | 1064 |
} |
1065 | 1065 |
|
1066 |
- if(cvd_unpack(cvd, tempdir) == -1) { |
|
1067 |
- mprintf("!verifycdiff: Can't unpack CVD file %s\n", cvd); |
|
1068 |
- rmdirs(tempdir); |
|
1069 |
- free(tempdir); |
|
1070 |
- return -1; |
|
1066 |
+ if(cvd) { |
|
1067 |
+ if(cvd_unpack(cvd, tempdir) == -1) { |
|
1068 |
+ mprintf("!verifycdiff: Can't unpack CVD file %s\n", cvd); |
|
1069 |
+ rmdirs(tempdir); |
|
1070 |
+ free(tempdir); |
|
1071 |
+ return -1; |
|
1072 |
+ } |
|
1073 |
+ } else { |
|
1074 |
+ if(dircopy(incdir, tempdir) == -1) { |
|
1075 |
+ mprintf("!verifycdiff: Can't copy dir %s to %s\n", incdir, tempdir); |
|
1076 |
+ rmdirs(tempdir); |
|
1077 |
+ free(tempdir); |
|
1078 |
+ return -1; |
|
1079 |
+ } |
|
1071 | 1080 |
} |
1072 | 1081 |
|
1073 | 1082 |
if((fd = open(diff, O_RDONLY)) == -1) { |
... | ... |
@@ -1097,7 +1207,9 @@ static int verifycdiff(const char *diff, const char *cvd) |
1097 | 1097 |
} |
1098 | 1098 |
close(fd); |
1099 | 1099 |
|
1100 |
- if(strstr(cvd, "main.cvd")) |
|
1100 |
+ cvd ? (cpt = cvd) : (cpt = incdir); |
|
1101 |
+ |
|
1102 |
+ if(strstr(cpt, "main.cvd")) |
|
1101 | 1103 |
strcpy(info, "main.info"); |
1102 | 1104 |
else |
1103 | 1105 |
strcpy(info, "daily.info"); |
... | ... |
@@ -1145,20 +1257,76 @@ static int verifycdiff(const char *diff, const char *cvd) |
1145 | 1145 |
rmdirs(tempdir); |
1146 | 1146 |
free(tempdir); |
1147 | 1147 |
|
1148 |
- if(!ret) |
|
1149 |
- mprintf("Verification: %s correctly applies to %s\n", diff, cvd); |
|
1148 |
+ if(!ret) { |
|
1149 |
+ if(cvd) |
|
1150 |
+ mprintf("Verification: %s correctly applies to %s\n", diff, cvd); |
|
1151 |
+ else |
|
1152 |
+ mprintf("Verification: %s correctly applies to the previous version\n"); |
|
1153 |
+ } |
|
1150 | 1154 |
|
1151 | 1155 |
return ret; |
1152 | 1156 |
} |
1153 | 1157 |
|
1154 |
-static int makediff(struct optstruct *opt) |
|
1158 |
+static int diffdirs(const char *old, const char *new, const char *patch) |
|
1155 | 1159 |
{ |
1156 | 1160 |
FILE *diff; |
1157 | 1161 |
DIR *dd; |
1158 | 1162 |
struct dirent *dent; |
1159 |
- char *odir, *ndir, opath[1024], name[32], broken[32], cwd[512]; |
|
1163 |
+ char cwd[512], opath[1024]; |
|
1164 |
+ |
|
1165 |
+ |
|
1166 |
+ getcwd(cwd, sizeof(cwd)); |
|
1167 |
+ |
|
1168 |
+ if(!(diff = fopen(patch, "w"))) { |
|
1169 |
+ mprintf("!diffdirs: Can't open %s for writing\n", patch); |
|
1170 |
+ return -1; |
|
1171 |
+ } |
|
1172 |
+ |
|
1173 |
+ if(chdir(new) == -1) { |
|
1174 |
+ mprintf("!diffdirs: Can't chdir to %s\n", new); |
|
1175 |
+ fclose(diff); |
|
1176 |
+ return -1; |
|
1177 |
+ } |
|
1178 |
+ |
|
1179 |
+ if((dd = opendir(new)) == NULL) { |
|
1180 |
+ mprintf("!diffdirs: Can't open directory %s\n", new); |
|
1181 |
+ fclose(diff); |
|
1182 |
+ return -1; |
|
1183 |
+ } |
|
1184 |
+ |
|
1185 |
+ while((dent = readdir(dd))) { |
|
1186 |
+#ifndef C_INTERIX |
|
1187 |
+ if(dent->d_ino) |
|
1188 |
+#endif |
|
1189 |
+ { |
|
1190 |
+ if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) |
|
1191 |
+ continue; |
|
1192 |
+ |
|
1193 |
+ snprintf(opath, sizeof(opath), "%s/%s", old, dent->d_name); |
|
1194 |
+ if(compare(opath, dent->d_name, diff) == -1) { |
|
1195 |
+ fclose(diff); |
|
1196 |
+ unlink(patch); |
|
1197 |
+ closedir(dd); |
|
1198 |
+ return -1; |
|
1199 |
+ } |
|
1200 |
+ } |
|
1201 |
+ } |
|
1202 |
+ |
|
1203 |
+ closedir(dd); |
|
1204 |
+ |
|
1205 |
+ fclose(diff); |
|
1206 |
+ mprintf("Generated cdiff file %s\n", patch); |
|
1207 |
+ chdir(cwd); |
|
1208 |
+ |
|
1209 |
+ return 0; |
|
1210 |
+} |
|
1211 |
+ |
|
1212 |
+static int makediff(struct optstruct *opt) |
|
1213 |
+{ |
|
1214 |
+ char *odir, *ndir, name[32], broken[32]; |
|
1160 | 1215 |
struct cl_cvd *cvd; |
1161 | 1216 |
unsigned int oldver, newver; |
1217 |
+ int ret; |
|
1162 | 1218 |
|
1163 | 1219 |
|
1164 | 1220 |
if(!opt->filename) { |
... | ... |
@@ -1234,68 +1402,17 @@ static int makediff(struct optstruct *opt) |
1234 | 1234 |
else |
1235 | 1235 |
snprintf(name, sizeof(name), "daily-%u.cdiff", newver); |
1236 | 1236 |
|
1237 |
- getcwd(cwd, sizeof(cwd)); |
|
1238 |
- |
|
1239 |
- if(!(diff = fopen(name, "w"))) { |
|
1240 |
- mprintf("!makediff: Can't open %s for writing\n", name); |
|
1241 |
- rmdirs(odir); |
|
1242 |
- rmdirs(ndir); |
|
1243 |
- free(odir); |
|
1244 |
- free(ndir); |
|
1245 |
- return -1; |
|
1246 |
- } |
|
1247 |
- |
|
1248 |
- if(chdir(ndir) == -1) { |
|
1249 |
- mprintf("!makediff: Can't chdir to %s\n", ndir); |
|
1250 |
- rmdirs(odir); |
|
1251 |
- rmdirs(ndir); |
|
1252 |
- free(odir); |
|
1253 |
- free(ndir); |
|
1254 |
- fclose(diff); |
|
1255 |
- return -1; |
|
1256 |
- } |
|
1257 |
- |
|
1258 |
- if((dd = opendir(ndir)) == NULL) { |
|
1259 |
- mprintf("!makediff: Can't open directory %s\n", ndir); |
|
1260 |
- rmdirs(odir); |
|
1261 |
- rmdirs(ndir); |
|
1262 |
- free(odir); |
|
1263 |
- free(ndir); |
|
1264 |
- fclose(diff); |
|
1265 |
- return -1; |
|
1266 |
- } |
|
1267 |
- |
|
1268 |
- while((dent = readdir(dd))) { |
|
1269 |
-#ifndef C_INTERIX |
|
1270 |
- if(dent->d_ino) |
|
1271 |
-#endif |
|
1272 |
- { |
|
1273 |
- if(!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) |
|
1274 |
- continue; |
|
1237 |
+ ret = diffdirs(odir, ndir, name); |
|
1275 | 1238 |
|
1276 |
- snprintf(opath, sizeof(opath), "%s/%s", odir, dent->d_name); |
|
1277 |
- if(compare(opath, dent->d_name, diff) == -1) { |
|
1278 |
- rmdirs(odir); |
|
1279 |
- rmdirs(ndir); |
|
1280 |
- free(odir); |
|
1281 |
- free(ndir); |
|
1282 |
- fclose(diff); |
|
1283 |
- unlink(name); |
|
1284 |
- return -1; |
|
1285 |
- } |
|
1286 |
- } |
|
1287 |
- } |
|
1288 |
- |
|
1289 |
- fclose(diff); |
|
1290 | 1239 |
rmdirs(odir); |
1291 | 1240 |
rmdirs(ndir); |
1292 | 1241 |
free(odir); |
1293 | 1242 |
free(ndir); |
1294 |
- mprintf("Generated diff file %s\n", name); |
|
1295 | 1243 |
|
1296 |
- chdir(cwd); |
|
1244 |
+ if(ret == -1) |
|
1245 |
+ return -1; |
|
1297 | 1246 |
|
1298 |
- if(verifycdiff(name, opt_arg(opt, "diff")) == -1) { |
|
1247 |
+ if(verifycdiff(name, opt_arg(opt, "diff"), NULL) == -1) { |
|
1299 | 1248 |
snprintf(broken, sizeof(broken), "%s.broken", name); |
1300 | 1249 |
if(rename(name, broken)) { |
1301 | 1250 |
unlink(name); |
... | ... |
@@ -1329,14 +1446,14 @@ void help(void) |
1329 | 1329 |
mprintf(" --build=NAME -b NAME build a CVD file\n"); |
1330 | 1330 |
mprintf(" --server=ADDR ClamAV Signing Service address\n"); |
1331 | 1331 |
mprintf(" --unpack=FILE -u FILE Unpack a CVD file\n"); |
1332 |
- mprintf(" --unpack-current=NAME Unpack local CVD\n"); |
|
1332 |
+ mprintf(" --unpack-current=SHORTNAME Unpack local CVD/INCDIR in cwd\n"); |
|
1333 | 1333 |
mprintf(" --list-sigs[=FILE] -l[FILE] List signature names\n"); |
1334 | 1334 |
mprintf(" --vba=FILE Extract VBA/Word6 macro code\n"); |
1335 | 1335 |
mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n"); |
1336 | 1336 |
mprintf(" --vba-hex=FILE Extract Word6 macro code with hex values\n"); |
1337 | 1337 |
mprintf(" --diff=OLD NEW -d OLD NEW Create diff for OLD and NEW CVDs\n"); |
1338 | 1338 |
mprintf(" --run-cdiff=FILE -r FILE Execute update script FILE in cwd\n"); |
1339 |
- mprintf(" --verify-cdiff=DIFF CVD Verify DIFF against CVD\n"); |
|
1339 |
+ mprintf(" --verify-cdiff=DIFF CVD/INCDIR Verify DIFF against CVD\n"); |
|
1340 | 1340 |
mprintf("\n"); |
1341 | 1341 |
|
1342 | 1342 |
return; |
... | ... |
@@ -1372,7 +1489,6 @@ int main(int argc, char **argv) |
1372 | 1372 |
{0, 0, 0, 0} |
1373 | 1373 |
}; |
1374 | 1374 |
|
1375 |
- |
|
1376 | 1375 |
opt = opt_parse(argc, argv, short_options, long_options, NULL); |
1377 | 1376 |
if(!opt) { |
1378 | 1377 |
mprintf("!Can't parse the command line\n"); |
... | ... |
@@ -1424,10 +1540,13 @@ int main(int argc, char **argv) |
1424 | 1424 |
ret = runcdiff(opt); |
1425 | 1425 |
else if(opt_check(opt, "verify-cdiff")) { |
1426 | 1426 |
if(!opt->filename) { |
1427 |
- mprintf("!makediff: --diff requires two arguments\n"); |
|
1427 |
+ mprintf("!--verify-cdiff requires two arguments\n"); |
|
1428 | 1428 |
ret = -1; |
1429 | 1429 |
} else { |
1430 |
- ret = verifycdiff(opt_arg(opt, "verify-cdiff"), opt->filename); |
|
1430 |
+ if(cli_strbcasestr(opt->filename, ".cvd")) |
|
1431 |
+ ret = verifycdiff(opt_arg(opt, "verify-cdiff"), opt->filename, NULL); |
|
1432 |
+ else |
|
1433 |
+ ret = verifycdiff(opt_arg(opt, "verify-cdiff"), NULL, opt->filename); |
|
1431 | 1434 |
} |
1432 | 1435 |
} else |
1433 | 1436 |
help(); |