cache over 256 trees

aCaB authored on 2009/08/11 19:23:14
Showing 10 changed files
... ...
@@ -304,6 +304,8 @@ int main(int argc, char **argv)
304 304
 	break;
305 305
     }
306 306
 
307
+    cache_init(256);
308
+
307 309
     if(!(engine = cl_engine_new())) {
308 310
 	logg("!Can't initialize antivirus engine\n");
309 311
 	ret = 1;
... ...
@@ -169,6 +169,8 @@ int main(int argc, char **argv)
169 169
     gettimeofday(&t1, &tz);
170 170
 #endif
171 171
 
172
+    cache_init(256);
173
+
172 174
     ret = scanmanager(opts);
173 175
 
174 176
     if(!optget(opts, "no-summary")->enabled) {
... ...
@@ -323,7 +323,9 @@ libclamav_la_SOURCES = \
323 323
 	macho.c \
324 324
 	macho.h \
325 325
 	ishield.c \
326
-	ishield.h
326
+	ishield.h \
327
+	cache.c \
328
+	cache.h
327 329
 
328 330
 if !LINK_TOMMATH
329 331
 libclamav_la_SOURCES += bignum.c \
... ...
@@ -131,7 +131,7 @@ am__libclamav_la_SOURCES_DIST = clamav.h matcher-ac.c matcher-ac.h \
131 131
 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
132 132
 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
133 133
 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
134
-	ishield.c ishield.h bignum.c bignum_class.h
134
+	ishield.c ishield.h cache.c cache.h bignum.c bignum_class.h
135 135
 @LINK_TOMMATH_FALSE@am__objects_1 = libclamav_la-bignum.lo
136 136
 am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
137 137
 	libclamav_la-matcher-bm.lo libclamav_la-matcher.lo \
... ...
@@ -177,7 +177,8 @@ am_libclamav_la_OBJECTS = libclamav_la-matcher-ac.lo \
177 177
 	libclamav_la-version.lo libclamav_la-mpool.lo \
178 178
 	libclamav_la-sha256.lo libclamav_la-bytecode.lo \
179 179
 	libclamav_la-bytecode_vm.lo libclamav_la-cpio.lo \
180
-	libclamav_la-macho.lo libclamav_la-ishield.lo $(am__objects_1)
180
+	libclamav_la-macho.lo libclamav_la-ishield.lo \
181
+	libclamav_la-cache.lo $(am__objects_1)
181 182
 libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS)
182 183
 libclamav_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
183 184
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libclamav_la_CFLAGS) \
... ...
@@ -547,7 +548,7 @@ libclamav_la_SOURCES = clamav.h matcher-ac.c matcher-ac.h matcher-bm.c \
547 547
 	uniq.h version.c version.h mpool.c mpool.h default.h sha256.c \
548 548
 	sha256.h bignum.h bytecode.c bytecode.h bytecode_vm.c \
549 549
 	bytecode_priv.h clambc.h cpio.c cpio.h macho.c macho.h \
550
-	ishield.c ishield.h $(am__append_7)
550
+	ishield.c ishield.h cache.c cache.h $(am__append_7)
551 551
 noinst_LTLIBRARIES = libclamav_internal_utils.la libclamav_internal_utils_nothreads.la
552 552
 COMMON_CLEANFILES = version.h version.h.tmp *.gcda *.gcno
553 553
 @MAINTAINER_MODE_TRUE@BUILT_SOURCES = jsparse/generated/operators.h jsparse/generated/keywords.h jsparse-keywords.gperf
... ...
@@ -681,6 +682,7 @@ distclean-compile:
681 681
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-bytecode_vm.Plo@am__quote@
682 682
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-bzlib.Plo@am__quote@
683 683
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-cab.Plo@am__quote@
684
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-cache.Plo@am__quote@
684 685
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-chmunpack.Plo@am__quote@
685 686
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-cpio.Plo@am__quote@
686 687
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libclamav_la-cvd.Plo@am__quote@
... ...
@@ -1417,6 +1419,13 @@ libclamav_la-ishield.lo: ishield.c
1417 1417
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1418 1418
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-ishield.lo `test -f 'ishield.c' || echo '$(srcdir)/'`ishield.c
1419 1419
 
