Browse code

improve cdiff support

git-svn: trunk@2131

Tomasz Kojm authored on 2006/07/27 21:24:44
Showing 2 changed files
... ...
@@ -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();