Browse code

add support for cl_engine and cli_matcher

git-svn: trunk@1726

Tomasz Kojm authored on 2005/09/23 11:23:36
Showing 21 changed files
... ...
@@ -1,3 +1,10 @@
1
+Fri Sep 23 04:05:07 CEST 2005 (tk)
2
+----------------------------------
3
+  * libclamav/clamav.h: split cl_node into cli_matcher and cl_engine
4
+  * libclamav/readdb.c: read signatures into separate trees depending on
5
+			their type
6
+  * libclamav/matcher.c: scan data with suitable trees
7
+
1 8
 Mon Sep 19 01:15:02 CEST 2005 (tk)
2 9
 ----------------------------------
3 10
   * libclamav/elf.c: add cli_elfheader()
... ...
@@ -84,6 +84,7 @@ extern "C"
84 84
 #define CL_MAIL		CL_SCAN_MAIL
85 85
 #define CL_OLE2		CL_SCAN_OLE2
86 86
 #define CL_ENCRYPTED    CL_SCAN_BLOCKENCRYPTED
87
+#define cl_node		cl_engine
87 88
 
88 89
 
89 90
 struct cli_bm_patt {
... ...
@@ -126,8 +127,7 @@ struct cli_meta_node {
126 126
     struct cli_meta_node *next;
127 127
 };
128 128
 
129
-struct cl_node {
130
-    unsigned int refcount;
129
+struct cli_matcher {
131 130
     unsigned int maxpatlen; /* maximal length of pattern in db */
132 131
 
133 132
     /* Extended Boyer-Moore */
... ...
@@ -137,6 +137,13 @@ struct cl_node {
137 137
     /* Extended Aho-Corasick */
138 138
     struct cli_ac_node *ac_root, **ac_nodetable;
139 139
     unsigned int ac_partsigs, ac_nodes;
140
+};
141
+
142
+struct cl_engine {
143
+    unsigned int refcount; /* reference counter */
144
+
145
+    /* Roots table */
146
+    struct cli_matcher **root;
140 147
 
141 148
     /* MD5 */
142 149
     struct cli_md5_node **md5_hlist;
... ...
@@ -180,21 +187,21 @@ struct cl_cvd {
180 180
 };
181 181
 
182 182
 /* file scanning */
183
-extern int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root);
183
+extern int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine);
184 184
 
185
-extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options);
185
+extern int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options);
186 186
 
187
-extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options);
187
+extern int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options);
188 188
 
189 189
 /* software versions */
190 190
 extern int cl_retflevel(void);
191 191
 extern const char *cl_retver(void);
192 192
 
193 193
 /* database */
194
-extern int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo);
195
-extern int cl_loaddbdir(const char *dirname, struct cl_node **root, unsigned int *signo);
194
+extern int cl_loaddb(const char *filename, struct cl_engine **engine, unsigned int *signo);
195
+extern int cl_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo);
196 196
 extern const char *cl_retdbdir(void);
197
-extern struct cl_node *cl_dup(struct cl_node *root);
197
+extern struct cl_engine *cl_dup(struct cl_engine *engine);
198 198
 
199 199
 /* CVD */
200 200
 extern struct cl_cvd *cl_cvdhead(const char *file);
... ...
@@ -212,8 +219,8 @@ extern void cl_debug(void);
212 212
 
213 213
 extern void cl_settempdir(const char *dir, short leavetemps);
214 214
 
215
-extern int cl_build(struct cl_node *root);
216
-extern void cl_free(struct cl_node *root);
215
+extern int cl_build(struct cl_engine *engine);
216
+extern void cl_free(struct cl_engine *engine);
217 217
 
218 218
 extern const char *cl_strerror(int clerror);
219 219
 extern const char *cl_perror(int clerror); /* deprecated */
... ...
@@ -335,7 +335,7 @@ int cl_cvdverify(const char *file)
335 335
     return ret;
336 336
 }
337 337
 
338
-int cli_cvdload(FILE *fd, struct cl_node **root, unsigned int *signo, short warn)
338
+int cli_cvdload(FILE *fd, struct cl_engine **engine, unsigned int *signo, short warn)
339 339
 {
340 340
         char *dir, *tmp, *buffer;
341 341
 	struct cl_cvd cvd;
... ...
@@ -430,7 +430,7 @@ int cli_cvdload(FILE *fd, struct cl_node **root, unsigned int *signo, short warn
430 430
 	    /* end */
431 431
 
432 432
     /* load extracted directory */
433
-    cl_loaddbdir(dir, root, signo);
433
+    cl_loaddbdir(dir, engine, signo);
434 434
 
435 435
     cli_rmdirs(dir);
436 436
     free(dir);
... ...
@@ -22,7 +22,7 @@
22 22
 #include <stdio.h>
23 23
 #include "clamav.h"
24 24
 
25
-int cli_cvdload(FILE *fd, struct cl_node **root, unsigned int *signo, short warn);
25
+int cli_cvdload(FILE *fd, struct cl_engine **engine, unsigned int *signo, short warn);
26 26
 int cli_untgz(int fd, const char *destdir);
27 27
 
28 28
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -20,7 +20,5 @@
20 20
 # define DATADIR "/usr/local/share/clamav"
21 21
 #endif
22 22
 
23
-#define VIRUSDB DATADIR "/viruses.db"
24
-
25 23
 #define CLI_IGN -200
26 24
 #define CLI_ALT -201
... ...
@@ -54,7 +54,7 @@ static inline uint32_t EC32(uint32_t v)
54 54
 	return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24));
55 55
 }
56 56
 
57
-int cli_scanelf(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
57
+int cli_scanelf(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
58 58
 {
59 59
 	struct elf_file_hdr32 file_hdr;
60 60
 	struct elf_section_hdr32 *section_hdr;
... ...
@@ -56,7 +56,7 @@ struct elf_section_hdr32 {
56 56
     uint32_t sh_entsize;
57 57
 };
58 58
 
59
-int cli_scanelf(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
59
+int cli_scanelf(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
60 60
 
61 61
 int cli_elfheader(int desc, struct cli_exe_info *elfinfo);
62 62
 
... ...
@@ -272,9 +272,12 @@ cli_file_t cli_filetype2(int desc)
272 272
     return ret;
273 273
 }
274 274
 
275
-int cli_addtypesigs(struct cl_node *root)
275
+int cli_addtypesigs(struct cl_engine *engine)
276 276
 {
277 277
 	int i, ret;
278
+	struct cli_matcher *root;
279
+
280
+    root = engine->root[0];
278 281
 
279 282
     for(i = 0; cli_smagic[i].sig; i++) {
280 283
 	if((ret = cli_parse_add(root, cli_smagic[i].descr, cli_smagic[i].sig, cli_smagic[i].type, NULL, 0))) {
... ...
@@ -56,6 +56,6 @@ typedef enum {
56 56
 
57 57
 cli_file_t cli_filetype(const char *buf, size_t buflen);
58 58
 cli_file_t cli_filetype2(int desc);
59
-int cli_addtypesigs(struct cl_node *root);
59
+int cli_addtypesigs(struct cl_engine *engine);
60 60
 
61 61
 #endif
... ...
@@ -44,7 +44,7 @@ struct nodelist {
44 44
     struct nodelist *next;
45 45
 };
46 46
 
47
-int cli_ac_addpatt(struct cl_node *root, struct cli_ac_patt *pattern)
47
+int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern)
48 48
 {
49 49
 	struct cli_ac_node *pos, *next;
50 50
 	int i;
... ...
@@ -60,14 +60,14 @@ int cli_ac_addpatt(struct cl_node *root, struct cli_ac_patt *pattern)
60 60
 	if(!next) {
61 61
 	    next = (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
62 62
 	    if(!next) {
63
-		cli_dbgmsg("Unable to allocate pattern node (%d)\n", sizeof(struct cl_node));
63
+		cli_dbgmsg("Unable to allocate pattern node (%d)\n", sizeof(struct cli_matcher));
64 64
 		return CL_EMEM;
65 65
 	    }
66 66
 
67 67
 	    root->ac_nodes++;
68 68
 	    root->ac_nodetable = (struct cli_ac_node **) cli_realloc(root->ac_nodetable, (root->ac_nodes) * sizeof(struct cli_ac_node *));
69 69
 	    if(root->ac_nodetable == NULL) {
70
-		cli_dbgmsg("Unable to realloc nodetable (%d)\n", (root->ac_nodes) * sizeof(struct cl_node *));
70
+		cli_dbgmsg("Unable to realloc nodetable (%d)\n", (root->ac_nodes) * sizeof(struct cli_matcher *));
71 71
 		return CL_EMEM;
72 72
 	    }
73 73
 	    root->ac_nodetable[root->ac_nodes - 1] = next;
... ...
@@ -128,7 +128,7 @@ static struct cli_ac_node *cli_dequeue(struct nodelist **bfs)
128 128
     }
129 129
 }
130 130
 
131
-static int cli_maketrans(struct cl_node *root)
131
+static int cli_maketrans(struct cli_matcher *root)
132 132
 {
133 133
 	struct nodelist *bfs = NULL;
134 134
 	struct cli_ac_node *ac_root = root->ac_root, *child, *node;
... ...
@@ -166,7 +166,7 @@ static int cli_maketrans(struct cl_node *root)
166 166
     return 0;
167 167
 }
168 168
 
169
-int cli_ac_buildtrie(struct cl_node *root)
169
+int cli_ac_buildtrie(struct cli_matcher *root)
170 170
 {
171 171
 	int ret;
172 172
 
... ...
@@ -178,9 +178,6 @@ int cli_ac_buildtrie(struct cl_node *root)
178 178
 	return 0;
179 179
     }
180 180
 
181
-    if((ret = cli_addtypesigs(root)))
182
-	return ret;
183
-
184 181
     return cli_maketrans(root);
185 182
 }
186 183
 
... ...
@@ -209,7 +206,7 @@ static void cli_freepatt(struct cli_ac_patt *list)
209 209
     }
210 210
 }
211 211
 
212
-void cli_ac_free(struct cl_node *root)
212
+void cli_ac_free(struct cli_matcher *root)
213 213
 {
214 214
 	unsigned int i;
215 215
 
... ...
@@ -263,7 +260,7 @@ inline static int cli_findpos(const char *buffer, int offset, int length, const
263 263
     return 1;
264 264
 }
265 265
 
266
-int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, unsigned long int *ftoffset)
266
+int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, unsigned long int *ftoffset)
267 267
 {
268 268
 	struct cli_ac_node *current;
269 269
 	struct cli_ac_patt *pt;
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 - 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2002 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -22,9 +22,9 @@
22 22
 #include "clamav.h"
23 23
 #include "matcher.h"
24 24
 
25
-int cli_ac_addpatt(struct cl_node *root, struct cli_ac_patt *pattern);
26
-int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, unsigned long int *ftoffset);
27
-int cli_ac_buildtrie(struct cl_node *root);
28
-void cli_ac_free(struct cl_node *root);
25
+int cli_ac_addpatt(struct cli_matcher *root, struct cli_ac_patt *pattern);
26
+int cli_ac_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, int *partcnt, short otfrec, unsigned long int offset, unsigned long int *partoff, unsigned short ftype, int fd, unsigned long int *ftoffset);
27
+int cli_ac_buildtrie(struct cli_matcher *root);
28
+void cli_ac_free(struct cli_matcher *root);
29 29
 
30 30
 #endif
... ...
@@ -35,7 +35,7 @@
35 35
 #define DHASH(a,b,c) 211 * a + 37 * b + c
36 36
 
37 37
 
38
-int cli_bm_addpatt(struct cl_node *root, struct cli_bm_patt *pattern)
38
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern)
39 39
 {
40 40
 	int i;
41 41
 	uint16_t idx;
... ...
@@ -76,7 +76,7 @@ int cli_bm_addpatt(struct cl_node *root, struct cli_bm_patt *pattern)
76 76
     return 0;
77 77
 }
78 78
 
79
-int cli_bm_init(struct cl_node *root)
79
+int cli_bm_init(struct cli_matcher *root)
80 80
 {
81 81
 	unsigned int i;
82 82
 	unsigned int size = DHASH(256, 256, 256);
... ...
@@ -99,7 +99,7 @@ int cli_bm_init(struct cl_node *root)
99 99
     return 0;
100 100
 }
101 101
 
102
-void cli_bm_free(struct cl_node *root)
102
+void cli_bm_free(struct cli_matcher *root)
103 103
 {
104 104
 	struct cli_bm_patt *b1, *b2;
105 105
 	unsigned int i;
... ...
@@ -128,7 +128,7 @@ void cli_bm_free(struct cl_node *root)
128 128
     }
129 129
 }
130 130
 
131
-int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, unsigned long int offset, unsigned short ftype, int fd)
131
+int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, unsigned long int offset, unsigned short ftype, int fd)
132 132
 {
133 133
 	unsigned int i, j, shift, off, found = 0;
134 134
 	uint16_t idx;
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2004 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -22,9 +22,9 @@
22 22
 #include "clamav.h"
23 23
 #include "matcher.h"
24 24
 
25
-int cli_bm_addpatt(struct cl_node *root, struct cli_bm_patt *pattern);
26
-int cli_bm_init(struct cl_node *root);
27
-int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, unsigned long int offset, unsigned short ftype, int fd);
28
-void cli_bm_free(struct cl_node *root);
25
+int cli_bm_addpatt(struct cli_matcher *root, struct cli_bm_patt *pattern);
26
+int cli_bm_init(struct cli_matcher *root);
27
+int cli_bm_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cli_matcher *root, unsigned long int offset, unsigned short ftype, int fd);
28
+void cli_bm_free(struct cli_matcher *root);
29 29
 