1420
+libclamav_la-cache.lo: cache.c
1421
+@am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-cache.lo -MD -MP -MF $(DEPDIR)/libclamav_la-cache.Tpo -c -o libclamav_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
1422
+@am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libclamav_la-cache.Tpo $(DEPDIR)/libclamav_la-cache.Plo
1423
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='cache.c' object='libclamav_la-cache.lo' libtool=yes @AMDEPBACKSLASH@
1424
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1425
+@am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -c -o libclamav_la-cache.lo `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
1426
+
1420 1427
 libclamav_la-bignum.lo: bignum.c
1421 1428
 @am__fastdepCC_TRUE@	$(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libclamav_la_CFLAGS) $(CFLAGS) -MT libclamav_la-bignum.lo -MD -MP -MF $(DEPDIR)/libclamav_la-bignum.Tpo -c -o libclamav_la-bignum.lo `test -f 'bignum.c' || echo '$(srcdir)/'`bignum.c
1422 1429
 @am__fastdepCC_TRUE@	mv -f $(DEPDIR)/libclamav_la-bignum.Tpo $(DEPDIR)/libclamav_la-bignum.Plo
1423 1430
new file mode 100644
... ...
@@ -0,0 +1,186 @@
0
+#include <string.h>
1
+#include <stdlib.h>
2
+#include <pthread.h>
3
+
4
+#include "md5.h"
5
+#include "mpool.h"
6
+#include "clamav.h"
7
+#include "cache.h"
8
+
9
+#if HAVE_CONFIG_H
10
+#include "clamav-config.h"
11
+#endif
12
+
13
+#define CACHE_PERTURB 10
14
+/* 1/10th */
15
+
16
+static mpool_t *mempool = NULL;
17
+static struct CACHE {
18
+    struct CACHE_ENTRY {
19
+	unsigned char hash[15];
20
+	uint32_t dbver;
21
+	uint32_t hits;
22
+    } *items;
23
+    pthread_mutex_t mutex;
24
+    uint32_t lastdb;
25
+} *cache = NULL;
26
+static unsigned int cache_entries = 0;
27
+
28
+int cache_init(unsigned int entries) {
29
+    unsigned int i;
30
+
31
+    if(!(mempool = mpool_create())) {
32
+	cli_errmsg("mpool init fail\n");
33
+	return 1;
34
+    }
35
+    if(!(cache = mpool_malloc(mempool, sizeof(struct CACHE) * 256))) {
36
+	cli_errmsg("mpool malloc fail\n");
37
+	mpool_destroy(mempool);
38
+	return 1;
39
+    }
40
+
41
+    for(i=0; i<256; i++) {
42
+	struct CACHE_ENTRY *e = mpool_calloc(mempool, sizeof(struct CACHE_ENTRY), entries);
43
+	if(!e) {
44
+	    cli_errmsg("mpool calloc fail\n");
45
+	    mpool_destroy(mempool);
46
+	    return 1;
47
+	}
48
+	cache[i].items = e;
49
+	cache[i].lastdb = 0;
50
+	if(pthread_mutex_init(&cache[i].mutex, NULL)) {
51
+	    cli_errmsg("mutex init fail\n");
52
+	    mpool_destroy(mempool);
53
+	    return 1;
54
+	}
55
+    }
56
+    cache_entries = entries;
57
+    return 0;
58
+}
59
+
60
+void cache_swap(struct CACHE_ENTRY *e, unsigned int a) {
61
+    struct CACHE_ENTRY t;
62
+    unsigned int b = a-1;
63
+
64
+    if(!a || e[a].hits <= e[b].hits)
65
+	return;
66
+
67
+    do {
68
+	if(e[a].hits > e[b].hits)
69
+	    continue;
70
+	break;
71
+    } while(b--);
72
+    b++;
73
+
74
+    memcpy(&t, &e[a], sizeof(t));
75
+    memcpy(&e[a], &e[b], sizeof(t));
76
+    memcpy(&e[b], &t, sizeof(t));
77
+}
78
+
79
+void updb(uint32_t db, unsigned int skip) {
80
+    unsigned int i;
81
+    for(i=0; i<256; i++) {
82
+	if(i==skip) continue;
83
+	if(pthread_mutex_lock(&cache[i].mutex)) {
84
+	    cli_errmsg("mutex lock fail\n");
85
+	    continue;
86
+	}
87
+	cache[i].lastdb = db;
88
+	pthread_mutex_unlock(&cache[i].mutex);	
89
+    }
90
+}
91
+
92
+int cache_check(unsigned char *md5, cli_ctx *ctx) {
93
+    unsigned int i;
94
+    int ret = CL_VIRUS;
95
+    struct CACHE_ENTRY *e;
96
+    struct CACHE *c;
97
+
98
+    if(!cache) return ret;
99
+
100
+    c = &cache[*md5];
101
+    e = c->items;
102
+    if(pthread_mutex_lock(&c->mutex)) {
103
+	cli_errmsg("mutex lock fail\n");
104
+	return ret;
105
+    }
106
+    if(c->lastdb <= ctx->engine->dbversion[0]) {
107
+	if(c->lastdb < ctx->engine->dbversion[0]) {
108
+	    c->lastdb = ctx->engine->dbversion[0];
109
+	    updb(c->lastdb, *md5);
110
+	} else {
111
+	    for(i=0; i<cache_entries; i++) {
112
+		if(!e[i].hits) break;
113
+		if(e[i].dbver == c->lastdb && !memcmp(e[i].hash, md5 + 1, 15)) {
114
+		    e[i].hits++;
115
+		    cache_swap(e, i);
116
+		    ret = CL_CLEAN;
117
+		    cli_warnmsg("cached\n");
118
+		    break;
119
+		}
120
+	    }
121
+	}
122
+    }
123
+    pthread_mutex_unlock(&c->mutex);
124
+    return ret;
125
+}
126
+
127
+void cache_add(unsigned char *md5, cli_ctx *ctx) {
128
+    unsigned int i, replace;
129
+    struct CACHE_ENTRY *e;
130
+    struct CACHE *c;
131
+
132
+    if(!cache) return;
133
+
134
+    c = &cache[*md5];
135
+    e = c->items;
136
+    if(pthread_mutex_lock(&c->mutex)) {
137
+	cli_errmsg("mutex lock fail\n");
138
+	return;
139
+    }
140
+    if(c->lastdb == ctx->engine->dbversion[0]) {
141
+	replace = cache_entries;
142
+	for(i=0; i<cache_entries; i++) {
143
+	    if(!e[i].hits) break;
144
+	    if(replace == cache_entries && e[i].dbver < c->lastdb) {
145
+		replace = i;
146
+	    } else if(e[i].hits && !memcmp(e[i].hash, md5 + 1, 15)) {
147
+		e[i].hits++;
148
+		cache_swap(e, i);
149
+		pthread_mutex_unlock(&c->mutex);
150
+		return;
151
+	    }
152
+	}
153
+	if(replace == cache_entries)
154
+	    replace = cache_entries - 1 - (rand() % (cache_entries / CACHE_PERTURB));
155
+	e[replace].hits = 1;
156
+	e[replace].dbver = c->lastdb;
157
+	memcpy(e[replace].hash, md5 + 1, 15);
158
+	cache_swap(e, replace);
159
+    }
160
+    pthread_mutex_unlock(&c->mutex);
161
+    return;
162
+}
163
+
164
+int cache_chekdesc(int desc, size_t size, unsigned char *hash, cli_ctx *ctx) {
165
+    cli_md5_ctx md5;
166
+    unsigned char buf[8192];
167
+    
168
+    off_t seekback = lseek(desc, 0, SEEK_CUR);
169
+
170
+    if(!cache) return CL_VIRUS;
171
+
172
+    cli_md5_init(&md5);
173
+    while(size) {
174
+	size_t readme = size < sizeof(buf) ? size : sizeof(buf);
175
+	if(cli_readn(desc, buf, readme)!=readme) {
176
+	    lseek(desc, seekback, SEEK_SET);
177
+	    return CL_VIRUS;
178
+	}
179
+	cli_md5_update(&md5, buf, readme);
180
+	size-=readme;
181
+    }
182
+    cli_md5_final(hash, &md5);
183
+    lseek(desc, seekback, SEEK_SET);
184
+    return cache_check(hash, ctx);
185
+}
0 186
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+#ifndef __CACHE_H
1
+#define __CACHE_H
2
+
3
+#include "others.h"
4
+
5
+int cache_init(unsigned int entries);
6
+int cache_check(unsigned char *md5, cli_ctx *ctx);
7
+void cache_add(unsigned char *md5, cli_ctx *ctx);
8
+int cache_chekdesc(int desc, size_t size, unsigned char *hash, cli_ctx *ctx);
9
+
10
+#endif
... ...
@@ -154,6 +154,7 @@ CLAMAV_PRIVATE {
154 154
     cli_bytecode_context_setparam_ptr;
155 155
     cli_bytecode_context_getresult_int;
156 156
     cli_bytecode_context_clear;
157
+    cache_init;
157 158
   local:
158 159
     *;
159 160
 };
... ...
@@ -445,3 +445,173 @@ int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struc
445 445
 
446 446
     return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
447 447
 }
448
+
449
+int cli_scandesc_hash(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *digest)
450
+{
451
+ 	unsigned char *buffer, *buff, *endbl, *upt;
452
+	int ret = CL_CLEAN, type = CL_CLEAN, bytes;
453
+	unsigned int i, evalcnt;
454
+	uint32_t buffersize, length, maxpatlen, shift = 0, offset = 0;
455
+	uint64_t evalids;
456
+	struct cli_ac_data gdata, tdata;
457
+	struct cli_matcher *groot = NULL, *troot = NULL;
458
+
459
+
460
+    if(!ctx->engine) {
461
+	cli_errmsg("cli_scandesc: engine == NULL\n");
462
+	return CL_ENULLARG;
463
+    }
464
+
465
+    if(!ftonly)
466
+	groot = ctx->engine->root[0]; /* generic signatures */
467
+
468
+    if(ftype) {
469
+	for(i = 1; i < CLI_MTARGETS; i++) {
470
+	    if(cli_mtargets[i].target == ftype) {
471
+		troot = ctx->engine->root[i];
472
+		break;
473
+	    }
474
+	}
475
+    }
476
+
477
+    if(ftonly) {
478
+	if(!troot)
479
+	    return CL_CLEAN;
480
+
481
+	maxpatlen = troot->maxpatlen;
482
+    } else {
483
+	if(troot)
484
+	    maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
485
+	else
486
+	    maxpatlen = groot->maxpatlen;
487
+    }
488
+
489
+    /* prepare the buffer */
490
+    buffersize = maxpatlen + SCANBUFF;
491
+    if(!(buffer = (unsigned char *) cli_calloc(buffersize, sizeof(unsigned char)))) {
492
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%u)\n", buffersize);
493
+	return CL_EMEM;
494
+    }
495
+
496
+    if(!ftonly && (ret = cli_ac_initdata(&gdata, groot->ac_partsigs, groot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
497
+	return ret;
498
+
499
+    if(troot) {
500
+	if((ret = cli_ac_initdata(&tdata, troot->ac_partsigs, troot->ac_lsigs, CLI_DEFAULT_AC_TRACKLEN)))
501
+	    return ret;
502
+    }
503
+
504
+    buff = buffer;
505
+    buff += maxpatlen; /* pointer to read data block */
506
+    endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
507
+					  * length of maxpatlen
508
+					  */
509
+
510
+    upt = buff;
511
+    while((bytes = cli_readn(desc, buff + shift, SCANBUFF - shift)) > 0) {
512
+
513
+	if(ctx->scanned)
514
+	    *ctx->scanned += bytes / CL_COUNT_PRECISION;
515
+
516
+	length = shift + bytes;
517
+	if(upt == buffer)
518
+	    length += maxpatlen;
519
+
520
+	if(troot) {
521
+	    if(troot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, troot, offset, ftype, desc)) != CL_VIRUS)
522
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, troot, &tdata, offset, ftype, desc, ftoffset, acmode, NULL);
523
+
524
+	    if(ret == CL_VIRUS) {
525
+		free(buffer);
526
+		if(!ftonly)
527
+		    cli_ac_freedata(&gdata);
528
+		cli_ac_freedata(&tdata);
529
+
530
+		if(cli_checkfp(desc, ctx))
531
+		    return CL_CLEAN;
532
+		else
533
+		    return CL_VIRUS;
534
+	    }
535
+	}
536
+
537
+	if(!ftonly) {
538
+	    if(groot->ac_only || (ret = cli_bm_scanbuff(upt, length, ctx->virname, groot, offset, ftype, desc)) != CL_VIRUS)
539
+		ret = cli_ac_scanbuff(upt, length, ctx->virname, NULL, NULL, groot, &gdata, offset, ftype, desc, ftoffset, acmode, NULL);
540
+
541
+	    if(ret == CL_VIRUS) {
542
+		free(buffer);
543
+		cli_ac_freedata(&gdata);
544
+		if(troot)
545
+		    cli_ac_freedata(&tdata);
546
+		if(cli_checkfp(desc, ctx))
547
+		    return CL_CLEAN;
548
+		else
549
+		    return CL_VIRUS;
550
+
551
+	    } else if((acmode & AC_SCAN_FT) && ret >= CL_TYPENO) {
552
+		if(ret > type)
553
+		    type = ret;
554
+	    }
555
+	}
556
+
557
+	if(bytes + shift == SCANBUFF) {
558
+	    memmove(buffer, endbl, maxpatlen);
559
+	    offset += SCANBUFF;
560
+
561
+	    if(upt == buff) {
562
+		upt = buffer;
563
+		offset -= maxpatlen;
564
+	    }
565
+
566
+	    shift = 0;
567
+
568
+	} else {
569
+	    shift += bytes;
570
+	}
571
+    }
572
+
573
+    free(buffer);
574
+
575
+    if(troot) {
576
+	for(i = 0; i < troot->ac_lsigs; i++) {
577
+	    evalcnt = 0;
578
+	    evalids = 0;
579
+	    if(cli_ac_chklsig(troot->ac_lsigtable[i]->logic, troot->ac_lsigtable[i]->logic + strlen(troot->ac_lsigtable[i]->logic), tdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
580
+		if(ctx->virname)
581
+		    *ctx->virname = troot->ac_lsigtable[i]->virname;
582
+		ret = CL_VIRUS;
583
+		break;
584
+	    }
585
+	}
586
+	cli_ac_freedata(&tdata);
587
+    }
588
+
589
+    if(groot) {
590
+	if(ret != CL_VIRUS) for(i = 0; i < groot->ac_lsigs; i++) {
591
+	    evalcnt = 0;
592
+	    evalids = 0;
593
+	    if(cli_ac_chklsig(groot->ac_lsigtable[i]->logic, groot->ac_lsigtable[i]->logic + strlen(groot->ac_lsigtable[i]->logic), gdata.lsigcnt[i], &evalcnt, &evalids, 0) == 1) {
594
+		if(ctx->virname)
595
+		    *ctx->virname = groot->ac_lsigtable[i]->virname;
596
+		ret = CL_VIRUS;
597
+		break;
598
+	    }
599
+	}
600
+	cli_ac_freedata(&gdata);
601
+    }
602
+
603
+    if(ret == CL_VIRUS) {
604
+	lseek(desc, 0, SEEK_SET);
605
+	if(cli_checkfp(desc, ctx))
606
+	    return CL_CLEAN;
607
+	else
608
+	    return CL_VIRUS;
609
+    }
610
+
611
+    if(!ftonly && ctx->engine->md5_hdb) {
612
+	if(cli_bm_scanbuff(digest, 16, ctx->virname, ctx->engine->md5_hdb, 0, 0, -1) == CL_VIRUS && (cli_bm_scanbuff(digest, 16, NULL, ctx->engine->md5_fp, 0, 0, -1) != CL_VIRUS))
613
+	    return CL_VIRUS;
614
+    }
615
+
616
+    return (acmode & AC_SCAN_FT) ? type : CL_CLEAN;
617
+}
... ...
@@ -127,6 +127,7 @@ struct cli_target_info {
127 127
 int cli_scanbuff(const unsigned char *buffer, uint32_t length, uint32_t offset, cli_ctx *ctx, cli_file_t ftype, struct cli_ac_data **acdata);
128 128
 
129 129
 int cli_scandesc(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode);
130
+int cli_scandesc_hash(int desc, cli_ctx *ctx, cli_file_t ftype, uint8_t ftonly, struct cli_matched_type **ftoffset, unsigned int acmode, unsigned char *digest);
130 131
 
131 132
 int cli_validatesig(cli_file_t ftype, const char *offstr, off_t fileoff, struct cli_target_info *info, int desc, const char *virname);
132 133
 
... ...
@@ -96,6 +96,7 @@
96 96
 #include "macho.h"
97 97
 #include "ishield.h"
98 98
 #include "7z.h"
99
+#include "cache.h"
99 100
 
100 101
 #ifdef HAVE_BZLIB_H
101 102
 #include <bzlib.h>
... ...
@@ -1881,6 +1882,7 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1881 1881
 	cli_file_t type, dettype = 0;
1882 1882
 	struct stat sb;
1883 1883
 	uint8_t typercg = 1;
1884
+	unsigned char hash[16];
1884 1885
 
1885 1886
     if(ctx->engine->maxreclevel && ctx->recursion > ctx->engine->maxreclevel) {
1886 1887
         cli_dbgmsg("cli_magic_scandesc: Archive recursion limit exceeded (%u, max: %u)\n", ctx->recursion, ctx->engine->maxreclevel);
... ...
@@ -1910,13 +1912,17 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
1910 1910
     if(cli_updatelimits(ctx, sb.st_size)!=CL_CLEAN)
1911 1911
         return CL_CLEAN;
1912 1912
 
1913
+    if(cache_chekdesc(desc, sb.st_size, hash, ctx) == CL_CLEAN)
1914
+	return CL_CLEAN;
1915
+    
1913 1916
     if(!ctx->options || (ctx->recursion == ctx->engine->maxreclevel)) { /* raw mode (stdin, etc.) or last level of recursion */
1914 1917
 	if(ctx->recursion == ctx->engine->maxreclevel)
1915 1918
 	    cli_dbgmsg("cli_magic_scandesc: Hit recursion limit, only scanning raw file\n");
1916 1919
 	else
1917 1920
 	    cli_dbgmsg("Raw mode: No support for special files\n");
1918
-	if((ret = cli_scandesc(desc, ctx, 0, 0, NULL, AC_SCAN_VIR)) == CL_VIRUS)
1921
+	if((ret = cli_scandesc_hash(desc, ctx, 0, 0, NULL, AC_SCAN_VIR, hash)) == CL_VIRUS)
1919 1922
 	    cli_dbgmsg("%s found in descriptor %d\n", *ctx->virname, desc);
1923
+	else cache_add(hash, ctx);
1920 1924
 	return ret;
1921 1925
     }
1922 1926
 
... ...
@@ -2177,8 +2183,10 @@ int cli_magic_scandesc(int desc, cli_ctx *ctx)
2177 2177
 	case CL_EMAXSIZE:
2178 2178
 	case CL_EMAXFILES:
2179 2179
 	    cli_dbgmsg("Descriptor[%d]: %s\n", desc, cl_strerror(ret));
2180
+	    cache_add(hash, ctx);
2180 2181
 	    return CL_CLEAN;
2181 2182
 	default:
2183
+	    if(ret == CL_CLEAN) cache_add(hash, ctx);
2182 2184
 	    return ret;
2183 2185
     }
2184 2186
 }