30 30
 #endif
... ...
@@ -39,9 +39,9 @@
39 39
 #include "special.h"
40 40
 
41 41
 #define MD5_BLOCKSIZE 4096
42
+#define MAX(a,b) ((a > b) ? a : b)
42 43
 
43
-#define TARGET_TABLE_SIZE 7
44
-static int targettab[TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2, CL_TYPE_HTML, CL_TYPE_MAIL, CL_TYPE_GRAPHICS, CL_TYPE_ELF };
44
+static int targettab[CL_TARGET_TABLE_SIZE] = { 0, CL_TYPE_MSEXE, CL_TYPE_MSOLE2, CL_TYPE_HTML, CL_TYPE_MAIL, CL_TYPE_GRAPHICS, CL_TYPE_ELF };
45 45
 
46 46
 extern short cli_debug_flag;
47 47
 
... ...
@@ -50,42 +50,84 @@ extern short cli_debug_flag;
50 50
 static pthread_mutex_t cli_ref_mutex = PTHREAD_MUTEX_INITIALIZER;
51 51
 #endif
52 52
 
53
-int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, unsigned short ftype)
53
+int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype)
54 54
 {
55
-	int ret, *partcnt;
55
+	int ret, i, tid = 0, *partcnt;
56 56
 	unsigned long int *partoff;
57
+	struct cli_matcher *groot, *troot = NULL;
57 58
 
58 59
 
59
-    if((partcnt = (int *) cli_calloc(root->ac_partsigs + 1, sizeof(int))) == NULL) {
60
-	cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(int));
60
+    if(!engine) {
61
+	cli_errmsg("cli_scanbuff: engine == NULL\n");
62
+	return CL_ENULLARG;
63
+    }
64
+
65
+    groot = engine->root[0]; /* generic signatures */
66
+
67
+    if(ftype) {
68
+	for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
69
+	    if(targettab[i] == ftype) {
70
+		tid = i;
71
+		break;
72
+	    }
73
+	}
74
+	if(tid)
75
+	    troot = engine->root[tid];
76
+    }
77
+
78
+    if(troot) {
79
+
80
+	if((partcnt = (int *) cli_calloc(troot->ac_partsigs + 1, sizeof(int))) == NULL) {
81
+	    cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", troot->ac_partsigs + 1, sizeof(int));
82
+	    return CL_EMEM;
83
+	}
84
+
85
+	if((partoff = (unsigned long int *) cli_calloc(troot->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
86
+	    cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", troot->ac_partsigs + 1, sizeof(unsigned long int));
87
+	    free(partcnt);
88
+	    return CL_EMEM;
89
+	}
90
+
91
+	if((ret = cli_bm_scanbuff(buffer, length, virname, troot, 0, ftype, -1)) != CL_VIRUS)
92
+	    ret = cli_ac_scanbuff(buffer, length, virname, troot, partcnt, 0, 0, partoff, ftype, -1, NULL);
93
+
94
+	free(partcnt);
95
+	free(partoff);
96
+
97
+	if(ret == CL_VIRUS)
98
+	    return ret;
99
+    }
100
+
101
+    if((partcnt = (int *) cli_calloc(groot->ac_partsigs + 1, sizeof(int))) == NULL) {
102
+	cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", groot->ac_partsigs + 1, sizeof(int));
61 103
 	return CL_EMEM;
62 104
     }
63 105
 
64
-    if((partoff = (unsigned long int *) cli_calloc(root->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
65
-	cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(unsigned long int));
106
+    if((partoff = (unsigned long int *) cli_calloc(groot->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
107
+	cli_dbgmsg("cl_scanbuff(): unable to cli_calloc(%d, %d)\n", groot->ac_partsigs + 1, sizeof(unsigned long int));
66 108
 	free(partcnt);
67 109
 	return CL_EMEM;
68 110
     }
69 111
 
70
-    if((ret = cli_bm_scanbuff(buffer, length, virname, root, 0, ftype, -1)) != CL_VIRUS)
71
-	ret = cli_ac_scanbuff(buffer, length, virname, root, partcnt, 0, 0, partoff, ftype, -1, NULL);
112
+    if((ret = cli_bm_scanbuff(buffer, length, virname, groot, 0, ftype, -1)) != CL_VIRUS)
113
+	ret = cli_ac_scanbuff(buffer, length, virname, groot, partcnt, 0, 0, partoff, ftype, -1, NULL);
72 114
 
73 115
     free(partcnt);
74 116
     free(partoff);
75 117
     return ret;
76 118
 }
77 119
 
78
-int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root)
120
+int cl_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine)
79 121
 {
80
-    return cli_scanbuff(buffer, length, virname, root, 0);
122
+    return cli_scanbuff(buffer, length, virname, engine, 0);
81 123
 }
82 124
 
83
-static struct cli_md5_node *cli_vermd5(const unsigned char *md5, const struct cl_node *root)
125
+static struct cli_md5_node *cli_vermd5(const unsigned char *md5, const struct cl_engine *engine)
84 126
 {
85 127
 	struct cli_md5_node *pt;
86 128
 
87 129
 
88
-    if(!(pt = root->md5_hlist[md5[0] & 0xff]))
130
+    if(!(pt = engine->md5_hlist[md5[0] & 0xff]))
89 131
 	return NULL;
90 132
 
91 133
     while(pt) {
... ...
@@ -183,20 +225,20 @@ static long int cli_caloff(const char *offstr, int fd, unsigned short ftype)
183 183
     return -1;
184 184
 }
185 185
 
186
-int cli_checkfp(int fd, const struct cl_node *root)
186
+int cli_checkfp(int fd, const struct cl_engine *engine)
187 187
 {
188 188
 	struct cli_md5_node *md5_node;
189 189
 	char *digest;
190 190
 
191 191
 
192
-    if(root->md5_hlist) {
192
+    if(engine->md5_hlist) {
193 193
 
194 194
 	if(!(digest = cli_md5digest(fd))) {
195 195
 	    cli_errmsg("cli_checkfp(): Can't generate MD5 checksum\n");
196 196
 	    return 0;
197 197
 	}
198 198
 
199
-	if((md5_node = cli_vermd5(digest, root)) && md5_node->fp) {
199
+	if((md5_node = cli_vermd5(digest, engine)) && md5_node->fp) {
200 200
 		struct stat sb;
201 201
 
202 202
 	    if(fstat(fd, &sb))
... ...
@@ -220,20 +262,6 @@ int cli_checkfp(int fd, const struct cl_node *root)
220 220
 int cli_validatesig(unsigned short target, unsigned short ftype, const char *offstr, unsigned long int fileoff, int desc, const char *virname)
221 221
 {
222 222
 
223
-
224
-    if(target) {
225
-	if(target >= TARGET_TABLE_SIZE) {
226
-	    cli_dbgmsg("Unknown target in signature (%s)\n", virname);
227
-	    return 0;
228
-	} else {
229
-	    if(targettab[target] != ftype) {
230
-		cli_dbgmsg("Type: %d, expected: %d (%s)\n", ftype, targettab[target], virname);
231
-		return 0;
232
-	    }
233
-	} 
234
-
235
-    }
236
-
237 223
     if(offstr && desc != -1) {
238 224
 	    long int off = cli_caloff(offstr, desc, ftype);
239 225
 
... ...
@@ -251,49 +279,90 @@ int cli_validatesig(unsigned short target, unsigned short ftype, const char *off
251 251
     return 1;
252 252
 }
253 253
 
254
-int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, short otfrec, unsigned short ftype, unsigned long int *ftoffset)
254
+int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, unsigned long int *ftoffset)
255 255
 {
256 256
  	char *buffer, *buff, *endbl, *pt;
257
-	int bytes, buffsize, length, ret, *partcnt, type = CL_CLEAN;
258
-	unsigned long int *partoff, offset = 0;
257
+	int bytes, buffsize, length, ret, *gpartcnt, *tpartcnt;
258
+	int type = CL_CLEAN, i, tid = 0;
259
+	unsigned int maxpatlen;
260
+	unsigned long int *gpartoff, *tpartoff, offset = 0;
259 261
 	MD5_CTX ctx;
260 262
 	unsigned char digest[16];
261 263
 	struct cli_md5_node *md5_node;
264
+	struct cli_matcher *groot, *troot = NULL;
262 265
 
263 266
 
264
-    if(!root) {
265
-	cli_errmsg("cli_scandesc: root == NULL\n");
267
+    if(!engine) {
268
+	cli_errmsg("cli_scandesc: engine == NULL\n");
266 269
 	return CL_ENULLARG;
267 270
     }
268 271
 
272
+    groot = engine->root[0]; /* generic signatures */
273
+
274
+    if(ftype) {
275
+	for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
276
+	    if(targettab[i] == ftype) {
277
+		tid = i;
278
+		break;
279
+	    }
280
+	}
281
+	if(tid)
282
+	    troot = engine->root[tid];
283
+    }
284
+
285
+    if(troot)
286
+	maxpatlen = MAX(troot->maxpatlen, groot->maxpatlen);
287
+    else
288
+	maxpatlen = groot->maxpatlen;
289
+
269 290
     /* prepare the buffer */
270
-    buffsize = root->maxpatlen + SCANBUFF;
291
+    buffsize = maxpatlen + SCANBUFF;
271 292
     if(!(buffer = (char *) cli_calloc(buffsize, sizeof(char)))) {
272 293
 	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d)\n", buffsize);
273 294
 	return CL_EMEM;
274 295
     }
275 296
 
276
-    if((partcnt = (int *) cli_calloc(root->ac_partsigs + 1, sizeof(int))) == NULL) {
277
-	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(int));
297
+    if((gpartcnt = (int *) cli_calloc(groot->ac_partsigs + 1, sizeof(int))) == NULL) {
298
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", groot->ac_partsigs + 1, sizeof(int));
278 299
 	free(buffer);
279 300
 	return CL_EMEM;
280 301
     }
281 302
 
282
-    if((partoff = (unsigned long int *) cli_calloc(root->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
283
-	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", root->ac_partsigs + 1, sizeof(unsigned long int));
303
+    if((gpartoff = (unsigned long int *) cli_calloc(groot->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
304
+	cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", groot->ac_partsigs + 1, sizeof(unsigned long int));
284 305
 	free(buffer);
285
-	free(partcnt);
306
+	free(gpartcnt);
286 307
 	return CL_EMEM;
287 308
     }
288 309
 
289
-    if(root->md5_hlist)
310
+    if(troot) {
311
+
312
+	if((tpartcnt = (int *) cli_calloc(troot->ac_partsigs + 1, sizeof(int))) == NULL) {
313
+	    cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", troot->ac_partsigs + 1, sizeof(int));
314
+	    free(buffer);
315
+	    free(gpartcnt);
316
+	    free(gpartoff);
317
+	    return CL_EMEM;
318
+	}
319
+
320
+	if((tpartoff = (unsigned long int *) cli_calloc(troot->ac_partsigs + 1, sizeof(unsigned long int))) == NULL) {
321
+	    cli_dbgmsg("cli_scandesc(): unable to cli_calloc(%d, %d)\n", troot->ac_partsigs + 1, sizeof(unsigned long int));
322
+	    free(buffer);
323
+	    free(gpartcnt);
324
+	    free(gpartoff);
325
+	    free(tpartcnt);
326
+	    return CL_EMEM;
327
+	}
328
+    }
329
+
330
+    if(engine->md5_hlist)
290 331
 	MD5_Init(&ctx);
291 332
 
292 333
 
293 334
     buff = buffer;
294
-    buff += root->maxpatlen; /* pointer to read data block */
295
-    endbl = buff + SCANBUFF - root->maxpatlen; /* pointer to the last block
296
-						* length of root->maxpatlen
335
+    buff += maxpatlen; /* pointer to read data block */
336
+    endbl = buff + SCANBUFF - maxpatlen; /* pointer to the last block
337
+						* length of maxpatlen
297 338
 						*/
298 339
 
299 340
     pt = buff;
... ...
@@ -306,14 +375,34 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct
306 306
 	if(bytes < SCANBUFF)
307 307
 	    length -= SCANBUFF - bytes;
308 308
 
309
-	if(cli_bm_scanbuff(pt, length, virname, root, offset, ftype, desc) == CL_VIRUS ||
310
-	   (ret = cli_ac_scanbuff(pt, length, virname, root, partcnt, otfrec, offset, partoff, ftype, desc, ftoffset)) == CL_VIRUS) {
311
-	    free(buffer);
312
-	    free(partcnt);
313
-	    free(partoff);
309
+	if(troot) {
310
+	    if(cli_bm_scanbuff(pt, length, virname, troot, offset, ftype, desc) == CL_VIRUS ||
311
+	    (ret = cli_ac_scanbuff(pt, length, virname, troot, tpartcnt, otfrec, offset, tpartoff, ftype, desc, ftoffset)) == CL_VIRUS) {
312
+		free(buffer);
313
+		free(gpartcnt);
314
+		free(gpartoff);
315
+		free(tpartcnt);
316
+		free(tpartoff);
317
+
318
+		lseek(desc, 0, SEEK_SET);
319
+		if(cli_checkfp(desc, engine))
320
+		    return CL_CLEAN;
321
+		else
322
+		    return CL_VIRUS;
323
+	    }
324
+	}
314 325
 
326
+	if(cli_bm_scanbuff(pt, length, virname, groot, offset, ftype, desc) == CL_VIRUS ||
327
+	   (ret = cli_ac_scanbuff(pt, length, virname, groot, gpartcnt, otfrec, offset, gpartoff, ftype, desc, ftoffset)) == CL_VIRUS) {
328
+	    free(buffer);
329
+	    free(gpartcnt);
330
+	    free(gpartoff);
331
+	    if(troot) {
332
+		free(tpartcnt);
333
+		free(tpartoff);
334
+	    }
315 335
 	    lseek(desc, 0, SEEK_SET);
316
-	    if(cli_checkfp(desc, root))
336
+	    if(cli_checkfp(desc, engine))
317 337
 		return CL_CLEAN;
318 338
 	    else
319 339
 		return CL_VIRUS;
... ...
@@ -324,26 +413,30 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct
324 324
 	}
325 325
 
326 326
 	if(bytes == SCANBUFF) {
327
-	    memmove(buffer, endbl, root->maxpatlen);
327
+	    memmove(buffer, endbl, maxpatlen);
328 328
 
329 329
 	    if(pt == buffer) {
330 330
 		offset += SCANBUFF;
331 331
 	    } else {
332
-		offset += SCANBUFF - root->maxpatlen;
332
+		offset += SCANBUFF - maxpatlen;
333 333
 		pt = buffer;
334 334
 		length = buffsize;
335 335
 	    }
336 336
 	}
337 337
 
338
-	if(root->md5_hlist)
338
+	if(engine->md5_hlist)
339 339
 	    MD5_Update(&ctx, buff, bytes);
340 340
     }
341 341
 
342 342
     free(buffer);
343
-    free(partcnt);
344
-    free(partoff);
343
+    free(gpartcnt);
344
+    free(gpartoff);
345
+    if(troot) {
346
+	free(tpartcnt);
347
+	free(tpartoff);
348
+    }
345 349
 
346
-    if(root->md5_hlist) {
350
+    if(engine->md5_hlist) {
347 351
 	MD5_Final(digest, &ctx);
348 352
 
349 353
 	if(cli_debug_flag) {
... ...
@@ -359,7 +452,7 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct
359 359
 	    cli_dbgmsg("Calculated MD5 checksum: %s\n", md5str);
360 360
 	}
361 361
 
362
-	if((md5_node = cli_vermd5(digest, root)) && !md5_node->fp) {
362
+	if((md5_node = cli_vermd5(digest, engine)) && !md5_node->fp) {
363 363
 		struct stat sb;
364 364
 
365 365
 	    if(fstat(desc, &sb))
... ...
@@ -379,15 +472,26 @@ int cli_scandesc(int desc, const char **virname, long int *scanned, const struct
379 379
     return otfrec ? type : CL_CLEAN;
380 380
 }
381 381
 
382
-int cl_build(struct cl_node *root)
382
+int cl_build(struct cl_engine *engine)
383 383
 {
384
-    return cli_ac_buildtrie(root);
384
+	int i, ret;
385
+	struct cli_matcher *root;
386
+
387
+    for(i = 0; i < CL_TARGET_TABLE_SIZE; i++)
388
+	if((root = engine->root[i]))
389
+	    cli_ac_buildtrie(root);
390
+    /* FIXME: check return values of cli_ac_buildtree */
391
+
392
+    if((ret = cli_addtypesigs(engine)))
393
+	return ret;
394
+
395
+    return 0;
385 396
 }
386 397
 
387
-struct cl_node *cl_dup(struct cl_node *root)
398
+struct cl_engine *cl_dup(struct cl_engine *engine)
388 399
 {
389
-    if(!root) {
390
-	cli_errmsg("cl_dup: root == NULL\n");
400
+    if(!engine) {
401
+	cli_errmsg("cl_dup: engine == NULL\n");
391 402
 	return NULL;
392 403
     }
393 404
 
... ...
@@ -395,23 +499,24 @@ struct cl_node *cl_dup(struct cl_node *root)
395 395
     pthread_mutex_lock(&cli_ref_mutex);
396 396
 #endif
397 397
 
398
-    root->refcount++;
399
-    
398
+    engine->refcount++;
399
+
400 400
 #ifdef CL_THREAD_SAFE
401 401
     pthread_mutex_unlock(&cli_ref_mutex);
402 402
 #endif
403 403
 
404
-    return root;
404
+    return engine;
405 405
 }
406 406
 
407
-void cl_free(struct cl_node *root)
407
+void cl_free(struct cl_engine *engine)
408 408
 {
409 409
 	int i;
410 410
 	struct cli_md5_node *md5pt, *md5h;
411 411
 	struct cli_meta_node *metapt, *metah;
412
+	struct cli_matcher *root;
412 413
 
413
-    if(!root) {
414
-	cli_errmsg("cl_free: root == NULL\n");
414
+    if(!engine) {
415
+	cli_errmsg("cl_free: engine == NULL\n");
415 416
 	return;
416 417
     }
417 418
 
... ...
@@ -419,8 +524,8 @@ void cl_free(struct cl_node *root)
419 419
     pthread_mutex_lock(&cli_ref_mutex);
420 420
 #endif
421 421
 
422
-    root->refcount--;
423
-    if (root->refcount) {
422
+    engine->refcount--;
423
+    if(engine->refcount) {
424 424
 #ifdef CL_THREAD_SAFE
425 425
 	pthread_mutex_unlock(&cli_ref_mutex);
426 426
 #endif
... ...
@@ -431,12 +536,16 @@ void cl_free(struct cl_node *root)
431 431
     pthread_mutex_unlock(&cli_ref_mutex);
432 432
 #endif
433 433
 
434
-    cli_ac_free(root);
435
-    cli_bm_free(root);
434
+    for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
435
+	if((root = engine->root[i])) {
436
+	    cli_ac_free(root);
437
+	    cli_bm_free(root);
438
+	}
439
+    }
436 440
 
437
-    if(root->md5_hlist) {
441
+    if(engine->md5_hlist) {
438 442
 	for(i = 0; i < 256; i++) {
439
-	    md5pt = root->md5_hlist[i];
443
+	    md5pt = engine->md5_hlist[i];
440 444
 	    while(md5pt) {
441 445
 		md5h = md5pt;
442 446
 		md5pt = md5pt->next;
... ...
@@ -447,10 +556,10 @@ void cl_free(struct cl_node *root)
447 447
 		free(md5h);
448 448
 	    }
449 449
 	}
450
-	free(root->md5_hlist);
450
+	free(engine->md5_hlist);
451 451
     }
452 452
 
453
-    metapt = root->zip_mlist;
453
+    metapt = engine->zip_mlist;
454 454
     while(metapt) {
455 455
 	metah = metapt;
456 456
 	metapt = metapt->next;
... ...
@@ -460,7 +569,7 @@ void cl_free(struct cl_node *root)
460 460
 	free(metah);
461 461
     }
462 462
 
463
-    metapt = root->rar_mlist;
463
+    metapt = engine->rar_mlist;
464 464
     while(metapt) {
465 465
 	metah = metapt;
466 466
 	metapt = metapt->next;
... ...
@@ -470,15 +579,15 @@ void cl_free(struct cl_node *root)
470 470
 	free(metah);
471 471
     }
472 472
 
473
-    free(root);
473
+    free(engine);
474 474
 }
475 475
 
476
-int cl_buildtrie(struct cl_node *root) /* for backward compatibility */
476
+int cl_buildtrie(struct cl_engine *engine) /* for backward compatibility */
477 477
 {
478
-    return cl_build(root);
478
+    return cl_build(engine);
479 479
 }
480 480
 
481
-void cl_freetrie(struct cl_node *root) /* for backward compatibility */
481
+void cl_freetrie(struct cl_engine *engine) /* for backward compatibility */
482 482
 {
483
-    cl_free(root);
483
+    cl_free(engine);
484 484
 }
... ...
@@ -21,12 +21,14 @@
21 21
 
22 22
 #include "clamav.h"
23 23
 
24
-int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, short otfrec, unsigned short ftype, unsigned long int *ftoffset);
24
+#define CL_TARGET_TABLE_SIZE 7
25 25
 
26
-int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_node *root, unsigned short ftype);
26
+int cli_scandesc(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, short otfrec, unsigned short ftype, unsigned long int *ftoffset);
27
+
28
+int cli_scanbuff(const char *buffer, unsigned int length, const char **virname, const struct cl_engine *engine, unsigned short ftype);
27 29
 
28 30
 int cli_validatesig(unsigned short target, unsigned short ftype, const char *offstr, unsigned long int fileoff, int desc, const char *virname);
29 31
 
30
-int cli_checkfp(int fd, const struct cl_node *root);
32
+int cli_checkfp(int fd, const struct cl_engine *engine);
31 33
 
32 34
 #endif
... ...
@@ -148,7 +148,7 @@ static int cli_ddump(int desc, int offset, int size, const char *file)
148 148
 }
149 149
 */
150 150
 
151
-int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
151
+int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
152 152
 {
153 153
 	uint16_t e_magic; /* DOS signature ("MZ") */
154 154
 	uint16_t nsections;
... ...
@@ -695,7 +695,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
695 695
 			lseek(ndesc, 0, SEEK_SET);
696 696
 
697 697
 			cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
698
-			if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
698
+			if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
699 699
 			    free(section_hdr);
700 700
 			    close(ndesc);
701 701
 			    if(!cli_leavetemps_flag)
... ...
@@ -884,7 +884,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
884 884
 			lseek(ndesc, 0, SEEK_SET);
885 885
 
886 886
 			cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
887
-			if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
887
+			if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
888 888
 			    free(section_hdr);
889 889
 			    close(ndesc);
890 890
 			    if(!cli_leavetemps_flag)
... ...
@@ -1077,7 +1077,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
1077 1077
 			lseek(ndesc, 0, SEEK_SET);
1078 1078
 
1079 1079
 			cli_dbgmsg("***** Scanning rebuilt PE file *****\n");
1080
-			if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
1080
+			if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1081 1081
 			    free(section_hdr);
1082 1082
 			    close(ndesc);
1083 1083
 			    if(!cli_leavetemps_flag)
... ...
@@ -1284,7 +1284,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
1284 1284
 		cli_dbgmsg("UPX/FSG: Decompressed data saved in %s\n", tempfile);
1285 1285
 
1286 1286
 	    cli_dbgmsg("***** Scanning decompressed file *****\n");
1287
-	    if((ret = cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS) {
1287
+	    if((ret = cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec)) == CL_VIRUS) {
1288 1288
 		close(ndesc);
1289 1289
 		if(!cli_leavetemps_flag)
1290 1290
 		    unlink(tempfile);
... ...
@@ -1382,7 +1382,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
1382 1382
 	    fsync(ndesc);
1383 1383
 	    lseek(ndesc, 0, SEEK_SET);
1384 1384
 
1385
-	    if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
1385
+	    if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1386 1386
 		free(section_hdr);
1387 1387
 		close(ndesc);
1388 1388
 		if(!cli_leavetemps_flag) {
... ...
@@ -1448,7 +1448,7 @@ int cli_scanpe(int desc, const char **virname, long int *scanned, const struct c
1448 1448
 	    fsync(ndesc);
1449 1449
 	    lseek(ndesc, 0, SEEK_SET);
1450 1450
 
1451
-	    if(cli_magic_scandesc(ndesc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
1451
+	    if(cli_magic_scandesc(ndesc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1452 1452
 		free(section_hdr);
1453 1453
 		close(ndesc);
1454 1454
 		if(!cli_leavetemps_flag) {
... ...
@@ -94,7 +94,7 @@ struct pe_image_section_hdr {
94 94
     uint32_t Characteristics;
95 95
 };
96 96
 
97
-int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
97
+int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
98 98
 
99 99
 int cli_peheader(int desc, struct cli_exe_info *peinfo);
100 100
 
... ...
@@ -60,7 +60,7 @@
60 60
 
61 61
 /* TODO: clean up the code */
62 62
 
63
-static int cli_ac_addsig(struct cl_node *root, const char *virname, const char *hexsig, int sigid, int parts, int partno, unsigned short type, unsigned int mindist, unsigned int maxdist, char *offset, unsigned short target)
63
+static int cli_ac_addsig(struct cli_matcher *root, const char *virname, const char *hexsig, int sigid, int parts, int partno, unsigned short type, unsigned int mindist, unsigned int maxdist, char *offset, unsigned short target)
64 64
 {
65 65
 	struct cli_ac_patt *new;
66 66
 	char *pt, *hex;
... ...
@@ -247,7 +247,7 @@ static int cli_ac_addsig(struct cl_node *root, const char *virname, const char *
247 247
     return 0;
248 248
 }
249 249
 
250
-int cli_parse_add(struct cl_node *root, const char *virname, const char *hexsig, unsigned short type, char *offset, unsigned short target)
250
+int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, unsigned short type, char *offset, unsigned short target)
251 251
 {
252 252
 	struct cli_bm_patt *bm_new;
253 253
 	char *pt, *hexcpy, *start, *n;
... ...
@@ -428,38 +428,87 @@ int cli_parse_add(struct cl_node *root, const char *virname, const char *hexsig,
428 428
     return 0;
429 429
 }
430 430
 
431
-static int cli_loaddb(FILE *fd, struct cl_node **root, unsigned int *signo)
431
+static int cli_initengine(struct cl_engine **engine)
432 432
 {
433
-	char buffer[FILEBUFF], *pt, *start;
434
-	int line = 0, ret = 0;
433
+	struct cli_matcher *root;
434
+	int i, ret;
435 435
 
436 436
 
437
-    if(!*root) {
438
-	cli_dbgmsg("Initializing main node\n");
439
-	*root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node));
440
-	if(!*root)
437
+    if(!*engine) {
438
+	cli_dbgmsg("Initializing the engine structure\n");
439
+
440
+	*engine = (struct cl_engine *) cli_calloc(1, sizeof(struct cl_engine));
441
+	if(!*engine) {
442
+	    cli_errmsg("Can't allocate memory for the engine structure!\n");
441 443
 	    return CL_EMEM;
442
-	(*root)->refcount = 1;
443
-    }
444
+	}
445
+
446
+	(*engine)->refcount = 1;
444 447
 
445
-    if(!(*root)->ac_root) {
446
-	cli_dbgmsg("Initializing trie\n");
447
-	(*root)->ac_root =  (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
448
-	if(!(*root)->ac_root) {
449
-	    free(*root);
450
-	    cli_errmsg("Can't initialise AC pattern matcher\n");
448
+	(*engine)->root = (struct cli_matcher **) cli_calloc(CL_TARGET_TABLE_SIZE, sizeof(struct cli_matcher *));
449
+	if(!(*engine)->root) {
450
+	    /* no need to free previously allocated memory here */
451
+	    cli_errmsg("Can't allocate memory for roots!\n");
451 452
 	    return CL_EMEM;
452 453
 	}
453 454
     }
454 455
 
455
-    if(!(*root)->bm_shift) {
456
-	cli_dbgmsg("Initializing BM tables\n");
457
-	if((ret = cli_bm_init(*root))) {
458
-	    cli_errmsg("Can't initialise BM pattern matcher\n");
459
-	    return ret;
456
+    return 0;
457
+}
458
+
459
+static int cli_initroots(struct cl_engine *engine)
460
+{
461
+	int i, ret;
462
+	struct cli_matcher *root;
463
+
464
+
465
+    for(i = 0; i < CL_TARGET_TABLE_SIZE; i++) {
466
+	if(!engine->root[i]) {
467
+	    cli_dbgmsg("Initializing engine->root[%d]\n", i);
468
+	    root = engine->root[i] = (struct cli_matcher *) cli_calloc(1, sizeof(struct cli_matcher));
469
+	    if(!root) {
470
+		cli_errmsg("Can't initialise AC pattern matcher\n");
471
+		return CL_EMEM;
472
+	    }
473
+
474
+	    cli_dbgmsg("Initialising AC pattern matcher of root[%d]\n", i);
475
+	    root->ac_root =  (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
476
+	    if(!root->ac_root) {
477
+		/* no need to free previously allocated memory here */
478
+		cli_errmsg("Can't initialise AC pattern matcher\n");
479
+		return CL_EMEM;
480
+	    }
481
+
482
+	    cli_dbgmsg("Initializing BM tables of root[%d]\n", i);
483
+	    if((ret = cli_bm_init(root))) {
484
+		cli_errmsg("Can't initialise BM pattern matcher\n");
485
+		return ret;
486
+	    }
460 487
 	}
461 488
     }
462 489
 
490
+    return 0;
491
+}
492
+
493
+static int cli_loaddb(FILE *fd, struct cl_engine **engine, unsigned int *signo)
494
+{
495
+	char buffer[FILEBUFF], *pt, *start;
496
+	int line = 0, ret = 0;
497
+	struct cli_matcher *root;
498
+
499
+
500
+    if((ret = cli_initengine(engine))) {
501
+	cl_free(*engine);
502
+	return ret;
503
+    }
504
+
505
+    if((ret = cli_initroots(*engine))) {
506
+	cl_free(*engine);
507
+	return ret;
508
+    }
509
+
510
+    root = (*engine)->root[0];
511
+
463 512
     while(fgets(buffer, FILEBUFF, fd)) {
464 513
 	line++;
465 514
 	cli_chomp(buffer);
... ...
@@ -476,7 +525,7 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, unsigned int *signo)
476 476
 
477 477
 	if(*pt == '=') continue;
478 478
 
479
-	if((ret = cli_parse_add(*root, start, pt, 0, NULL, 0))) {
479
+	if((ret = cli_parse_add(root, start, pt, 0, NULL, 0))) {
480 480
 	    cli_errmsg("Problem parsing signature at line %d\n", line);
481 481
 	    ret = CL_EMALFDB;
482 482
 	    break;
... ...
@@ -485,13 +534,13 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, unsigned int *signo)
485 485
 
486 486
     if(!line) {
487 487
 	cli_errmsg("Empty database file\n");
488
-	cl_free(*root);
488
+	cl_free(*engine);
489 489
 	return CL_EMALFDB;
490 490
     }
491 491
 
492 492
     if(ret) {
493 493
 	cli_errmsg("Problem parsing database at line %d\n", line);
494
-	cl_free(*root);
494
+	cl_free(*engine);
495 495
 	return ret;
496 496
     }
497 497
 
... ...
@@ -501,37 +550,22 @@ static int cli_loaddb(FILE *fd, struct cl_node **root, unsigned int *signo)
501 501
     return 0;
502 502
 }
503 503
 
504
-static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
504
+static int cli_loadndb(FILE *fd, struct cl_engine **engine, unsigned int *signo)
505 505
 {
506 506
 	char buffer[FILEBUFF], *sig, *virname, *offset, *pt;
507
+	struct cli_matcher *root;
507 508
 	int line = 0, sigs = 0, ret = 0;
508 509
 	unsigned short target;
509 510
 
510 511
 
511
-    if(!*root) {
512
-	cli_dbgmsg("Initializing main node\n");
513
-	*root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node));
514
-	if(!*root)
515
-	    return CL_EMEM;
516
-	(*root)->refcount = 1;
517
-    }
518
-
519
-    if(!(*root)->ac_root) {
520
-	cli_dbgmsg("Initializing trie\n");
521
-	(*root)->ac_root =  (struct cli_ac_node *) cli_calloc(1, sizeof(struct cli_ac_node));
522
-	if(!(*root)->ac_root) {
523
-	    free(*root);
524
-	    cli_errmsg("Can't initialise AC pattern matcher\n");
525
-	    return CL_EMEM;
526
-	}
512
+    if((ret = cli_initengine(engine))) {
513
+	cl_free(*engine);
514
+	return ret;
527 515
     }
528 516
 
529
-    if(!(*root)->bm_shift) {
530
-	cli_dbgmsg("Initializing BM tables\n");
531
-	if((ret = cli_bm_init(*root))) {
532
-	    cli_errmsg("Can't initialise BM pattern matcher\n");
533
-	    return ret;
534
-	}
517
+    if((ret = cli_initroots(*engine))) {
518
+	cl_free(*engine);
519
+	return ret;
535 520
     }
536 521
 
537 522
     while(fgets(buffer, FILEBUFF, fd)) {
... ...
@@ -557,7 +591,7 @@ static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
557 557
 	    }
558 558
 
559 559
 	    if(atoi(pt) > cl_retflevel()) {
560
-		cli_warnmsg("Signature for %s requires new ClamAV version. Please update!\n", virname);
560
+		cli_dbgmsg("Signature for %s requires new ClamAV version. Please update!\n", virname);
561 561
 		sigs--;
562 562
 		free(virname);
563 563
 		free(pt);
... ...
@@ -577,6 +611,16 @@ static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
577 577
 	target = (unsigned short) atoi(pt);
578 578
 	free(pt);
579 579
 
580
+	if(target >= CL_TARGET_TABLE_SIZE) {
581
+	    cli_dbgmsg("Not supported target type in signature for %s\n", virname);
582
+	    sigs--;
583
+	    free(virname);
584
+	    free(pt);
585
+	    continue;
586
+	}
587
+
588
+	root = (*engine)->root[target];
589
+
580 590
 	if(!(offset = cli_strtok(buffer, 2, ":"))) {
581 591
 	    free(virname);
582 592
 	    ret = CL_EMALFDB;
... ...
@@ -593,7 +637,7 @@ static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
593 593
 	    break;
594 594
 	}
595 595
 
596
-	if((ret = cli_parse_add(*root, virname, sig, 0, offset, target))) {
596
+	if((ret = cli_parse_add(root, virname, sig, 0, offset, target))) {
597 597
 	    cli_errmsg("Problem parsing signature at line %d\n", line);
598 598
 	    free(virname);
599 599
 	    free(offset);
... ...
@@ -608,13 +652,13 @@ static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
608 608
 
609 609
     if(!line) {
610 610
 	cli_errmsg("Empty database file\n");
611
-	cl_free(*root);
611
+	cl_free(*engine);
612 612
 	return CL_EMALFDB;
613 613
     }
614 614
 
615 615
     if(ret) {
616 616
 	cli_errmsg("Problem parsing database at line %d\n", line);
617
-	cl_free(*root);
617
+	cl_free(*engine);
618 618
 	return ret;
619 619
     }
620 620
 
... ...
@@ -624,19 +668,16 @@ static int cli_loadndb(FILE *fd, struct cl_node **root, unsigned int *signo)
624 624
     return 0;
625 625
 }
626 626
 
627
-static int cli_loadhdb(FILE *fd, struct cl_node **root, unsigned int *signo, unsigned short fp)
627
+static int cli_loadhdb(FILE *fd, struct cl_engine **engine, unsigned int *signo, unsigned short fp)
628 628
 {
629 629
 	char buffer[FILEBUFF], *pt;
630 630
 	int line = 0, ret = 0;
631 631
 	struct cli_md5_node *new;
632 632
 
633 633
 
634
-    if(!*root) {
635
-	cli_dbgmsg("Initializing main node\n");
636
-	*root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node));
637
-	if(!*root)
638
-	    return CL_EMEM;
639
-	(*root)->refcount = 1;
634
+    if((ret = cli_initengine(engine))) {
635
+	cl_free(*engine);
636
+	return ret;
640 637
     }
641 638
 
642 639
     while(fgets(buffer, FILEBUFF, fd)) {
... ...
@@ -684,28 +725,28 @@ static int cli_loadhdb(FILE *fd, struct cl_node **root, unsigned int *signo, uns
684 684
 
685 685
 	new->viralias = cli_strtok(buffer, 3, ":"); /* aliases are optional */
686 686
 
687
-	if(!(*root)->md5_hlist) {
687
+	if(!(*engine)->md5_hlist) {
688 688
 	    cli_dbgmsg("Initializing md5 list structure\n");
689
-	    (*root)->md5_hlist = (struct cli_md5_node **) cli_calloc(256, sizeof(struct cli_md5_node *));
690
-	    if(!(*root)->md5_hlist) {
689
+	    (*engine)->md5_hlist = (struct cli_md5_node **) cli_calloc(256, sizeof(struct cli_md5_node *));
690
+	    if(!(*engine)->md5_hlist) {
691 691
 		ret = CL_EMEM;
692 692
 		break;
693 693
 	    }
694 694
 	}
695 695
 
696
-	new->next = (*root)->md5_hlist[new->md5[0] & 0xff];
697
-	(*root)->md5_hlist[new->md5[0] & 0xff] = new;
696
+	new->next = (*engine)->md5_hlist[new->md5[0] & 0xff];
697
+	(*engine)->md5_hlist[new->md5[0] & 0xff] = new;
698 698
     }
699 699
 
700 700
     if(!line) {
701 701
 	cli_errmsg("Empty database file\n");
702
-	cl_free(*root);
702
+	cl_free(*engine);
703 703
 	return CL_EMALFDB;
704 704
     }
705 705
 
706 706
     if(ret) {
707 707
 	cli_errmsg("Problem parsing database at line %d\n", line);
708
-	cl_free(*root);
708
+	cl_free(*engine);
709 709
 	return ret;
710 710
     }
711 711
 
... ...
@@ -715,19 +756,16 @@ static int cli_loadhdb(FILE *fd, struct cl_node **root, unsigned int *signo, uns
715 715
     return 0;
716 716
 }
717 717
 
718
-static int cli_loadmd(FILE *fd, struct cl_node **root, unsigned int *signo, int type)
718
+static int cli_loadmd(FILE *fd, struct cl_engine **engine, unsigned int *signo, int type)
719 719
 {
720 720
 	char buffer[FILEBUFF], *pt;
721 721
 	int line = 0, comments = 0, ret = 0;
722 722
 	struct cli_meta_node *new;
723 723
 
724 724
 
725
-    if(!*root) {
726
-	cli_dbgmsg("Initializing main node\n");
727
-	*root = (struct cl_node *) cli_calloc(1, sizeof(struct cl_node));
728
-	if(!*root)
729
-	    return CL_EMEM;
730
-	(*root)->refcount = 1;
725
+    if((ret = cli_initengine(engine))) {
726
+	cl_free(*engine);
727
+	return ret;
731 728
     }
732 729
 
733 730
     while(fgets(buffer, FILEBUFF, fd)) {
... ...
@@ -863,23 +901,23 @@ static int cli_loadmd(FILE *fd, struct cl_node **root, unsigned int *signo, int
863 863
 	}
864 864
 
865 865
 	if(type == 1) {
866
-	    new->next = (*root)->zip_mlist;
867
-	    (*root)->zip_mlist = new;
866
+	    new->next = (*engine)->zip_mlist;
867
+	    (*engine)->zip_mlist = new;
868 868
 	} else {
869
-	    new->next = (*root)->rar_mlist;
870
-	    (*root)->rar_mlist = new;
869
+	    new->next = (*engine)->rar_mlist;
870
+	    (*engine)->rar_mlist = new;
871 871
 	}
872 872
     }
873 873
 
874 874
     if(!line) {
875 875
 	cli_errmsg("Empty database file\n");
876
-	cl_free(*root);
876
+	cl_free(*engine);
877 877
 	return CL_EMALFDB;
878 878
     }
879 879
 
880 880
     if(ret) {
881 881
 	cli_errmsg("Problem parsing database at line %d\n", line);
882
-	cl_free(*root);
882
+	cl_free(*engine);
883 883
 	return ret;
884 884
     }
885 885
 
... ...
@@ -889,7 +927,7 @@ static int cli_loadmd(FILE *fd, struct cl_node **root, unsigned int *signo, int
889 889
     return 0;
890 890
 }
891 891
 
892
-int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo)
892
+int cl_loaddb(const char *filename, struct cl_engine **engine, unsigned int *signo)
893 893
 {
894 894
 	FILE *fd;
895 895
 	int ret;
... ...
@@ -903,7 +941,7 @@ int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo)
903 903
     cli_dbgmsg("Loading %s\n", filename);
904 904
 
905 905
     if(cli_strbcasestr(filename, ".db")  || cli_strbcasestr(filename, ".db2") || cli_strbcasestr(filename, ".db3")) {
906
-	ret = cli_loaddb(fd, root, signo);
906
+	ret = cli_loaddb(fd, engine, signo);
907 907
 
908 908
     } else if(cli_strbcasestr(filename, ".cvd")) {
909 909
 	    int warn = 0;
... ...
@@ -911,26 +949,26 @@ int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo)
911 911
 	if(!strcmp(filename, "daily.cvd"))
912 912
 	    warn = 1;
913 913
 
914
-	ret = cli_cvdload(fd, root, signo, warn);
914
+	ret = cli_cvdload(fd, engine, signo, warn);
915 915
 
916 916
     } else if(cli_strbcasestr(filename, ".hdb")) {
917
-	ret = cli_loadhdb(fd, root, signo, 0);
917
+	ret = cli_loadhdb(fd, engine, signo, 0);
918 918
 
919 919
     } else if(cli_strbcasestr(filename, ".fp")) {
920
-	ret = cli_loadhdb(fd, root, signo, 1);
920
+	ret = cli_loadhdb(fd, engine, signo, 1);
921 921
 
922 922
     } else if(cli_strbcasestr(filename, ".ndb")) {
923
-	ret = cli_loadndb(fd, root, signo);
923
+	ret = cli_loadndb(fd, engine, signo);
924 924
 
925 925
     } else if(cli_strbcasestr(filename, ".zmd")) {
926
-	ret = cli_loadmd(fd, root, signo, 1);
926
+	ret = cli_loadmd(fd, engine, signo, 1);
927 927
 
928 928
     } else if(cli_strbcasestr(filename, ".rmd")) {
929
-	ret = cli_loadmd(fd, root, signo, 2);
929
+	ret = cli_loadmd(fd, engine, signo, 2);
930 930
 
931 931
     } else {
932 932
 	cli_dbgmsg("cl_loaddb: unknown extension - assuming old database format\n");
933
-	ret = cli_loaddb(fd, root, signo);
933
+	ret = cli_loaddb(fd, engine, signo);
934 934
     }
935 935
 
936 936
     if(ret)
... ...
@@ -940,7 +978,7 @@ int cl_loaddb(const char *filename, struct cl_node **root, unsigned int *signo)
940 940
     return ret;
941 941
 }
942 942
 
943
-int cl_loaddbdir(const char *dirname, struct cl_node **root, unsigned int *signo)
943
+int cl_loaddbdir(const char *dirname, struct cl_engine **engine, unsigned int *signo)
944 944
 {
945 945
 	DIR *dd;
946 946
 	struct dirent *dent;
... ...
@@ -991,7 +1029,7 @@ int cl_loaddbdir(const char *dirname, struct cl_node **root, unsigned int *signo
991 991
 		    return CL_EMEM;
992 992
 		}
993 993
 		sprintf(dbfile, "%s/%s", dirname, dent->d_name);
994
-		if((ret = cl_loaddb(dbfile, root, signo))) {
994
+		if((ret = cl_loaddb(dbfile, engine, signo))) {
995 995
 		    cli_dbgmsg("cl_loaddbdir(): error loading database %s\n", dbfile);
996 996
 		    free(dbfile);
997 997
 		    closedir(dd);
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net>
2
+ *  Copyright (C) 2004 - 2005 Tomasz Kojm <tkojm@clamav.net>
3 3
  *
4 4
  *  This program is free software; you can redistribute it and/or modify
5 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -19,6 +19,6 @@
19 19
 #ifndef __READDB_H
20 20
 #define __READDB_H
21 21
 
22
-int cli_parse_add(struct cl_node *root, const char *virname, const char *hexsig, unsigned short type, char *offset, unsigned short target);
22
+int cli_parse_add(struct cli_matcher *root, const char *virname, const char *hexsig, unsigned short type, char *offset, unsigned short target);
23 23
 
24 24
 #endif
... ...
@@ -101,9 +101,9 @@ extern int cli_mbox(const char *dir, int desc, unsigned int options); /* FIXME *
101 101
 
102 102
 #define MAX_MAIL_RECURSION  15
103 103
 
104
-static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
104
+static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
105 105
 
106
-static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
106
+static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
107 107
 
108 108
 /*
109 109
 #ifdef CL_THREAD_SAFE
... ...
@@ -115,7 +115,7 @@ static void cli_unlock_mutex(void *mtx)
115 115
 #endif
116 116
 */
117 117
 
118
-static int cli_scanrar(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned long int offset)
118
+static int cli_scanrar(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned long int offset)
119 119
 {
120 120
 	int fd, ret = CL_CLEAN;
121 121
 	unsigned int files = 0;
... ...
@@ -137,7 +137,7 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
137 137
     lseek(desc, offset, SEEK_SET);
138 138
     metadata = metadata_tmp = cli_unrar(desc, dir, limits);
139 139
 
140
-    if(cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
140
+    if(cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
141 141
 	    ret = CL_VIRUS;
142 142
     } else while(metadata) {
143 143
 
... ...
@@ -149,7 +149,7 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
149 149
 		metadata->pack_size ? ((unsigned int) metadata->unpack_size / (unsigned int) metadata->pack_size) : 0, limits ? limits->maxratio : 0);
150 150
 
151 151
 	/* Scan metadata */
152
-	mdata = root->rar_mlist;
152
+	mdata = engine->rar_mlist;
153 153
 	if(mdata) do {
154 154
 	    if(mdata->encrypted != metadata->encrypted)
155 155
 		continue;
... ...
@@ -190,7 +190,7 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
190 190
 	if(DETECT_ENCRYPTED && metadata->encrypted) {
191 191
 	    cli_dbgmsg("RAR: Encrypted files found in archive.\n");
192 192
 	    lseek(desc, 0, SEEK_SET);
193
-	    ret = cli_scandesc(desc, virname, scanned, root, 0, 0, NULL);
193
+	    ret = cli_scandesc(desc, virname, scanned, engine, 0, 0, NULL);
194 194
 	    if(ret < 0) {
195 195
 		break;
196 196
 	    } else if(ret != CL_VIRUS) {
... ...
@@ -262,7 +262,7 @@ static int cli_scanrar(int desc, const char **virname, long int *scanned, const
262 262
 }
263 263
 
264 264
 #ifdef HAVE_ZLIB_H
265
-static int cli_scanzip(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned long int offset)
265
+static int cli_scanzip(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned long int offset)
266 266
 {
267 267
 	ZZIP_DIR *zdir;
268 268
 	ZZIP_DIRENT zdirent;
... ...
@@ -327,7 +327,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
327 327
 	}
328 328
 
329 329
 	/* Scan metadata */
330
-	mdata = root->zip_mlist;
330
+	mdata = engine->zip_mlist;
331 331
 	if(mdata) do {
332 332
 	    if(mdata->encrypted != encrypted)
333 333
 		continue;
... ...
@@ -392,7 +392,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
392 392
 	if(DETECT_ENCRYPTED && encrypted) {
393 393
 	    cli_dbgmsg("Zip: Encrypted files found in archive.\n");
394 394
 	    lseek(desc, 0, SEEK_SET);
395
-	    ret = cli_scandesc(desc, virname, scanned, root, 0, 0, NULL);
395
+	    ret = cli_scandesc(desc, virname, scanned, engine, 0, 0, NULL);
396 396
 	    if(ret < 0) {
397 397
 		break;
398 398
 	    } else if(ret != CL_VIRUS) {
... ...
@@ -472,7 +472,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
472 472
 	fd = fileno(tmp);
473 473
 
474 474
 	lseek(fd, 0, SEEK_SET);
475
-	if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS ) {
475
+	if((ret = cli_magic_scandesc(fd, virname, scanned, engine, limits, options, arec, mrec)) == CL_VIRUS ) {
476 476
 	    cli_dbgmsg("Zip: Infected with %s\n", *virname);
477 477
 	    ret = CL_VIRUS;
478 478
 	    break;
... ...
@@ -505,7 +505,7 @@ static int cli_scanzip(int desc, const char **virname, long int *scanned, const
505 505
     return ret;
506 506
 }
507 507
 
508
-static int cli_scangzip(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
508
+static int cli_scangzip(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
509 509
 {
510 510
 	int fd, bytes, ret = CL_CLEAN;
511 511
 	unsigned long int size = 0;
... ...
@@ -585,7 +585,7 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
585 585
     }
586 586
 
587 587
     lseek(fd, 0, SEEK_SET);
588
-    if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS ) {
588
+    if((ret = cli_magic_scandesc(fd, virname, scanned, engine, limits, options, arec, mrec)) == CL_VIRUS ) {
589 589
 	cli_dbgmsg("GZip: Infected with %s\n", *virname);
590 590
 	fclose(tmp);
591 591
 	if(!cli_leavetemps_flag)
... ...
@@ -610,7 +610,7 @@ static int cli_scangzip(int desc, const char **virname, long int *scanned, const
610 610
 #define BZ2_bzRead bzRead
611 611
 #endif
612 612
 
613
-static int cli_scanbzip(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
613
+static int cli_scanbzip(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
614 614
 {
615 615
 	int fd, bytes, ret = CL_CLEAN, bzerror = 0;
616 616
 	short memlim = 0;
... ...
@@ -704,7 +704,7 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
704 704
     }
705 705
 
706 706
     lseek(fd, 0, SEEK_SET);
707
-    if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS ) {
707
+    if((ret = cli_magic_scandesc(fd, virname, scanned, engine, limits, options, arec, mrec)) == CL_VIRUS ) {
708 708
 	cli_dbgmsg("Bzip: Infected with %s\n", *virname);
709 709
     }
710 710
     fclose(tmp);
... ...
@@ -717,7 +717,7 @@ static int cli_scanbzip(int desc, const char **virname, long int *scanned, const
717 717
 }
718 718
 #endif
719 719
 
720
-static int cli_scanszdd(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
720
+static int cli_scanszdd(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
721 721
 {
722 722
 	int fd, ret = CL_CLEAN, dcpy;
723 723
 	FILE *tmp = NULL, *in;
... ...
@@ -765,7 +765,7 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
765 765
 
766 766
     fd = fileno(tmp);
767 767
     lseek(fd, 0, SEEK_SET);
768
-    if((ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec)) == CL_VIRUS) {
768
+    if((ret = cli_magic_scandesc(fd, virname, scanned, engine, limits, options, arec, mrec)) == CL_VIRUS) {
769 769
 	cli_dbgmsg("SZDD: Infected with %s\n", *virname);
770 770
 	fclose(tmp);
771 771
 	if(!cli_leavetemps_flag)
... ...
@@ -781,7 +781,7 @@ static int cli_scanszdd(int desc, const char **virname, long int *scanned, const
781 781
     return ret;
782 782
 }
783 783
 
784
-static int cli_scanmscab(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
784
+static int cli_scanmscab(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
785 785
 {
786 786
 	struct mscab_decompressor *cabd = NULL;
787 787
 	struct mscabd_cabinet *base, *cab;
... ...
@@ -822,7 +822,7 @@ static int cli_scanmscab(int desc, const char **virname, long int *scanned, cons
822 822
 	    if(cabd->extract(cabd, file, tempname)) {
823 823
 		cli_dbgmsg("MSCAB: libmscab error code: %d\n", cabd->last_error(cabd));
824 824
 	    } else {
825
-		ret = cli_scanfile(tempname, virname, scanned, root, limits, options, arec, mrec);
825
+		ret = cli_scanfile(tempname, virname, scanned, engine, limits, options, arec, mrec);
826 826
 	    }
827 827
 	    if(!cli_leavetemps_flag)
828 828
 		unlink(tempname);
... ...
@@ -840,7 +840,7 @@ static int cli_scanmscab(int desc, const char **virname, long int *scanned, cons
840 840
     return ret;
841 841
 }
842 842
 
843
-static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
843
+static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
844 844
 {
845 845
 	DIR *dd;
846 846
 	struct dirent *dent;
... ...
@@ -874,14 +874,14 @@ static int cli_scandir(const char *dirname, const char **virname, long int *scan
874 874
 		    /* stat the file */
875 875
 		    if(lstat(fname, &statbuf) != -1) {
876 876
 			if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) {
877
-			    if (cli_scandir(fname, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
877
+			    if (cli_scandir(fname, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
878 878
 				free(fname);
879 879
 				closedir(dd);
880 880
 				return CL_VIRUS;
881 881
 			    }
882 882
 			} else
883 883
 			    if(S_ISREG(statbuf.st_mode))
884
-				if(cli_scanfile(fname, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
884
+				if(cli_scanfile(fname, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
885 885
 				    free(fname);
886 886
 				    closedir(dd);
887 887
 				    return CL_VIRUS;
... ...
@@ -901,7 +901,7 @@ static int cli_scandir(const char *dirname, const char **virname, long int *scan
901 901
     return 0;
902 902
 }
903 903
 
904
-static int cli_vba_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
904
+static int cli_vba_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
905 905
 {
906 906
 	int ret = CL_CLEAN, i, fd, ofd, data_len;
907 907
 	vba_project_t *vba_project;
... ...
@@ -942,7 +942,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
942 942
 		if(scanned)
943 943
 		    *scanned += data_len / CL_COUNT_PRECISION;
944 944
 
945
-		if(cli_scanbuff(data, data_len, virname, root, CL_TYPE_MSOLE2) == CL_VIRUS) {
945
+		if(cli_scanbuff(data, data_len, virname, engine, CL_TYPE_MSOLE2) == CL_VIRUS) {
946 946
 		    free(data);
947 947
 		    ret = CL_VIRUS;
948 948
 		    break;
... ...
@@ -959,7 +959,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
959 959
 	free(vba_project->offset);
960 960
 	free(vba_project);
961 961
     } else if ((fullname = ppt_vba_read(dirname))) {
962
-    	if(cli_scandir(fullname, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
962
+    	if(cli_scandir(fullname, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
963 963
 	    ret = CL_VIRUS;
964 964
 	}
965 965
 	if(!cli_leavetemps_flag)
... ...
@@ -986,7 +986,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
986 986
 		} else {
987 987
 			if(scanned)
988 988
 			    *scanned += vba_project->length[i] / CL_COUNT_PRECISION;
989
-			if(cli_scanbuff(data, vba_project->length[i], virname, root, CL_TYPE_MSOLE2) == CL_VIRUS) {
989
+			if(cli_scanbuff(data, vba_project->length[i], virname, engine, CL_TYPE_MSOLE2) == CL_VIRUS) {
990 990
 				free(data);
991 991
 				ret = CL_VIRUS;
992 992
 				break;
... ...
@@ -1015,7 +1015,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
1015 1015
     if (fd >= 0) {
1016 1016
     	ofd = cli_decode_ole_object(fd, dirname);
1017 1017
 	if (ofd >= 0) {
1018
-		ret = cli_scandesc(ofd, virname, scanned, root, 0, 0, NULL);
1018
+		ret = cli_scandesc(ofd, virname, scanned, engine, 0, 0, NULL);
1019 1019
 		close(ofd);
1020 1020
 	}
1021 1021
 	close(fd);
... ...
@@ -1043,7 +1043,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
1043 1043
 		    /* stat the file */
1044 1044
 		    if(lstat(fname, &statbuf) != -1) {
1045 1045
 			if(S_ISDIR(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode))
1046
-			    if (cli_vba_scandir(fname, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
1046
+			    if (cli_vba_scandir(fname, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1047 1047
 			    	ret = CL_VIRUS;
1048 1048
 				free(fname);
1049 1049
 				break;
... ...
@@ -1062,7 +1062,7 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int *
1062 1062
     return ret;
1063 1063
 }
1064 1064
 
1065
-static int cli_scanhtml(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1065
+static int cli_scanhtml(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1066 1066
 {
1067 1067
 	char *tempname, fullname[1024];
1068 1068
 	int ret=CL_CLEAN, fd;
... ...
@@ -1081,7 +1081,7 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
1081 1081
     snprintf(fullname, 1024, "%s/comment.html", tempname);
1082 1082
     fd = open(fullname, O_RDONLY);
1083 1083
     if (fd >= 0) {
1084
-        ret = cli_scandesc(fd, virname, scanned, root, 0, CL_TYPE_HTML, NULL);
1084
+        ret = cli_scandesc(fd, virname, scanned, engine, 0, CL_TYPE_HTML, NULL);
1085 1085
 	close(fd);
1086 1086
     }
1087 1087
 
... ...
@@ -1096,7 +1096,7 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
1096 1096
 	snprintf(fullname, 1024, "%s/nocomment.html", tempname);
1097 1097
 	fd = open(fullname, O_RDONLY);
1098 1098
 	if (fd >= 0) {
1099
-	    ret = cli_scandesc(fd, virname, scanned, root, 0, CL_TYPE_HTML, NULL);
1099
+	    ret = cli_scandesc(fd, virname, scanned, engine, 0, CL_TYPE_HTML, NULL);
1100 1100
 	    close(fd);
1101 1101
 	}
1102 1102
     }
... ...
@@ -1112,7 +1112,7 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
1112 1112
 	snprintf(fullname, 1024, "%s/script.html", tempname);
1113 1113
 	fd = open(fullname, O_RDONLY);
1114 1114
 	if (fd >= 0) {
1115
-	    ret = cli_scandesc(fd, virname, scanned, root, 0, CL_TYPE_HTML, NULL);
1115
+	    ret = cli_scandesc(fd, virname, scanned, engine, 0, CL_TYPE_HTML, NULL);
1116 1116
 	    close(fd);
1117 1117
 	}
1118 1118
     }
... ...
@@ -1126,7 +1126,7 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
1126 1126
 
1127 1127
     if (ret == CL_CLEAN) {
1128 1128
     	snprintf(fullname, 1024, "%s/rfc2397", tempname);
1129
-    	ret = cli_scandir(fullname, virname, scanned, root, limits, options, arec, mrec);
1129
+    	ret = cli_scandir(fullname, virname, scanned, engine, limits, options, arec, mrec);
1130 1130
     }
1131 1131
 
1132 1132
     if(!cli_leavetemps_flag)
... ...
@@ -1136,7 +1136,7 @@ static int cli_scanhtml(int desc, const char **virname, long int *scanned, const
1136 1136
     return ret;
1137 1137
 }
1138 1138
 
1139
-static int cli_scanole2(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1139
+static int cli_scanole2(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1140 1140
 {
1141 1141
 	char *dir;
1142 1142
 	int ret = CL_CLEAN;
... ...
@@ -1160,8 +1160,8 @@ static int cli_scanole2(int desc, const char **virname, long int *scanned, const
1160 1160
 	return ret;
1161 1161
     }
1162 1162
 
1163
-    if((ret = cli_vba_scandir(dir, virname, scanned, root, limits, options, arec, mrec)) != CL_VIRUS) {
1164
-	if(cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS) {
1163
+    if((ret = cli_vba_scandir(dir, virname, scanned, engine, limits, options, arec, mrec)) != CL_VIRUS) {
1164
+	if(cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS) {
1165 1165
 	    ret = CL_VIRUS;
1166 1166
 	}
1167 1167
     }
... ...
@@ -1172,7 +1172,7 @@ static int cli_scanole2(int desc, const char **virname, long int *scanned, const
1172 1172
     return ret;
1173 1173
 }
1174 1174
 
1175
-static int cli_scantar(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned int posix)
1175
+static int cli_scantar(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec, unsigned int posix)
1176 1176
 {
1177 1177
 	char *dir;
1178 1178
 	int ret = CL_CLEAN;
... ...
@@ -1191,7 +1191,7 @@ static int cli_scantar(int desc, const char **virname, long int *scanned, const
1191 1191
     if((ret = cli_untar(dir, desc, posix)))
1192 1192
 	cli_dbgmsg("Tar: %s\n", cl_strerror(ret));
1193 1193
     else
1194
-	ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
1194
+	ret = cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec);
1195 1195
 
1196 1196
     if(!cli_leavetemps_flag)
1197 1197
 	cli_rmdirs(dir);
... ...
@@ -1200,7 +1200,7 @@ static int cli_scantar(int desc, const char **virname, long int *scanned, const
1200 1200
     return ret;
1201 1201
 }
1202 1202
 
1203
-static int cli_scanbinhex(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1203
+static int cli_scanbinhex(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1204 1204
 {
1205 1205
 	char *dir;
1206 1206
 	int ret = CL_CLEAN;
... ...
@@ -1220,7 +1220,7 @@ static int cli_scanbinhex(int desc, const char **virname, long int *scanned, con
1220 1220
     if((ret = cli_binhex(dir, desc)))
1221 1221
 	cli_dbgmsg("Binhex: %s\n", cl_strerror(ret));
1222 1222
     else
1223
-	ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
1223
+	ret = cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec);
1224 1224
 
1225 1225
     if(!cli_leavetemps_flag)
1226 1226
 	cli_rmdirs(dir);
... ...
@@ -1229,7 +1229,7 @@ static int cli_scanbinhex(int desc, const char **virname, long int *scanned, con
1229 1229
     return ret;
1230 1230
 }
1231 1231
 
1232
-static int cli_scanmschm(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1232
+static int cli_scanmschm(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1233 1233
 {
1234 1234
 	char *tempname;
1235 1235
 	int ret = CL_CLEAN;
... ...
@@ -1245,7 +1245,7 @@ static int cli_scanmschm(int desc, const char **virname, long int *scanned, cons
1245 1245
     }
1246 1246
 
1247 1247
     if(chm_unpack(desc, tempname))
1248
-	ret = cli_scandir(tempname, virname, scanned, root, limits, options, arec, mrec);
1248
+	ret = cli_scandir(tempname, virname, scanned, engine, limits, options, arec, mrec);
1249 1249
 
1250 1250
     if(!cli_leavetemps_flag)
1251 1251
 	cli_rmdirs(tempname);
... ...
@@ -1254,7 +1254,7 @@ static int cli_scanmschm(int desc, const char **virname, long int *scanned, cons
1254 1254
     return ret;
1255 1255
 }
1256 1256
 
1257
-static int cli_scanscrenc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1257
+static int cli_scanscrenc(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1258 1258
 {
1259 1259
 	char *tempname;
1260 1260
 	int ret = CL_CLEAN;
... ...
@@ -1269,7 +1269,7 @@ static int cli_scanscrenc(int desc, const char **virname, long int *scanned, con
1269 1269
     }
1270 1270
 
1271 1271
     if (html_screnc_decode(desc, tempname))
1272
-	ret = cli_scandir(tempname, virname, scanned, root, limits, options, arec, mrec);
1272
+	ret = cli_scandir(tempname, virname, scanned, engine, limits, options, arec, mrec);
1273 1273
 
1274 1274
     if(!cli_leavetemps_flag)
1275 1275
 	cli_rmdirs(tempname);
... ...
@@ -1302,7 +1302,7 @@ static int cli_scanjpeg(int desc, const char **virname)
1302 1302
     return ret;
1303 1303
 }
1304 1304
 
1305
-static int cli_scanpdf(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1305
+static int cli_scanpdf(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1306 1306
 {
1307 1307
 	int ret;
1308 1308
 	char *dir = cli_gentemp(NULL);
... ...
@@ -1317,7 +1317,7 @@ static int cli_scanpdf(int desc, const char **virname, long int *scanned, const
1317 1317
     ret = cli_pdf(dir, desc);
1318 1318
 
1319 1319
     if(ret == CL_CLEAN)
1320
-	ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
1320
+	ret = cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec);
1321 1321
 
1322 1322
     if(!cli_leavetemps_flag)
1323 1323
 	cli_rmdirs(dir);
... ...
@@ -1326,7 +1326,7 @@ static int cli_scanpdf(int desc, const char **virname, long int *scanned, const
1326 1326
     return ret;
1327 1327
 }
1328 1328
 
1329
-static int cli_scantnef(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1329
+static int cli_scantnef(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1330 1330
 {
1331 1331
 	int ret;
1332 1332
 	char *dir = cli_gentemp(NULL);
... ...
@@ -1341,7 +1341,7 @@ static int cli_scantnef(int desc, const char **virname, long int *scanned, const
1341 1341
     ret = cli_tnef(dir, desc);
1342 1342
 
1343 1343
     if(ret == CL_CLEAN)
1344
-	ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
1344
+	ret = cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec);
1345 1345
 
1346 1346
     if(!cli_leavetemps_flag)
1347 1347
 	cli_rmdirs(dir);
... ...
@@ -1350,7 +1350,7 @@ static int cli_scantnef(int desc, const char **virname, long int *scanned, const
1350 1350
     return ret;
1351 1351
 }
1352 1352
 
1353
-static int cli_scanmail(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1353
+static int cli_scanmail(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1354 1354
 {
1355 1355
 	char *dir;
1356 1356
 	int ret;
... ...
@@ -1376,7 +1376,7 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const
1376 1376
 	return ret;
1377 1377
     }
1378 1378
 
1379
-    ret = cli_scandir(dir, virname, scanned, root, limits, options, arec, mrec);
1379
+    ret = cli_scandir(dir, virname, scanned, engine, limits, options, arec, mrec);
1380 1380
 
1381 1381
     if(!cli_leavetemps_flag)
1382 1382
 	cli_rmdirs(dir);
... ...
@@ -1385,7 +1385,7 @@ static int cli_scanmail(int desc, const char **virname, long int *scanned, const
1385 1385
     return ret;
1386 1386
 }
1387 1387
 
1388
-int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1388
+int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1389 1389
 {
1390 1390
 	int ret = CL_CLEAN, nret;
1391 1391
 	int bread = 0;
... ...
@@ -1403,14 +1403,14 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1403 1403
 	return CL_CLEAN;
1404 1404
     }
1405 1405
 
1406
-    if(!root) {
1407
-	cli_errmsg("CRITICAL: root == NULL\n");
1406
+    if(!engine) {
1407
+	cli_errmsg("CRITICAL: engine == NULL\n");
1408 1408
 	return CL_EMALFDB;
1409 1409
     }
1410 1410
 
1411 1411
     if(!options) { /* raw mode (stdin, etc.) */
1412 1412
 	cli_dbgmsg("Raw mode: No support for special files\n");
1413
-	if((ret = cli_scandesc(desc, virname, scanned, root, 0, 0, NULL) == CL_VIRUS))
1413
+	if((ret = cli_scandesc(desc, virname, scanned, engine, 0, 0, NULL) == CL_VIRUS))
1414 1414
 	    cli_dbgmsg("%s found in descriptor %d\n", *virname, desc);
1415 1415
 	return ret;
1416 1416
     }
... ...
@@ -1441,73 +1441,73 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1441 1441
     switch(type) {
1442 1442
 	case CL_TYPE_RAR:
1443 1443
 	    if(SCAN_ARCHIVE)
1444
-		ret = cli_scanrar(desc, virname, scanned, root, limits, options, arec, mrec, 0);
1444
+		ret = cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, 0);
1445 1445
 	    break;
1446 1446
 
1447 1447
 	case CL_TYPE_ZIP:
1448 1448
 	    if(SCAN_ARCHIVE)
1449
-		ret = cli_scanzip(desc, virname, scanned, root, limits, options, arec, mrec, 0);
1449
+		ret = cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, 0);
1450 1450
 	    break;
1451 1451
 
1452 1452
 	case CL_TYPE_GZ:
1453 1453
 	    if(SCAN_ARCHIVE)
1454
-		ret = cli_scangzip(desc, virname, scanned, root, limits, options, arec, mrec);
1454
+		ret = cli_scangzip(desc, virname, scanned, engine, limits, options, arec, mrec);
1455 1455
 	    break;
1456 1456
 
1457 1457
 	case CL_TYPE_BZ:
1458 1458
 #ifdef HAVE_BZLIB_H
1459 1459
 	    if(SCAN_ARCHIVE)
1460
-		ret = cli_scanbzip(desc, virname, scanned, root, limits, options, arec, mrec);
1460
+		ret = cli_scanbzip(desc, virname, scanned, engine, limits, options, arec, mrec);
1461 1461
 #endif
1462 1462
 	    break;
1463 1463
 
1464 1464
 	case CL_TYPE_MSSZDD:
1465 1465
 	    if(SCAN_ARCHIVE)
1466
-		ret = cli_scanszdd(desc, virname, scanned, root, limits, options, arec, mrec);
1466
+		ret = cli_scanszdd(desc, virname, scanned, engine, limits, options, arec, mrec);
1467 1467
 	    break;
1468 1468
 
1469 1469
 	case CL_TYPE_MSCAB:
1470 1470
 	    if(SCAN_ARCHIVE)
1471
-		ret = cli_scanmscab(desc, virname, scanned, root, limits, options, arec, mrec);
1471
+		ret = cli_scanmscab(desc, virname, scanned, engine, limits, options, arec, mrec);
1472 1472
 	    break;
1473 1473
 
1474 1474
 	case CL_TYPE_MAIL:
1475 1475
 	    if(SCAN_MAIL)
1476
-		ret = cli_scanmail(desc, virname, scanned, root, limits, options, arec, mrec);
1476
+		ret = cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec);
1477 1477
 	    break;
1478 1478
 
1479 1479
 	case CL_TYPE_TNEF:
1480 1480
 	    if(SCAN_MAIL)
1481
-		ret = cli_scantnef(desc, virname, scanned, root, limits, options, arec, mrec);
1481
+		ret = cli_scantnef(desc, virname, scanned, engine, limits, options, arec, mrec);
1482 1482
 	    break;
1483 1483
 
1484 1484
 	case CL_TYPE_MSCHM:
1485 1485
 	    if(SCAN_ARCHIVE)
1486
-		ret = cli_scanmschm(desc, virname, scanned, root, limits, options, arec, mrec);
1486
+		ret = cli_scanmschm(desc, virname, scanned, engine, limits, options, arec, mrec);
1487 1487
 	    break;
1488 1488
 
1489 1489
 	case CL_TYPE_MSOLE2:
1490 1490
 	    if(SCAN_OLE2)
1491
-		ret = cli_scanole2(desc, virname, scanned, root, limits, options, arec, mrec);
1491
+		ret = cli_scanole2(desc, virname, scanned, engine, limits, options, arec, mrec);
1492 1492
 	    break;
1493 1493
 
1494 1494
 	case CL_TYPE_POSIX_TAR:
1495 1495
 	    if(SCAN_ARCHIVE)
1496
-		ret = cli_scantar(desc, virname, scanned, root, limits, options, arec, mrec, 1);
1496
+		ret = cli_scantar(desc, virname, scanned, engine, limits, options, arec, mrec, 1);
1497 1497
 	    break;
1498 1498
 
1499 1499
 	case CL_TYPE_OLD_TAR:
1500 1500
 	    if(SCAN_ARCHIVE)
1501
-		ret = cli_scantar(desc, virname, scanned, root, limits, options, arec, mrec, 0);
1501
+		ret = cli_scantar(desc, virname, scanned, engine, limits, options, arec, mrec, 0);
1502 1502
 	    break;
1503 1503
 
1504 1504
 	case CL_TYPE_BINHEX:
1505 1505
 	    if(SCAN_ARCHIVE)
1506
-		ret = cli_scanbinhex(desc, virname, scanned, root, limits, options, arec, mrec);
1506
+		ret = cli_scanbinhex(desc, virname, scanned, engine, limits, options, arec, mrec);
1507 1507
 	    break;
1508 1508
 
1509 1509
 	case CL_TYPE_SCRENC:
1510
-	    ret = cli_scanscrenc(desc, virname, scanned, root, limits, options, arec, mrec);
1510
+	    ret = cli_scanscrenc(desc, virname, scanned, engine, limits, options, arec, mrec);
1511 1511
 	    break;
1512 1512
 
1513 1513
 	case CL_TYPE_RIFF:
... ...
@@ -1520,11 +1520,11 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1520 1520
 
1521 1521
 	case CL_TYPE_PDF:
1522 1522
 	    if(SCAN_ARCHIVE)    /* you may wish to change this line */
1523
-		ret = cli_scanpdf(desc, virname, scanned, root, limits, options, arec, mrec);
1523
+		ret = cli_scanpdf(desc, virname, scanned, engine, limits, options, arec, mrec);
1524 1524
 	    break;
1525 1525
 
1526 1526
 	case CL_TYPE_ELF: /* TODO: Add ScanELF option */
1527
-		ret = cli_scanelf(desc, virname, scanned, root, limits, options, arec, mrec);
1527
+		ret = cli_scanelf(desc, virname, scanned, engine, limits, options, arec, mrec);
1528 1528
 	    break;
1529 1529
 
1530 1530
 	case CL_TYPE_DATA:
... ...
@@ -1561,7 +1561,7 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1561 1561
 	if(lseek(desc, 0, SEEK_SET) < 0)
1562 1562
 	    cli_errmsg("lseek() failed, trying to continue anyway...\n");
1563 1563
 
1564
-	if((nret = cli_scandesc(desc, virname, scanned, root, ftrec, type, &ftoffset)) == CL_VIRUS) {
1564
+	if((nret = cli_scandesc(desc, virname, scanned, engine, ftrec, type, &ftoffset)) == CL_VIRUS) {
1565 1565
 	    cli_dbgmsg("%s found in descriptor %d.\n", *virname, desc);
1566 1566
 	    return CL_VIRUS;
1567 1567
 
... ...
@@ -1575,27 +1575,27 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1575 1575
 	    switch(nret) {
1576 1576
 		case CL_TYPE_HTML:
1577 1577
 		    if(SCAN_HTML && type == CL_TYPE_UNKNOWN_TEXT)
1578
-			if(cli_scanhtml(desc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS)
1578
+			if(cli_scanhtml(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1579 1579
 			    return CL_VIRUS;
1580 1580
 		    break;
1581 1581
 
1582 1582
 		case CL_TYPE_MAIL:
1583 1583
 		    if(SCAN_MAIL && type == CL_TYPE_UNKNOWN_TEXT)
1584
-			if(cli_scanmail(desc, virname, scanned, root, limits, options, arec, mrec) == CL_VIRUS)
1584
+			if(cli_scanmail(desc, virname, scanned, engine, limits, options, arec, mrec) == CL_VIRUS)
1585 1585
 			    return CL_VIRUS;
1586 1586
 		    break;
1587 1587
 
1588 1588
 		case CL_TYPE_RARSFX:
1589 1589
 		    if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE)
1590 1590
 			cli_dbgmsg("RAR-SFX found at %d\n", ftoffset);
1591
-			if(cli_scanrar(desc, virname, scanned, root, limits, options, arec, mrec, ftoffset) == CL_VIRUS)
1591
+			if(cli_scanrar(desc, virname, scanned, engine, limits, options, arec, mrec, ftoffset) == CL_VIRUS)
1592 1592
 			    return CL_VIRUS;
1593 1593
 		    break;
1594 1594
 
1595 1595
 		case CL_TYPE_ZIPSFX:
1596 1596
 		    if(SCAN_ARCHIVE && type == CL_TYPE_MSEXE)
1597 1597
 			cli_dbgmsg("ZIP-SFX found at %d\n", ftoffset);
1598
-			if(cli_scanzip(desc, virname, scanned, root, limits, options, arec, mrec, ftoffset) == CL_VIRUS)
1598
+			if(cli_scanzip(desc, virname, scanned, engine, limits, options, arec, mrec, ftoffset) == CL_VIRUS)
1599 1599
 			    return CL_VIRUS;
1600 1600
 		    break;
1601 1601
 	    }
... ...
@@ -1611,7 +1611,7 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1611 1611
 	 */
1612 1612
 	case CL_TYPE_MSEXE:
1613 1613
 	    if(SCAN_PE)
1614
-		ret = cli_scanpe(desc, virname, scanned, root, limits, options, arec, mrec);
1614
+		ret = cli_scanpe(desc, virname, scanned, engine, limits, options, arec, mrec);
1615 1615
 	    break;
1616 1616
 
1617 1617
 	default:
... ...
@@ -1627,12 +1627,12 @@ int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const
1627 1627
     }
1628 1628
 }
1629 1629
 
1630
-int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options)
1630
+int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
1631 1631
 {
1632
-    return cli_magic_scandesc(desc, virname, scanned, root, limits, options, 0, 0);
1632
+    return cli_magic_scandesc(desc, virname, scanned, engine, limits, options, 0, 0);
1633 1633
 }
1634 1634
 
1635
-static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1635
+static int cli_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec)
1636 1636
 {
1637 1637
 	int fd, ret;
1638 1638
 
... ...
@@ -1641,13 +1641,13 @@ static int cli_scanfile(const char *filename, const char **virname, unsigned lon
1641 1641
     if((fd = open(filename, O_RDONLY)) == -1)
1642 1642
 	return CL_EOPEN;
1643 1643
 
1644
-    ret = cli_magic_scandesc(fd, virname, scanned, root, limits, options, arec, mrec);
1644
+    ret = cli_magic_scandesc(fd, virname, scanned, engine, limits, options, arec, mrec);
1645 1645
 
1646 1646
     close(fd);
1647 1647
     return ret;
1648 1648
 }
1649 1649
 
1650
-int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options)
1650
+int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options)
1651 1651
 {
1652 1652
 	int fd, ret;
1653 1653
 
... ...
@@ -1655,7 +1655,7 @@ int cl_scanfile(const char *filename, const char **virname, unsigned long int *s
1655 1655
     if((fd = open(filename, O_RDONLY)) == -1)
1656 1656
 	return CL_EOPEN;
1657 1657
 
1658
-    ret = cl_scandesc(fd, virname, scanned, root, limits, options);
1658
+    ret = cl_scandesc(fd, virname, scanned, engine, limits, options);
1659 1659
     close(fd);
1660 1660
 
1661 1661
     return ret;
... ...
@@ -21,6 +21,6 @@
21 21
 
22 22
 #include "clamav.h"
23 23
 
24
-int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
24
+int cli_magic_scandesc(int desc, const char **virname, long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options, unsigned int arec, unsigned int mrec);
25 25
 
26 26
 #endif