Browse code

New code added.

git-svn-id: file:///var/lib/svn/clamav-devel/trunk/clamav-devel@64 77e5149b-7576-45b1-b177-96237e5ba77b

Tomasz Kojm authored on 2003/09/29 20:44:52
Showing 27 changed files
... ...
@@ -7,6 +7,9 @@ Nigel Horne <njh@bandsman.co.uk>
7 7
 home page : http://bandsman.co.uk
8 8
 Author of clamav-milter and the whole mbox code.
9 9
 
10
+System administrator (www, mailing lists, mirror issues, virus
11
+submission mechanisms): Luca 'NERvOus' Gibelli <nervous@nervous.it>
12
+
10 13
 Database developers:
11 14
 
12 15
 aCaB <acab@digitalfuture.it>
... ...
@@ -15,6 +18,7 @@ Jason Englander <jason@englanders.cc>
15 15
 Tomasz Kojm <zolw@konarski.edu.pl>
16 16
 Tomasz Papszun <tomek@lodz.tpsa.pl>
17 17
 
18
+
18 19
 TrashScan was written by Trashware <trashware@gmx.net>.
19 20
 
20 21
 ClamAV patches were submitted by (in alphabetical order):
... ...
@@ -28,6 +32,7 @@ Jason Englander <jason@englanders.cc>
28 28
 David Ford <david+cert@blue-labs.org>
29 29
 Nigel Horne <njh@smsltd.demon.co.uk>
30 30
 Hrvoje Habjanic <hrvoje.habjanic@zg.hinet.hr>
31
+Nicholas M. Kirsch <nick@kirsch.org>
31 32
 Robbert Kouprie <robbert@exx.nl>
32 33
 Thomas Lamy <Thomas.Lamy@in-online.net>
33 34
 Peter N Lewis <peter@stairways.com.au>
... ...
@@ -1,3 +1,19 @@
1
+Mon Sep 29 13:42:51 CEST 2003 (tk)
2
+----------------------------------
3
+  * libclamav: initial support for cvd file format (a database container file
4
+	       with support for digital signatures)
5
+  * libclamav: fixed zip recursion problem introduced in -20030907 (bug
6
+	       reported by Tomasz Papszun)
7
+  * libclamav: support for gzip and Maildir files was enabled if ScanMail _or_
8
+	       ScanArchive was defined. Fixed.
9
+  * libclamav: zziplib updated to 0.12.83 (probably not the newest one but
10
+	       seems to be very stable)
11
+  * sigtool: --build (builds a cvd file, not finished yet)
12
+  * clamd: new directive TCPAddr by Bernard Quatermass
13
+  * libclamav: new scan option CL_DISABLERAR (disables built-in rar unpacker)
14
+  * clamd: rar scanning is now disabled by default and may be enabled with
15
+	   ScanRAR in clamav.conf.
16
+
1 17
 Mon Sep 29 07:15:30 BST 2003 (njh)
2 18
 ----------------------------------
3 19
   * clamav-milter: ensure remoteIP is initialised
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
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
... ...
@@ -46,11 +46,13 @@ struct cfgstruct *parsecfg(const char *cfgfile)
46 46
 	    {"MaxFileSize", OPT_COMPSIZE},
47 47
 	    {"ScanMail", OPT_NOARG},
48 48
 	    {"ScanArchive", OPT_NOARG},
49
+	    {"ScanRAR", OPT_NOARG},
49 50
 	    {"ArchiveMaxFileSize", OPT_COMPSIZE},
50 51
 	    {"ArchiveMaxRecursion", OPT_NUM},
51 52
 	    {"ArchiveMaxFiles", OPT_NUM},
52 53
 	    {"ArchiveLimitMemoryUsage", OPT_NOARG},
53 54
 	    {"DataDirectory", OPT_STR},
55
+	    {"TCPAddr", OPT_STR},
54 56
 	    {"TCPSocket", OPT_NUM},
55 57
 	    {"LocalSocket", OPT_STR},
56 58
 	    {"MaxConnectionQueueLength", OPT_NUM},
... ...
@@ -215,6 +215,9 @@ int scanstream(int odesc, unsigned long int *scanned, const struct cl_node *root
215 215
 	return -1;
216 216
     }
217 217
 
218
+
219
+    logg("*Accepted connection on port %d\n", port);
220
+
218 221
     if(cfgopt(copt, "StreamSaveToDisk")) {
219 222
 	if((tmp = tmpfile()) == NULL) {
220 223
 	    shutdown(sockfd, 2);
... ...
@@ -447,6 +447,13 @@ int acceptloop(int socketd, struct cl_node *root, const struct cfgstruct *copt)
447 447
     if(cfgopt(copt, "ScanArchive")) { 
448 448
 	logg("Archive support enabled.\n");
449 449
 	options |= CL_ARCHIVE;
450
+
451
+	if(cfgopt(copt, "ScanRAR")) {
452
+	    logg("RAR support enabled.\n");
453
+	} else {
454
+	    logg("RAR support disabled.\n");
455
+	    options |= CL_DISABLERAR;
456
+	}
450 457
     } else {
451 458
 	logg("Archive support disabled.\n");
452 459
     }
... ...
@@ -36,11 +36,19 @@ int tcpserver(const struct optstruct *opt, const struct cfgstruct *copt, struct
36 36
 	int sockfd, backlog;
37 37
 	struct cfgstruct *cpt;
38 38
 	char *estr;
39
+	const char *taddr;
39 40
 
40 41
     memset((char *) &server, 0, sizeof(server));
41 42
     server.sin_family = AF_INET;
42 43
     server.sin_port = htons(cfgopt(copt, "TCPSocket")->numarg);
43
-    server.sin_addr.s_addr = INADDR_ANY;
44
+    taddr = cfgopt(copt, "TCPAddr")->strarg;
45
+    if ( taddr != NULL && *taddr )
46
+    {
47
+	server.sin_addr.s_addr = inet_addr( taddr );
48
+    }else
49
+    {
50
+	server.sin_addr.s_addr = INADDR_ANY;
51
+    }
44 52
 
45 53
 
46 54
     if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
... ...
@@ -55,8 +63,12 @@ int tcpserver(const struct optstruct *opt, const struct cfgstruct *copt, struct
55 55
 	//fprintf(stderr, "ERROR: can't bind(): %s\n", estr);
56 56
 	logg("!bind() error: %s\n", estr);
57 57
 	exit(1);
58
-    } else
59
-	logg("Binded to port %d\n", cfgopt(copt, "TCPSocket")->numarg);
58
+    } else {
59
+	if ( taddr != NULL && *taddr )
60
+	    logg("Bound to address %s on port %d\n", taddr, cfgopt(copt, "TCPSocket")->numarg);
61
+	else
62
+	    logg("Bound to port %d\n", cfgopt(copt, "TCPSocket")->numarg);
63
+    }
60 64
 
61 65
     if((cpt = cfgopt(copt, "MaxConnectionQueueLength")))
62 66
 	backlog = cpt->numarg;
... ...
@@ -182,7 +182,7 @@ int scanmanager(const struct optstruct *opt)
182 182
 		}
183 183
 		/* generate the temporary directory */
184 184
 
185
-		dir = gentemp(tmpdir);
185
+		dir = cl_gentemp(tmpdir);
186 186
 		if(mkdir(dir, 0700)) {
187 187
 			mprintf("@Can't create the temporary directory %s\n", dir);
188 188
 			exit(63); /* critical */
... ...
@@ -473,7 +473,7 @@ int scancompressed(const char *filename, struct cl_node *root, const struct pass
473 473
 
474 474
     /* generate the temporary directory */
475 475
 
476
-    gendir = gentemp(tmpdir);
476
+    gendir = cl_gentemp(tmpdir);
477 477
     if(mkdir(gendir, 0700)) {
478 478
 	mprintf("@Can't create the temporary directory %s\n", gendir);
479 479
 	exit(63); /* critical */
... ...
@@ -670,7 +670,7 @@ int scandenied(const char *filename, struct cl_node *root, const struct passwd *
670 670
     }
671 671
 
672 672
     /* generate the temporary directory */
673
-    gendir = gentemp(tmpdir);
673
+    gendir = cl_gentemp(tmpdir);
674 674
     if(mkdir(gendir, 0700)) {
675 675
 	mprintf("@Can't create the temporary directory %s\n", gendir);
676 676
 	exit(63); /* critical */
... ...
@@ -420,32 +420,6 @@ int filecopy(const char *src, const char *dest)
420 420
     return close(d);
421 421
 }
422 422
 
423
-char *gentemp(const char *dir)
424
-{
425
-	char *name, *mdir, *tmp;
426
-	unsigned char salt[32];
427
-	int cnt=0, i;
428
-
429
-    if(!dir)
430
-	mdir = "/tmp";
431
-    else
432
-	mdir = (char *) dir;
433
-
434
-    name = (char*) calloc(strlen(mdir) + 1 + 16 + 1, sizeof(char));
435
-    cnt += sprintf(name, "%s/", mdir);
436
-
437
-    do {
438
-	for(i = 0; i < 32; i++)
439
-	    salt[i] = cl_rndnum(255);
440
-
441
-	tmp = cl_md5buff(salt, 32);
442
-	strncat(name, tmp, 16);
443
-	free(tmp);
444
-    } while(fileinfo(name, 1) != -1);
445
-
446
-    return(name);
447
-}
448
-
449 423
 int strbcasestr(const char *haystack, const char *needle)
450 424
 {
451 425
 	char *pt = (char *) haystack;
... ...
@@ -35,7 +35,6 @@ int strbcasestr(const char *haystack, const char *needle);
35 35
 int readaccess(const char *path, const char *username);
36 36
 int writeaccess(const char *path, const char *username);
37 37
 int filecopy(const char *src, const char *dest);
38
-char *gentemp(const char *dir);
39 38
 
40 39
 /* njh@bandsman.co.uk: for BeOS */
41 40
 /* TODO: configure should see if sete[ug]id is set on the target */
... ...
@@ -53,7 +53,13 @@ Example
53 53
 LocalSocket /tmp/clamd
54 54
 
55 55
 # Remove stale socket after unclean shutdown.
56
-#FixStaleSocket
56
+#RemoveStaleSocket
57
+
58
+# TCP address.
59
+# By default we bind to INADDR_ANY, probably not wise.
60
+# Enable the following to provide some degree of protection
61
+# from the outside world.
62
+#TCPAddr 127.0.0.1
57 63
 
58 64
 # TCP port address.
59 65
 #TCPSocket 3310
... ...
@@ -132,6 +138,12 @@ MaxDirectoryRecursion 15
132 132
 # Comment this line to disable scanning of the archives.
133 133
 ScanArchive
134 134
 
135
+
136
+# By default the built-in RAR unpacker is disabled because the code
137
+# terribly leaks, however it's probably a good idea to enable it.
138
+#ScanRAR
139
+
140
+
135 141
 # Options below protect your system against Denial of Service attacks
136 142
 # with archive bombs.
137 143
 
... ...
@@ -174,7 +174,7 @@ int downloadmanager(const struct optstruct *opt, const char *hostname)
174 174
 	/* temporary file is created in clamav's directory thus we don't need
175 175
 	 * to create it immediately, because race conditions are impossible
176 176
 	 */
177
-	tempname = gentemp(".");
177
+	tempname = cl_gentemp(".");
178 178
 
179 179
 	/* download the database */
180 180
 	/* FIXME: We need to reconnect, because we won't be able to donwload
... ...
@@ -232,7 +232,7 @@ int downloadmanager(const struct optstruct *opt, const char *hostname)
232 232
     }
233 233
 
234 234
     if(updatedb2) {
235
-	tempname = gentemp(".");
235
+	tempname = cl_gentemp(".");
236 236
 
237 237
 	/* download viruses.db2 */
238 238
 
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
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
... ...
@@ -56,11 +56,13 @@ extern "C"
56 56
 #define CL_EMALFDB	-5 /* malformed database */
57 57
 #define CL_EPATSHORT	-6 /* pattern too short */
58 58
 #define CL_ETMPDIR	-7 /* mkdir() failed */
59
+#define CL_ECVDEXTR	-8 /* CVD extraction failure */
59 60
 
60 61
 /* options */
61 62
 #define CL_RAW		  00
62 63
 #define CL_ARCHIVE	  01
63 64
 #define CL_MAIL		0100
65
+#define CL_DISABLERAR  01000
64 66
 
65 67
 struct patt {
66 68
     short int *pattern;
... ...
@@ -94,6 +96,16 @@ struct cl_stat {
94 94
     struct stat *stattab;
95 95
 };
96 96
 
97
+struct cl_cvd {
98
+    char *time;	    /* 2 */
99
+    int version;    /* 3 */
100
+    int sigs;	    /* 4 */
101
+    short int fl;   /* 5 */
102
+    char *md5;	    /* 6 */
103
+    char *dsig;	    /* 7 */
104
+    char *builder;  /* 8 */
105
+};
106
+
97 107
 /* file scanning */
98 108
 extern int cl_scanbuff(const char *buffer, unsigned int length, char **virname, const struct cl_node *root);
99 109
 
... ...
@@ -106,6 +118,9 @@ extern int cl_loaddb(const char *filename, struct cl_node **root, int *virnum);
106 106
 extern int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum);
107 107
 extern char *cl_retdbdir(void);
108 108
 
109
+extern struct cl_cvd *cl_cvdhead(const char *file);
110
+extern void cl_cvdfree(struct cl_cvd *cvd);
111
+
109 112
 /* data dir stat functions */
110 113
 extern int cl_statinidir(const char *dirname, struct cl_stat *dbstat);
111 114
 extern int cl_statchkdir(const struct cl_stat *dbstat);
... ...
@@ -126,7 +141,7 @@ extern char *cl_md5buff(const char *buffer, unsigned int length);
126 126
 
127 127
 extern int cl_mbox(const char *dir, int desc);
128 128
 
129
-/* compute MD5 message digest from filename (compatible with md5sum(1)) */
129
+/* compute MD5 message digest from file (compatible with md5sum(1)) */
130 130
 extern char *cl_md5file(const char *filename);
131 131
 
132 132
 /* decode hexadecimal string */
... ...
@@ -138,6 +153,9 @@ extern char *cl_str2hex(const char *string, unsigned int len);
138 138
 /* generate a pseudo-random number */
139 139
 extern unsigned int cl_rndnum(unsigned int max);
140 140
 
141
+/* generate unique file name in temporary directory */
142
+char *cl_gentemp(const char *dir);
143
+
141 144
 #ifdef __cplusplus
142 145
 };
143 146
 #endif
144 147
new file mode 100644
... ...
@@ -0,0 +1,314 @@
0
+/*
1
+ *  Copyright (C) 2003 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *
3
+ *  untgz() is based on public domain minitar utility by Charles G. Waldman
4
+ *
5
+ *  This program is free software; you can redistribute it and/or modify
6
+ *  it under the terms of the GNU General Public License as published by
7
+ *  the Free Software Foundation; either version 2 of the License, or
8
+ *  (at your option) any later version.
9
+ *
10
+ *  This program is distributed in the hope that it will be useful,
11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ *  GNU General Public License for more details.
14
+ *
15
+ *  You should have received a copy of the GNU General Public License
16
+ *  along with this program; if not, write to the Free Software
17
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
+ */
19
+
20
+
21
+#include <stdio.h>
22
+#include <string.h>
23
+#include <stdlib.h>
24
+#include <sys/types.h>
25
+#include <sys/stat.h>
26
+#include <fcntl.h>
27
+#include <zlib.h>
28
+
29
+#include "clamav.h"
30
+
31
+#define TAR_BLOCKSIZE 512
32
+
33
+int cli_untgz(int fd, const char *destdir)
34
+{
35
+	char *fullname, osize[13], name[101], type;
36
+	char block[TAR_BLOCKSIZE];
37
+	int nbytes, nread, nwritten, in_block = 0;
38
+	unsigned int size;
39
+	FILE *outfile = NULL;
40
+	gzFile *infile;
41
+
42
+    cli_dbgmsg("in cli_untgz()\n");
43
+
44
+    if((infile = gzdopen(fd, "rb")) == NULL) {
45
+	cli_errmsg("Can't gzdopen() descriptor %d\n", fd);
46
+	return -1;
47
+    }
48
+
49
+
50
+    fullname = (char *) calloc(sizeof(char), strlen(destdir) + 100 + 5);
51
+
52
+    while(1) {
53
+
54
+	nread = gzread(infile, block, TAR_BLOCKSIZE);
55
+
56
+	if(!in_block && nread == 0)
57
+	    break;
58
+
59
+	if(nread != TAR_BLOCKSIZE) {
60
+	    cli_errmsg("Incomplete block read.\n");
61
+	    free(fullname);
62
+	    return -1;
63
+	}
64
+
65
+	if(!in_block) {
66
+	    if (block[0] == '\0')  /* We're done */
67
+		break;
68
+
69
+	    strncpy(name, block, 100);
70
+	    name[100] = '\0';
71
+	    strcpy(fullname, destdir);
72
+	    strcat(fullname, "/");
73
+	    strcat(fullname, name);
74
+	    cli_dbgmsg("Unpacking %s\n",fullname);
75
+	    type = block[156];
76
+
77
+	    switch(type) {
78
+		case '0':
79
+		case '\0':
80
+		    break;
81
+		case '5':
82
+		    cli_errmsg("Directories in CVD are not supported.\n");
83
+		    free(fullname);
84
+		    return -1;
85
+		default:
86
+		    cli_errmsg("Unknown type flag %c.\n",type);
87
+		    free(fullname);
88
+		    return -1;
89
+	    }
90
+
91
+	    in_block = 1;
92
+
93
+	    if(outfile) {
94
+		if(fclose(outfile)) {
95
+		    cli_errmsg("Cannot close file %s.\n", fullname);
96
+		    free(fullname);
97
+		    return -1;
98
+		}
99
+		outfile = NULL;
100
+	    }
101
+
102
+	    if(!(outfile = fopen(fullname, "wb"))) {
103
+		cli_errmsg("Cannot create file %s.\n", fullname);
104
+		free(fullname);
105
+		return -1;
106
+	    }
107
+
108
+	    strncpy(osize, block + 124, 12);
109
+	    osize[12] = '\0';
110
+	    size = -1;
111
+	    sscanf(osize, "%o", &size);
112
+
113
+	    if(size < 0) {
114
+		cli_errmsg("Invalid size in header.\n");
115
+		free(fullname);
116
+		return -1;
117
+	    }
118
+
119
+	} else { /* write or continue writing file contents */
120
+	    nbytes = size > TAR_BLOCKSIZE ? TAR_BLOCKSIZE : size;
121
+	    nwritten = fwrite(block, 1, nbytes, outfile);
122
+
123
+	    if(nwritten != nbytes) {
124
+		cli_errmsg("Wrote %d instead of %d (%s).\n", nwritten, nbytes, fullname);
125
+		free(fullname);
126
+		return -1;
127
+	    }
128
+
129
+	    size -= nbytes;
130
+	    if(size == 0)
131
+		in_block = 0;
132
+	}
133
+    }
134
+
135
+    return 0;
136
+}
137
+
138
+char *cli_cut(const char *line, int field)
139
+{
140
+        int length, counter = 0, i, j = 0, k;
141
+        char *buffer;
142
+
143
+    length = strlen(line);
144
+    buffer = (char *) cli_calloc(length, sizeof(char));
145
+
146
+    for(i = 0; i < length; i++) {
147
+        if(line[i] == ':') {
148
+            counter++;
149
+            if(counter == field) {
150
+		break;
151
+	    } else {
152
+		memset(buffer, 0, length);
153
+		j = 0;
154
+	    }
155
+        } else {
156
+            buffer[j++] = line[i];
157
+        }
158
+    }
159
+
160
+    return (char *) cli_realloc(buffer, strlen(buffer) + 1);
161
+}
162
+
163
+struct cl_cvd *cli_cvdhead(const char *head)
164
+{
165
+	char *pt;
166
+	struct cl_cvd *cvd;
167
+
168
+    cvd = (struct cl_cvd *) cli_calloc(1, sizeof(struct cl_cvd));
169
+    cvd->time = cli_cut(head, 2);
170
+
171
+    pt = cli_cut(head, 3);
172
+    cvd->version = atoi(pt);
173
+    free(pt);
174
+
175
+    pt = cli_cut(head, 4);
176
+    cvd->sigs = atoi(pt);
177
+    free(pt);
178
+
179
+    pt = cli_cut(head, 5);
180
+    cvd->fl = (short int) atoi(pt);
181
+    free(pt);
182
+
183
+    cvd->md5 = cli_cut(head, 6);
184
+    cvd->dsig = cli_cut(head, 7);
185
+    cvd->builder = cli_cut(head, 8);
186
+
187
+    return cvd;
188
+}
189
+
190
+struct cl_cvd *cl_cvdhead(const char *file)
191
+{
192
+	char head[257];
193
+	FILE *fd;
194
+	int i;
195
+
196
+
197
+    if((fd = fopen(file, "rb")) == NULL) {
198
+	cli_errmsg("Can't open CVD file %s\n", file);
199
+	return NULL;
200
+    }
201
+
202
+    if(fread(head, 1, 256, fd) != 256) {
203
+	cli_errmsg("Can't read CVD head from %s\n", file);
204
+	return NULL;
205
+    }
206
+    head[256] = 0;
207
+
208
+    for(i = 255; i > 0 && !isalnum(head[i]); head[i] = 0, i--);
209
+
210
+    if(strncmp(head, "ClamAV-VDB:", 11)) {
211
+	cli_errmsg("%s is not a CVD file.\n");
212
+	return NULL;
213
+    }
214
+
215
+    return cli_cvdhead(head);
216
+}
217
+
218
+void cl_cvdfree(struct cl_cvd *cvd)
219
+{
220
+    free(cvd->time);
221
+    free(cvd->md5);
222
+    free(cvd->dsig);
223
+    free(cvd->builder);
224
+    free(cvd);
225
+}
226
+
227
+int cli_cvdload(FILE *fd, struct cl_node **root, int *virnum)
228
+{
229
+        char head[257], *dir, *tmp, buffer[BUFFSIZE];
230
+	int bytes;
231
+	struct cl_cvd *cvd;
232
+	const char *tmpdir;
233
+	FILE *tmpd;
234
+
235
+    cli_dbgmsg("in cli_cvdload()\n");
236
+
237
+    if(fread(head, 1, 256, fd) != 256) {
238
+	cli_errmsg("Can't read CVD head.\n");
239
+	return -1;
240
+    }
241
+    head[256] = 0;
242
+
243
+    cvd = cli_cvdhead(head);
244
+
245
+    /* verify md5/dsig */
246
+
247
+
248
+    /* unpack */
249
+
250
+    tmpdir = getenv("TMPDIR");
251
+
252
+    if(tmpdir == NULL)
253
+#ifdef P_tmpdir
254
+	tmpdir = P_tmpdir;
255
+#else
256
+	tmpdir = "/tmp";
257
+#endif
258
+
259
+    dir = cl_gentemp(tmpdir);
260
+    if(mkdir(dir, 0700)) {
261
+	cli_errmsg("cli_cvdload():  Can't create temporary directory %s\n", dir);
262
+	return CL_ETMPDIR;
263
+    }
264
+
265
+    /* 
266
+    if(cli_untgz(fileno(fd), dir)) {
267
+	cli_errmsg("cli_cvdload(): Can't unpack CVD file.\n");
268
+	return CL_ECVDEXTR;
269
+    }
270
+    */
271
+
272
+    /* FIXME: it seems there is some problem with current position after
273
+     * gzdopen() in cli_untgz(). Temporarily we need this wrapper:
274
+     */
275
+
276
+	    /* start */
277
+
278
+	    tmp = cl_gentemp(tmpdir);
279
+	    if((tmpd = fopen(tmp, "wb+")) == NULL) {
280
+		cli_errmsg("Can't create temporary file %s\n", tmp);
281
+		free(dir);
282
+		free(tmp);
283
+		return -1;
284
+	    }
285
+	    while((bytes = fread(buffer, 1, BUFFSIZE, fd)) > 0)
286
+		fwrite(buffer, 1, bytes, tmpd);
287
+
288
+	    fflush(tmpd);
289
+	    fseek(tmpd, 0L, SEEK_SET);
290
+
291
+	    if(cli_untgz(fileno(tmpd), dir)) {
292
+		cli_errmsg("cli_cvdload(): Can't unpack CVD file.\n");
293
+		cli_rmdirs(dir);
294
+		free(dir);
295
+		unlink(tmp);
296
+		free(tmp);
297
+		return CL_ECVDEXTR;
298
+	    }
299
+
300
+	    fclose(tmpd);
301
+	    unlink(tmp);
302
+	    free(tmp);
303
+
304
+	    /* end */
305
+
306
+    /* load extracted directory */
307
+    cl_loaddbdir(dir, root, virnum);
308
+
309
+    cli_rmdirs(dir);
310
+    free(dir);
311
+
312
+    return 0;
313
+}
... ...
@@ -119,8 +119,10 @@ char *cl_strerror(int clerror)
119 119
 	    return "Malformed database.";
120 120
 	case CL_EPATSHORT:
121 121
 	    return "Too short pattern detected.";
122
+	case CL_ECVDEXTR:
123
+	     return "CVD extraction failure.";
122 124
 	case CL_ENULLARG:
123
-	    return "Null argument passed when initialized is required.";
125
+	    return "Null argument passed while initialized is required.";
124 126
 	default:
125 127
 	    return "Unknown error code.";
126 128
     }
... ...
@@ -200,6 +202,19 @@ void *cli_calloc(size_t nmemb, size_t size)
200 200
     } else return alloc;
201 201
 }
202 202
 
203
+void *cli_realloc(void *ptr, size_t size)
204
+{
205
+	void *alloc;
206
+
207
+    alloc = realloc(ptr, size);
208
+
209
+    if(!alloc) {
210
+	cli_errmsg("cli_realloc(): Can't re-allocate memory to %d byte.\n", size);
211
+	perror("realloc_problem");
212
+	return NULL;
213
+    } else return alloc;
214
+}
215
+
203 216
 #ifndef C_URANDOM
204 217
 /* it's very weak */
205 218
 #include <sys/time.h>
... ...
@@ -253,7 +268,8 @@ unsigned int cl_rndnum(unsigned int max)
253 253
 }
254 254
 #endif
255 255
 
256
-char *cli_gentemp(const char *dir)
256
+/* it uses MD5 to avoid potential races in tmp */
257
+char *cl_gentemp(const char *dir)
257 258
 {
258 259
 	char *name, *mdir, *tmp;
259 260
 	unsigned char salt[32];
... ...
@@ -26,7 +26,7 @@ void cli_errmsg(const char *str, ...);
26 26
 void cli_dbgmsg(const char *str, ...);
27 27
 void *cli_malloc(size_t nmemb);
28 28
 void *cli_calloc(size_t nmemb, size_t size);
29
-char *cli_gentemp(const char *dir);
29
+void *cli_realloc(void *ptr, size_t size);
30 30
 int cli_rmdirs(const char *dirname);
31 31
 
32 32
 #endif
... ...
@@ -1,6 +1,5 @@
1
-
2 1
 /*
3
- *  Copyright (C) 2002 Tomasz Kojm <zolw@konarski.edu.pl>
2
+ *  Copyright (C) 2002, 2003 Tomasz Kojm <zolw@konarski.edu.pl>
4 3
  *
5 4
  *  This program is free software; you can redistribute it and/or modify
6 5
  *  it under the terms of the GNU General Public License as published by
... ...
@@ -90,6 +89,17 @@ int cl_loaddb(const char *filename, struct cl_node **root, int *virnum)
90 90
 
91 91
     cli_dbgmsg("Loading %s\n", filename);
92 92
 
93
+    /* check for CVD file */
94
+    fgets(buffer, 12, fd);
95
+    fseek(fd, 0L, SEEK_SET);
96
+
97
+    if(!strncmp(buffer, "ClamAV-VDB:", 11)) {
98
+	cli_dbgmsg("%s: CVD file detected\n", filename);
99
+	ret = cli_cvdload(fd, root, virnum);
100
+	fclose(fd);
101
+	return ret;
102
+    }
103
+
93 104
     while(fgets(buffer, BUFFSIZE, fd)) {
94 105
 
95 106
 	/* for forward compatibility */
... ...
@@ -181,11 +191,15 @@ int cl_loaddbdir(const char *dirname, struct cl_node **root, int *virnum)
181 181
 
182 182
     while((dent = readdir(dd))) {
183 183
 	if(dent->d_ino) {
184
-	    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") && (cli_strbcasestr(dent->d_name, ".db") || cli_strbcasestr(dent->d_name, ".db2"))) {
184
+	    if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..") &&
185
+	    (cli_strbcasestr(dent->d_name, ".db")  ||
186
+	     cli_strbcasestr(dent->d_name, ".db2") ||
187
+	     cli_strbcasestr(dent->d_name, ".cvd"))) {
188
+
185 189
 		dbfile = (char *) cli_calloc(strlen(dent->d_name) + strlen(dirname) + 2, sizeof(char));
186 190
 
187 191
 		if(!dbfile) {
188
-		    cli_dbgmsg("cl_loaddbdir() -> dbfile == NULL\n");
192
+		    cli_dbgmsg("cl_loaddbdir(): dbfile == NULL\n");
189 193
 		    closedir(dd);
190 194
 		    return CL_EMEM;
191 195
 		}
... ...
@@ -49,6 +49,7 @@ int cli_scanrar_inuse = 0;
49 49
 
50 50
 #define SCAN_ARCHIVE	(options & CL_ARCHIVE)
51 51
 #define SCAN_MAIL	(options & CL_MAIL)
52
+#define DISABLE_RAR	(options & CL_DISABLERAR)
52 53
 
53 54
 #define MAGIC_BUFFER_SIZE 14
54 55
 #define RAR_MAGIC_STR "Rar!"
... ...
@@ -555,7 +556,7 @@ int cli_scanmail(int desc, char **virname, long int *scanned, const struct cl_no
555 555
 #endif
556 556
 
557 557
 	/* generate the temporary directory */
558
-	dir = cli_gentemp(tmpdir);
558
+	dir = cl_gentemp(tmpdir);
559 559
 	if(mkdir(dir, 0700)) {
560 560
 	    cli_errmsg("ScanMail -> Can't create temporary directory %s\n", dir);
561 561
 /*
... ...
@@ -619,22 +620,23 @@ int cli_magic_scandesc(int desc, char **virname, long int *scanned, const struct
619 619
 
620 620
 	if (bread != MAGIC_BUFFER_SIZE) {
621 621
 	    /* short read: No need to do magic */
622
+	    (*reclev)--;
622 623
 	    return ret;
623 624
 	}
624 625
 #ifdef CL_THREAD_SAFE
625 626
 	/* this check protects against recursive deadlock */
626
-	if(SCAN_ARCHIVE && !cli_scanrar_inuse && !strncmp(magic, RAR_MAGIC_STR, strlen(RAR_MAGIC_STR))) {
627
+	if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse && !strncmp(magic, RAR_MAGIC_STR, strlen(RAR_MAGIC_STR))) {
627 628
 	    ret = cli_scanrar(desc, virname, scanned, root, limits, options, reclev);
628 629
 	}
629 630
 #else
630
-	if(SCAN_ARCHIVE && !strncmp(magic, RAR_MAGIC_STR, strlen(RAR_MAGIC_STR))) {
631
+	if(!DISABLE_RAR && SCAN_ARCHIVE && !strncmp(magic, RAR_MAGIC_STR, strlen(RAR_MAGIC_STR))) {
631 632
 	    ret = cli_scanrar(desc, virname, scanned, root, limits, options, reclev);
632 633
 	}
633 634
 #endif
634 635
 #ifdef HAVE_ZLIB_H
635 636
 	else if(SCAN_ARCHIVE && !strncmp(magic, ZIP_MAGIC_STR, strlen(ZIP_MAGIC_STR))) {
636 637
 	    ret = cli_scanzip(desc, virname, scanned, root, limits, options, reclev);
637
-	} else if(!strncmp(magic, GZIP_MAGIC_STR, strlen(GZIP_MAGIC_STR))) {
638
+	} else if(SCAN_ARCHIVE && !strncmp(magic, GZIP_MAGIC_STR, strlen(GZIP_MAGIC_STR))) {
638 639
 	    ret = cli_scangzip(desc, virname, scanned, root, limits, options, reclev);
639 640
 	}
640 641
 #endif
... ...
@@ -648,10 +650,10 @@ int cli_magic_scandesc(int desc, char **virname, long int *scanned, const struct
648 648
 	}
649 649
 	else if(SCAN_MAIL && !strncmp(magic, RAWMAIL_MAGIC_STR, strlen(RAWMAIL_MAGIC_STR))) {
650 650
 	    ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev);
651
-	} else if(!strncmp(magic, MAILDIR_MAGIC_STR, strlen(MAILDIR_MAGIC_STR))) {
651
+	} else if(SCAN_MAIL && !strncmp(magic, MAILDIR_MAGIC_STR, strlen(MAILDIR_MAGIC_STR))) {
652 652
 	    cli_dbgmsg("Recognized Maildir mail file.\n");
653 653
 	    ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev);
654
-	} else if(!strncmp(magic, DELIVERED_MAGIC_STR, strlen(DELIVERED_MAGIC_STR))) {
654
+	} else if(SCAN_MAIL && !strncmp(magic, DELIVERED_MAGIC_STR, strlen(DELIVERED_MAGIC_STR))) {
655 655
 	    cli_dbgmsg("Recognized (Delivered-To) mail file.\n");
656 656
 	    ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev);
657 657
 	}
... ...
@@ -2,7 +2,7 @@
2 2
  * Author: 
3 3
  *      Guido Draheim <guidod@gmx.de>
4 4
  *
5
- *      Copyright (c) 2001 Guido Draheim
5
+ *      Copyright (c) 2001,2002,2003 Guido Draheim
6 6
  *          All rights reserved,
7 7
  *          use under the restrictions of the
8 8
  *          Lesser GNU General Public License
... ...
@@ -53,15 +53,34 @@
53 53
 #define _zzip_inline inline
54 54
 #endif
55 55
 #endif
56
+#ifndef _zzip_size_t
57
+#ifdef   ZZIP_size_t
58
+#define _zzip_size_t ZZIP_size_t
59
+#else
60
+#define _zzip_size_t size_t
61
+#endif
62
+#endif
63
+#ifndef _zzip_ssize_t
64
+#ifdef   ZZIP_ssize_t
65
+#define _zzip_ssize_t ZZIP_ssize_t
66
+#else
67
+#define _zzip_ssize_t ssize_t
68
+#endif
69
+#endif
56 70
 
57 71
 /* whether this library shall use a 64bit off_t largefile variant in 64on32: */
58 72
 /* (some exported names must be renamed to avoid bad calls after linking) */
59
-#if defined ZZIP_LARGEFILE_SENSITIVE && _FILE_OFFSET_BITS+0 == 64
60
-#define  ZZIP_LARGEFILE_RENAME
61
-#elif defined  _LARGE_FILES /* on AIX */
62
-#define  ZZIP_LARGEFILE_RENAME
73
+#if defined ZZIP_LARGEFILE_SENSITIVE 
74
+# if _FILE_OFFSET_BITS+0 == 64
75
+# define  ZZIP_LARGEFILE_RENAME
76
+# elif defined  _LARGE_FILES    /* used on older AIX to get at 64bit off_t */
77
+# define  ZZIP_LARGEFILE_RENAME
78
+# elif defined  _ZZIP_LARGEFILE /* or simply use this one for zzip64 runs */
79
+# define  ZZIP_LARGEFILE_RENAME
80
+# endif
63 81
 #endif
64
-/* if some were forgotten but required to have 64bit off_t largefile.. */
82
+
83
+/* if the environment did not setup these for 64bit off_t largefile... */
65 84
 #ifdef   ZZIP_LARGEFILE_RENAME
66 85
 # ifndef      _FILE_OFFSET_BITS
67 86
 #  ifdef ZZIP__FILE_OFFSET_BITS /* == 64 */
... ...
@@ -70,7 +89,12 @@
70 70
 # endif
71 71
 # ifndef      _LARGE_FILES
72 72
 #  ifdef ZZIP__LARGE_FILES /* == 1 */
73
-#  define     _LARGE_FILES 1
73
+#  define     _LARGE_FILES ZZIP__LARGE_FILES
74
+#  endif
75
+# endif
76
+# ifndef      _LARGEFILE_SOURCE
77
+#  ifdef ZZIP__LARGEFILE_SOURCE /* == 1 */
78
+#  define     _LARGEFILE_SOURCE ZZIP__LARGEFILE_SOURCE
74 79
 #  endif
75 80
 # endif
76 81
 #endif
... ...
@@ -141,6 +165,11 @@
141 141
 #define __attribute__(X) 
142 142
 #endif
143 143
 
144
+#if defined ZZIP_EXPORTS || defined ZZIPLIB_EXPORTS
145
+# undef ZZIP_DLL
146
+#define ZZIP_DLL 1
147
+#endif
148
+
144 149
 /* based on zconf.h : */
145 150
 /* compile with -DZZIP_DLL for Windows DLL support */
146 151
 #if defined ZZIP_DLL
... ...
@@ -1,4 +1,3 @@
1
-#define USE_DIRENT 0
2 1
 /*
3 2
  * Author: 
4 3
  *	Guido Draheim <guidod@gmx.de>
... ...
@@ -24,6 +23,8 @@
24 24
 #include <stdio.h>
25 25
 #endif
26 26
 
27
+//#include "__dirent.h"
28
+
27 29
 #ifndef offsetof
28 30
 #pragma warning had to DEFINE offsetof as it was not in stddef.h
29 31
 #define offsetof(T,M) ((unsigned)(& ((T*)0)->M))
... ...
@@ -50,11 +51,13 @@ zzip_rewinddir(ZZIP_DIR * dir)
50 50
 {
51 51
     if (! dir) return;
52 52
 
53
+    /*
53 54
     if (USE_DIRENT && dir->realdir) 
54 55
     {
55 56
         _zzip_rewinddir(dir->realdir);
56 57
         return;
57 58
     }
59
+    */
58 60
 
59 61
     if (dir->hdr0)
60 62
         dir->hdr = dir->hdr0;
... ...
@@ -118,11 +121,12 @@ zzip_readdir(ZZIP_DIR * dir)
118 118
 {
119 119
     if (! dir) { errno=EBADF; return 0; }
120 120
 
121
+    /*
121 122
     if (USE_DIRENT && dir->realdir)
122 123
     {
123 124
         if (! real_readdir(dir))
124 125
             return 0;
125
-    }else
126
+    }else */
126 127
     {
127 128
         if (! dir->hdr) return 0;
128 129
 
... ...
@@ -147,10 +151,10 @@ zzip_telldir(ZZIP_DIR* dir)
147 147
 {
148 148
     if (! dir) { errno=EBADF; return -1; }
149 149
 
150
-    if (USE_DIRENT && dir->realdir)
150
+    /* if (USE_DIRENT && dir->realdir)
151 151
     {
152 152
         return _zzip_telldir(dir->realdir);
153
-    }else
153
+    }else*/
154 154
     {
155 155
     	return ((zzip_off_t) ((char*) dir->hdr - (char*) dir->hdr0));
156 156
     }
... ...
@@ -164,10 +168,10 @@ zzip_seekdir(ZZIP_DIR* dir, zzip_off_t offset)
164 164
 {
165 165
     if (! dir) return; 
166 166
     
167
-    if (USE_DIRENT && dir->realdir)
167
+    /*if (USE_DIRENT && dir->realdir)
168 168
     {
169 169
         _zzip_seekdir(dir->realdir, offset);
170
-    }else
170
+    }else*/
171 171
     {
172 172
 	dir->hdr = (struct zzip_dir_hdr*) 
173 173
 	    (dir->hdr0 ? (char*) dir->hdr0 + (size_t) offset : 0);
... ...
@@ -229,6 +233,23 @@ zzip_opendir_ext_io(zzip_char_t* filename, int o_modes,
229 229
 #  ifdef ZZIP_HAVE_SYS_STAT_H
230 230
     if (stat(filename, &st) >= 0 && S_ISDIR(st.st_mode)
231 231
     ){
232
+      	/* if (USE_DIRENT)
233
+	{
234
+	    _zzip_DIR* realdir = _zzip_opendir(filename);
235
+	    if (realdir)
236
+	    {
237
+		if (! (dir = (ZZIP_DIR *)calloc(1, sizeof (*dir))))
238
+		{ 
239
+		    _zzip_closedir(realdir); 
240
+		    return 0; 
241
+		}else
242
+		{ 
243
+		    dir->realdir = realdir; 
244
+		    dir->realname = strdup(filename);
245
+		    return dir; 
246
+		}
247
+	    }
248
+        } */
232 249
         return 0;
233 250
     }
234 251
 #  endif /* HAVE_SYS_STAT_H */
... ...
@@ -253,13 +274,13 @@ zzip_closedir(ZZIP_DIR* dir)
253 253
 {
254 254
     if (! dir) { errno = EBADF; return -1; }
255 255
 
256
-    if (USE_DIRENT && dir->realdir)
256
+    /*if (USE_DIRENT && dir->realdir)
257 257
     {
258 258
         _zzip_closedir(dir->realdir);
259 259
         free(dir->realname);
260 260
         free(dir);
261 261
         return 0;
262
-    }else
262
+    }else*/
263 263
     {
264 264
         zzip_dir_close(dir);
265 265
         return 0;
... ...
@@ -81,6 +81,7 @@ zzip_strerror(int errcode)
81 81
 zzip_char_t* 
82 82
 zzip_strerror_of(ZZIP_DIR* dir)
83 83
 {
84
+    if (! dir) return strerror (errno);
84 85
     return zzip_strerror(dir->errcode);
85 86
 }
86 87
 
... ...
@@ -16,14 +16,15 @@
16 16
 
17 17
 #include "strc.h"
18 18
 
19
-#include <string.h>
20 19
 #include <sys/types.h>  /* njh@bandsman.co.uk: for icc7.0 */
20
+#include <string.h>
21 21
 #include <sys/stat.h>
22 22
 #include <errno.h>
23 23
 #include <stdlib.h>
24 24
 #include <ctype.h>
25 25
 
26 26
 #include <zzipformat.h>
27
+//#include "__debug.h"
27 28
 
28 29
 #if 0
29 30
 # if defined ZZIP_HAVE_IO_H
... ...
@@ -88,17 +89,14 @@ zzip_file_saveoffset(ZZIP_FILE * fp)
88 88
     return 0;
89 89
 }
90 90
 
91
-
92
-
93
-# ifndef ZZIP_CHECK_BACKSLASH_DIRSEPARATOR
94
-# define ZZIP_CHECK_BACKSLASH_DIRSEPARATOR 0
91
+# ifndef ZZIP_CHECK_BACKSLASH_DIRSEPARATOR           /* NOTE: also default */
92
+# define ZZIP_CHECK_BACKSLASH_DIRSEPARATOR 0         /* to "NO" on win32 ! */
95 93
 # endif
96 94
 
97 95
 # if !defined strcasecmp && !defined ZZIP_HAVE_STRCASECMP
98 96
 # define ZZIP_CHECK_BACKSLASH_DIRSEPARATOR 1
99 97
 # endif
100 98
 
101
-
102 99
 #if ! ZZIP_CHECK_BACKSLASH_DIRSEPARATOR+0
103 100
 #define dirsep_strrchr(N,C) strrchr(N,C)
104 101
 #define dirsep_casecmp strcasecmp
... ...
@@ -172,6 +170,9 @@ zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode)
172 172
             if (n)  hdr_name = n + 1;
173 173
         }
174 174
 
175
+        //HINT4("name='%s', compr=%d, size=%d\n", 
176
+	  //    hdr->d_name, hdr->d_compr, hdr->d_usize);
177
+
175 178
         if (!cmp(hdr_name, name))
176 179
         {
177 180
             switch (hdr->d_compr)
... ...
@@ -222,11 +223,11 @@ zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode)
222 222
 
223 223
             {   /* skip local header - should test tons of other info, 
224 224
 		 * but trust that those are correct */
225
-                int dataoff;
225
+                zzip_ssize_t dataoff;
226 226
                 struct zzip_file_header * p = (void*) fp->buf32k;
227 227
 
228 228
 		dataoff = dir->io->read(dir->fd, (void*)p, sizeof(*p));
229
-		if (dataoff < (int) sizeof(*p))
229
+		if (dataoff < (zzip_ssize_t)sizeof(*p))
230 230
 		{ err = ZZIP_DIR_READ;  goto error; }
231 231
                 if (! ZZIP_FILE_HEADER_CHECKMAGIC(p)) /* PK\3\4 */
232 232
 		{ err = ZZIP_CORRUPTED; goto error; }
... ...
@@ -323,12 +324,12 @@ zzip_close(ZZIP_FILE* fp)
323 323
  *       required just that but the latest zlib would work just fine with
324 324
  *       a smaller buffer.
325 325
  */
326
-int 
327
-zzip_file_read(ZZIP_FILE * fp, char * buf, int len)
326
+zzip_ssize_t 
327
+zzip_file_read(ZZIP_FILE * fp, char * buf, zzip_size_t len)
328 328
 {
329 329
     ZZIP_DIR * dir; 
330
-    int l;
331
-    int rv;
330
+    zzip_size_t l;
331
+    zzip_ssize_t rv;
332 332
     
333 333
     if (! fp || ! fp->dir) return 0;
334 334
 
... ...
@@ -358,14 +359,15 @@ zzip_file_read(ZZIP_FILE * fp, char * buf, int len)
358 358
 
359 359
          do {
360 360
              int err;
361
-             int startlen;
361
+             zzip_size_t startlen;
362 362
 
363 363
              if (fp->crestlen > 0 && fp->d_stream.avail_in == 0)
364 364
              {
365
-                 int cl = fp->crestlen > ZZIP_32K ? ZZIP_32K : fp->crestlen;
366
-             /*  int cl = fp->crestlen > 128? 128: fp->crestlen; */
365
+                 zzip_size_t cl = ( fp->crestlen < ZZIP_32K ?
366
+				    fp->crestlen : ZZIP_32K );
367
+             /*  zzip_size_t cl = fp->crestlen > 128 ? 128 : fp->crestlen; */
367 368
 
368
-                 int i = fp->io->read(dir->fd, fp->buf32k, cl);
369
+                 zzip_ssize_t i = fp->io->read(dir->fd, fp->buf32k, cl);
369 370
                  if (i <= 0)
370 371
                  {
371 372
                      dir->errcode = ZZIP_DIR_READ; /* or ZZIP_DIR_READ_EOF ? */
... ...
@@ -412,14 +414,14 @@ zzip_file_read(ZZIP_FILE * fp, char * buf, int len)
412 412
  * perform a normal => read(2)-call, otherwise => zzip_file_read is called
413 413
  * to decompress the data stream and any error is mapped to => errno(3).
414 414
  */
415
-int 
416
-zzip_read(ZZIP_FILE * fp, char * buf, int len)
415
+zzip_ssize_t
416
+zzip_read(ZZIP_FILE * fp, char * buf, zzip_size_t len)
417 417
 {
418 418
     if (! fp) return 0;
419 419
     if (! fp->dir) 
420 420
       { return fp->io->read(fp->fd, buf, len); } /* stat fd */
421 421
     else
422
-    {   register int v;
422
+    {   register zzip_ssize_t v;
423 423
         v = zzip_file_read(fp, buf, len);
424 424
         if (v == -1) { errno = zzip_errno(fp->dir->errcode); }
425 425
         return v;
... ...
@@ -428,8 +430,8 @@ zzip_read(ZZIP_FILE * fp, char * buf, int len)
428 428
 
429 429
 /** => zzip_read
430 430
  */
431
-int 
432
-zzip_fread(void *ptr, int size, int nmemb, ZZIP_FILE *file)
431
+zzip_size_t
432
+zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb, ZZIP_FILE *file)
433 433
 {
434 434
     if (! size) size=1;
435 435
     return zzip_read (file, ptr, size*nmemb)/size;
... ...
@@ -714,7 +716,7 @@ zzip_open_shared_io (ZZIP_FILE* stream,
714 714
       /* see if we can share the same zip directory */
715 715
       if (stream && stream->dir && stream->dir->realname)
716 716
       {
717
-	  int len = strlen (stream->dir->realname);
717
+	  zzip_size_t len = strlen (stream->dir->realname);
718 718
 	  if (! memcmp (filename, stream->dir->realname, len) &&
719 719
 	      filename[len] == '/' && filename[len+1])
720 720
 	  {
... ...
@@ -864,10 +866,10 @@ zzip_rewind(ZZIP_FILE *fp)
864 864
  * how gzio implements it, so I'm not sure there is a better way
865 865
  * without using the internals of the algorithm.
866 866
  */
867
-int
868
-zzip_seek(ZZIP_FILE * fp, int offset, int whence)
867
+zzip_off_t
868
+zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence)
869 869
 {
870
-    int cur_pos, rel_ofs, read_size, ofs;
870
+    zzip_off_t cur_pos, rel_ofs, read_size, ofs;
871 871
     ZZIP_DIR *dir;
872 872
   
873 873
     if (! fp)
... ...
@@ -875,7 +877,7 @@ zzip_seek(ZZIP_FILE * fp, int offset, int whence)
875 875
 
876 876
     if (! fp->dir) 
877 877
     { /* stat fd */
878
-        return fp->io->seeks(fp->fd,offset,whence);
878
+        return fp->io->seeks(fp->fd, offset, whence);
879 879
     }
880 880
 
881 881
     cur_pos = zzip_tell(fp);
... ...
@@ -914,7 +916,7 @@ zzip_seek(ZZIP_FILE * fp, int offset, int whence)
914 914
     if (read_size < 0) /* bad offset, before beginning of file */
915 915
         return -1;
916 916
 
917
-    if (read_size + cur_pos > fp->usize) /* bad offset, past EOF */
917
+    if (read_size + cur_pos > (zzip_off_t)fp->usize) /* bad offset, past EOF */
918 918
         return -1;
919 919
 
920 920
     if (read_size == 0) /* nothing to read */
... ...
@@ -953,10 +955,10 @@ zzip_seek(ZZIP_FILE * fp, int offset, int whence)
953 953
         
954 954
         while (read_size > 0)  
955 955
         {
956
-            int size = ZZIP_32K;
957
-            if (read_size < ZZIP_32K) size = (int)read_size;
956
+            zzip_off_t size = ZZIP_32K;
957
+            if (read_size < size/*32K*/) size = read_size;
958 958
 
959
-            size = zzip_file_read(fp, buf, size);
959
+            size = zzip_file_read(fp, buf, (zzip_size_t)size);
960 960
             if (size <= 0) { free(buf); return -1; }
961 961
       
962 962
             read_size -= size;
... ...
@@ -979,7 +981,7 @@ zzip_seek(ZZIP_FILE * fp, int offset, int whence)
979 979
  * calculated from the amount of data left and the total uncompressed
980 980
  * size;
981 981
  */
982
-int
982
+zzip_off_t
983 983
 zzip_tell(ZZIP_FILE * fp)
984 984
 {
985 985
     if (! fp)
... ...
@@ -65,10 +65,10 @@ struct zzip_file
65 65
   struct zzip_dir* dir; 
66 66
   int fd;
67 67
   int method;
68
-  int restlen;
69
-  int crestlen;
70
-  int usize;
71
-  int csize;
68
+  zzip_size_t restlen;
69
+  zzip_size_t crestlen;
70
+  zzip_size_t usize;
71
+  zzip_size_t csize;
72 72
   /* added dataoffset member - data offset from start of zipfile*/
73 73
   zzip_off_t dataoffset;
74 74
   char* buf32k;
... ...
@@ -27,6 +27,11 @@
27 27
 //#include "__mmap.h"
28 28
 //#include "__debug.h"
29 29
 
30
+#define __sizeof(X) ((zzip_ssize_t)(sizeof(X)))
31
+
32
+/* per default, we use a little hack to correct bad z_rootseek parts */
33
+#define ZZIP_CORRECT_ROOTSEEK 1
34
+
30 35
 /* ------------------------- fetch helpers --------------------------------- */
31 36
 
32 37
 /**
... ...
@@ -39,7 +44,7 @@ uint32_t __zzip_get32(unsigned char * s)
39 39
     |    ((uint32_t)s[1] << 8)  |  (uint32_t)s[0];
40 40
 }
41 41
 
42
-/** => __zzip_get16
42
+/** => __zzip_get32
43 43
  * This function does the same for a 16 bit value.
44 44
  */
45 45
 uint16_t __zzip_get16(unsigned char * s)
... ...
@@ -47,6 +52,88 @@ uint16_t __zzip_get16(unsigned char * s)
47 47
     return ((uint16_t)s[1] << 8) | (uint16_t)s[0];
48 48
 }
49 49
 
50
+/* ---------------------------  internals  -------------------------------- */
51
+/* internal functions of zziplib, avoid at all cost, changes w/o warning.
52
+ * we do export them for debugging purpose and special external tools
53
+ * which know what they do and which can adapt from version to version
54
+ */
55
+
56
+int __zzip_find_disk_trailer( int fd, zzip_off_t filesize, 
57
+			      struct zzip_disk_trailer * trailer,
58
+			      zzip_plugin_io_t io);
59
+int __zzip_parse_root_directory( int fd, 
60
+				 struct zzip_disk_trailer * trailer, 
61
+				 struct zzip_dir_hdr ** hdr_return,
62
+				 zzip_plugin_io_t io);
63
+
64
+_zzip_inline char* __zzip_aligned4(char* p);
65
+
66
+/* ------------------------  harden routines ------------------------------ */
67
+
68
+#ifdef ZZIP_HARDEN
69
+/*
70
+ * check for inconsistent values in trailer and prefer lower seek value
71
+ * - we fix values assuming the root directory was written at the end
72
+ * and it is just before the zip trailer. Therefore, ...
73
+ */
74
+_zzip_inline static void __fixup_rootseek(
75
+    zzip_off_t offset_of_trailer,
76
+    struct zzip_disk_trailer* trailer)
77
+{
78
+    if (                    (zzip_off_t) ZZIP_GET32(trailer->z_rootseek) >
79
+	offset_of_trailer - (zzip_off_t) ZZIP_GET32(trailer->z_rootsize) &&
80
+	offset_of_trailer > (zzip_off_t) ZZIP_GET32(trailer->z_rootsize))
81
+    {
82
+	register zzip_off_t offset;
83
+	offset = offset_of_trailer -  ZZIP_GET32(trailer->z_rootsize); 
84
+	trailer->z_rootseek[0] = offset & 0xff;
85
+	trailer->z_rootseek[1] = offset >> 8 & 0xff;
86
+	trailer->z_rootseek[2] = offset >> 16 & 0xff;
87
+	trailer->z_rootseek[3] = offset >> 24 & 0xff;
88
+	//HINT2("new rootseek=%li", 
89
+	 //     (long) ZZIP_GET32(trailer->z_rootseek));
90
+    }
91
+}
92
+#define __correct_rootseek(A,B,C)
93
+
94
+#elif defined ZZIP_CORRECT_ROOTSEEK
95
+/* store the seekvalue of the trailer into the "z_magic" field and with 
96
+ * a 64bit off_t we overwrite z_disk/z_finaldisk as well. If you change
97
+ * anything in zziplib or dump the trailer structure then watch out that
98
+ * these are still unused, so that this code may still (ab)use those. */
99
+#define __fixup_rootseek(_offset_of_trailer, _trailer)          \
100
+                      *(zzip_off_t*)_trailer = _offset_of_trailer;
101
+#define __correct_rootseek( _u_rootseek, _u_rootsize, _trailer) \
102
+    if (_u_rootseek > *(zzip_off_t*)_trailer - _u_rootsize)     \
103
+	_u_rootseek = *(zzip_off_t*)_trailer - _u_rootsize;
104
+#else
105
+#define __fixup_rootseek(A,B) 
106
+#define __correct_rootseek(A,B,C)
107
+#endif
108
+
109
+
110
+#ifdef DEBUG
111
+_zzip_inline static void __debug_dir_hdr (struct zzip_dir_hdr* hdr)
112
+{
113
+    if (sizeof(struct zzip_dir_hdr) > sizeof(struct zzip_root_dirent))
114
+    { WARN1("internal sizeof-mismatch may break wreakage"); }
115
+    /*  the internal directory structure is never bigger than the
116
+     *  external zip central directory space had been beforehand
117
+     *  (as long as the following assertion holds...) 
118
+     */
119
+
120
+    //if (((unsigned)hdr)&3)
121
+    //{ NOTE1("this machine's malloc(3) returns sth. not u32-aligned"); }
122
+    /* we assume that if this machine's malloc has returned a non-aligned 
123
+     * memory block, then it is actually safe to access misaligned data, and 
124
+     * since it does only affect the first hdr it should not even bring about
125
+     * too much of that cpu's speed penalty
126
+     */
127
+}
128
+#else
129
+#define __debug_dir_hdr(X)
130
+#endif
131
+
50 132
 /* -------------------------- low-level interface -------------------------- */
51 133
 
52 134
 #if defined BUFSIZ 
... ...
@@ -70,11 +157,13 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
70 70
 			 struct zzip_disk_trailer * trailer,
71 71
 			 zzip_plugin_io_t io)
72 72
 {
73
+/*
73 74
 #ifdef DEBUG
74
-#define return(val) { e=val; goto cleanup; }
75
+#define return(val) { e=val; HINT2("%s", zzip_strerror(e)); goto cleanup; }
75 76
 #else
77
+*/
76 78
 #define return(val) { e=val; goto cleanup; }
77
-#endif
79
+//#endif
78 80
     register int e;
79 81
     
80 82
 #ifndef _LOWSTK
... ...
@@ -84,13 +173,13 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
84 84
     char* buf = malloc(2*ZZIP_BUFSIZ);
85 85
 #endif
86 86
     zzip_off_t offset = 0;
87
-    size_t maplen = 0;
87
+    zzip_off_t maplen = 0; /* mmap(),read(),getpagesize() use size_t !! */
88 88
     char* fd_map = 0;
89 89
 
90 90
     if (!trailer)
91 91
         { return(EINVAL); }
92 92
   
93
-    if (filesize < sizeof(struct zzip_disk_trailer))
93
+    if (filesize < __sizeof(struct zzip_disk_trailer))
94 94
         { return(ZZIP_DIR_TOO_SHORT); }
95 95
           
96 96
     if (!buf)
... ...
@@ -99,8 +188,7 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
99 99
     offset = filesize; /* a.k.a. old offset */
100 100
     while(1) /* outer loop */
101 101
     {
102
-        register unsigned char* p;
103
-        register unsigned char* s;
102
+        register unsigned char* mapped;
104 103
 
105 104
          if (offset <= 0) { return(ZZIP_DIR_EDH_MISSING); }
106 105
 
... ...
@@ -108,6 +196,34 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
108 108
          if (filesize-offset > 64*1024) 
109 109
              { return(ZZIP_DIR_EDH_MISSING); }
110 110
 
111
+	/* the new offset shall overlap with the area after the old offset! */
112
+        /*if (USE_MMAP && io->use_mmap)
113
+        {
114
+	    zzip_off_t mapoff = offset;
115
+	    { 
116
+		zzip_off_t pagesize = _zzip_getpagesize (io->use_mmap);
117
+		if (pagesize < ZZIP_BUFSIZ) goto non_mmap;
118
+		if (mapoff == filesize && filesize > pagesize) 
119
+		    mapoff -= pagesize;
120
+		if (mapoff < pagesize) {
121
+		    maplen = mapoff + pagesize; mapoff = 0;
122
+		} else {               
123
+		    mapoff -= pagesize; maplen = 2*pagesize; 
124
+		    if (mapoff & (pagesize-1)) {
125
+			pagesize -= mapoff & (pagesize-1);
126
+			mapoff += pagesize;
127
+			maplen -= pagesize;
128
+		    }   
129
+		}
130
+		if (mapoff + maplen > filesize) maplen = filesize - mapoff;
131
+	    }
132
+
133
+            fd_map = _zzip_mmap(io->use_mmap, fd, mapoff, (zzip_size_t)maplen);
134
+            if (fd_map == MAP_FAILED) goto non_mmap;
135
+	    mapped = fd_map; offset = mapoff;
136
+	    HINT3("mapped *%p len=%li", fd_map, (long) maplen);
137
+        } else */ {
138
+        non_mmap:
111 139
 	    fd_map = 0; /* have no mmap */
112 140
 	    {
113 141
 		zzip_off_t pagesize = ZZIP_BUFSIZ;
... ...
@@ -128,35 +244,52 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
128 128
 	    
129 129
             if (io->seeks(fd, offset, SEEK_SET) < 0)
130 130
                 { return(ZZIP_DIR_SEEK); }
131
-            if (io->read(fd, buf, maplen) < (long)maplen)
131
+            if (io->read(fd, buf, (zzip_size_t)maplen) < (zzip_ssize_t)maplen)
132 132
                 { return(ZZIP_DIR_READ); }
133
-            p = buf; /* success */
134
-
133
+            mapped = buf; /* success */
134
+	    //HINT5("offs=$%lx len=%li filesize=%li pagesize=%i", 
135
+		//(long)offset, (long)maplen, (long)filesize, ZZIP_BUFSIZ);
136
+        }
135 137
 
136
-	/* now, check for the trailer-magic, hopefully near the end of file */
137
-        for (s = p + maplen-1; (s >= p); s--)
138
-        {
139
-            if (*s == 'P'
140
-             && p+maplen-1-s > sizeof(*trailer)-2
141
-             && ZZIP_DISK_TRAILER_CHECKMAGIC(s))
142
-            {
143
-                /* if the file-comment is not present, it happens
144
-                   that the z_comment field often isn't either */
145
-                if (p+maplen-1-s > sizeof(*trailer))
146
-                  { memcpy (trailer, s, sizeof(*trailer)); }
147
-                else
148
-                {
149
-                    memcpy (trailer, s, sizeof(*trailer)-2);
150
-                    trailer->z_comment[0] = 0; trailer->z_comment[1] = 0;
151
-                }
152
-                    
153
-                { return(0); }
154
-            }
138
+	{/* now, check for the trailer-magic, hopefully near the end of file */
139
+	    register unsigned char* end = mapped + maplen;
140
+	    register unsigned char* tail;
141
+	    for (tail = end-1; (tail >= mapped); tail--)
142
+	    {
143
+		if ((*tail == 'P') && /* quick pre-check for trailer magic */
144
+		    end-tail >= __sizeof(*trailer)-2 &&
145
+		    ZZIP_DISK_TRAILER_CHECKMAGIC(tail))
146
+		{
147
+		    /* if the file-comment is not present, it happens
148
+		       that the z_comment field often isn't either */
149
+		    if (end-tail >= __sizeof(*trailer))
150
+		    {
151
+			memcpy (trailer, tail, sizeof(*trailer)); 
152
+		    }else{
153
+			memcpy (trailer, tail, sizeof(*trailer)-2);
154
+			trailer->z_comment[0] = 0; 
155
+			trailer->z_comment[1] = 0;
156
+		    }
157
+
158
+		    __fixup_rootseek (offset + tail-mapped, trailer);
159
+		    { return(0); }
160
+		}
161
+	    }
155 162
         }
156 163
         
164
+         /*if (USE_MMAP && fd_map) 
165
+	 { 
166
+	     HINT3("unmap *%p len=%li",  fd_map, (long) maplen);
167
+	     _zzip_munmap(io->use_mmap, fd_map, (zzip_size_t)maplen); fd_map = 0; 
168
+	 }*/
157 169
     } /*outer loop*/
158 170
                
159 171
  cleanup:
172
+    /*if (USE_MMAP && fd_map)
173
+    { 
174
+	HINT3("unmap *%p len=%li",  fd_map, (long) maplen);
175
+	_zzip_munmap(io->use_mmap, fd_map, (zzip_size_t)maplen); 
176
+    }*/
160 177
 #   ifdef _LOWSTK
161 178
     free(buf);
162 179
 #   endif
... ...
@@ -174,8 +307,8 @@ __zzip_find_disk_trailer(int fd, zzip_off_t filesize,
174 174
 _zzip_inline char* __zzip_aligned4(char* p)
175 175
 {
176 176
 #define aligned4   __zzip_aligned4
177
-    p += ((long)p)&1;
178
-    p += ((long)p)&2;
177
+    p += ((long)p)&1;            /* warnings about truncation of a "pointer" */
178
+    p += ((long)p)&2;            /* to a "long int" may be safely ignored :) */
179 179
     return p;
180 180
 }
181 181
 
... ...
@@ -196,34 +329,33 @@ __zzip_parse_root_directory(int fd,
196 196
     struct zzip_dir_hdr * hdr0;
197 197
     uint16_t * p_reclen = 0;
198 198
     short entries; 
199
-    long offset;
200
-    char* fd_map = 0;
199
+    long offset;          /* offset from start of root directory */
200
+    char* fd_map = 0; 
201 201
     int32_t  fd_gap = 0;
202 202
     uint16_t u_entries  = ZZIP_GET16(trailer->z_entries);   
203 203
     uint32_t u_rootsize = ZZIP_GET32(trailer->z_rootsize);  
204 204
     uint32_t u_rootseek = ZZIP_GET32(trailer->z_rootseek);
205
+    __correct_rootseek (u_rootseek, u_rootsize, trailer);
205 206
 
206 207
     hdr0 = (struct zzip_dir_hdr*) malloc(u_rootsize);
207 208
     if (!hdr0) 
208 209
         return ZZIP_DIRSIZE;
209
-    hdr = hdr0;
210
+    hdr = hdr0;                  __debug_dir_hdr (hdr);
210 211
 
211
-#  ifdef DEBUG
212
-    if (sizeof(struct zzip_dir_hdr) > sizeof(struct zzip_root_dirent))
213
-    { WARN1("internal sizeof-mismatch may break wreakage"); }
214
-    /*  the internal directory structure is never bigger than the
215
-     *  external zip central directory space had been beforehand
216
-     *  (as long as the following assertion holds...) 
217
-     */
218
-
219
-    if (((unsigned)hdr0)&3)
220
-    { NOTE1("this machine's malloc(3) returns sth. not u32-aligned"); }
221
-    /* we assume that if this machine's malloc has returned a non-aligned 
222
-     * memory block, then it is actually safe to access misaligned data, and 
223
-     * since it does only affect the first hdr it should not even bring about
224
-     * too much of that cpu's speed penalty
225
-     */
226
-#  endif
212
+    /*if (USE_MMAP && io->use_mmap)
213
+    {
214
+        fd_gap = u_rootseek & (_zzip_getpagesize(io->use_mmap)-1) ;
215
+        HINT4(" mapseek=0x%x, maplen=%d, fd_gap=%d", 
216
+	      u_rootseek-fd_gap, u_rootsize+fd_gap, fd_gap);
217
+        fd_map = _zzip_mmap(io->use_mmap, 
218
+			    fd, u_rootseek-fd_gap, u_rootsize+fd_gap);
219
+        if (fd_map == MAP_FAILED) { 
220
+            NOTE2("map failed: %s",strerror(errno)); 
221
+            fd_map=0; 
222
+	}else{
223
+	    HINT3("mapped *%p len=%i", fd_map, u_rootsize+fd_gap);
224
+	}
225
+    }*/
227 226
 
228 227
     for (entries=u_entries, offset=0; entries > 0; entries--)
229 228
     {
... ...
@@ -236,11 +368,14 @@ __zzip_parse_root_directory(int fd,
236 236
         {
237 237
             if (io->seeks(fd, u_rootseek+offset, SEEK_SET) < 0)
238 238
                 return ZZIP_DIR_SEEK;
239
-            if (io->read(fd, &dirent, sizeof(dirent)) < sizeof(dirent))
239
+            if (io->read(fd, &dirent, sizeof(dirent)) < __sizeof(dirent))
240 240
                 return ZZIP_DIR_READ;
241 241
             d = &dirent;
242 242
         }
243 243
 
244
+	if (offset+sizeof(*d) > u_rootsize)
245
+	{ /*FAIL2("%i's entry stretches beyond root directory", entries);*/ break;}
246
+
244 247
 #       if 0 && defined DEBUG
245 248
         zzip_debug_xbuf ((unsigned char*) d, sizeof(*d) + 8);
246 249
 #       endif        
... ...
@@ -248,8 +383,9 @@ __zzip_parse_root_directory(int fd,
248 248
         u_extras  = ZZIP_GET16(d->z_extras); 
249 249
         u_comment = ZZIP_GET16(d->z_comment); 
250 250
         u_namlen  = ZZIP_GET16(d->z_namlen); 
251
-    
252
-    
251
+        //HINT5("offset=0x%lx, size %ld, dirent *%p, hdr %p\n",
252
+	  //    offset+u_rootseek, (long)u_rootsize, d, hdr);
253
+
253 254
         /* writes over the read buffer, Since the structure where data is
254 255
            copied is smaller than the data in buffer this can be done.
255 256
            It is important that the order of setting the fields is considered
... ...
@@ -264,10 +400,12 @@ __zzip_parse_root_directory(int fd,
264 264
         hdr->d_compr = (uint8_t)ZZIP_GET16(d->z_compr);
265 265
         if (hdr->d_compr > 255) hdr->d_compr = 255;
266 266
 
267
-        if (fd_map) 
268
-          { memcpy(hdr->d_name, fd_map+fd_gap+offset+sizeof(*d), u_namlen); }
269
-        else 
270
-          { io->read(fd, hdr->d_name, u_namlen); }
267
+	if (offset+sizeof(*d) + u_namlen > u_rootsize)
268
+	{ /*FAIL2("%i's name stretches beyond root directory", entries);*/ break;}
269
+
270
+	if (fd_map) 
271
+	{  memcpy(hdr->d_name, fd_map+fd_gap+offset+sizeof(*d), u_namlen); }
272
+	else { io->read(fd, hdr->d_name, u_namlen); }
271 273
         hdr->d_name[u_namlen] = '\0'; 
272 274
         hdr->d_namlen = u_namlen;
273 275
     
... ...
@@ -275,26 +413,38 @@ __zzip_parse_root_directory(int fd,
275 275
         offset += sizeof(*d) + u_namlen + u_extras + u_comment;
276 276
     
277 277
         if (offset > (long)u_rootsize)
278
-            break;
279
-
278
+	{ /*FAIL2("%i's end beyond root directory", entries);*/ entries--; break;}
279
+
280
+        //HINT5("file %d { compr=%d crc32=$%x offset=%d", 
281
+	  //    entries,  hdr->d_compr, hdr->d_crc32, hdr->d_off);
282
+        //HINT5("csize=%d usize=%d namlen=%d extras=%d", 
283
+	  //    hdr->d_csize, hdr->d_usize, u_namlen, u_extras);
284
+        //HINT5("comment=%d name='%s' %s <sizeof %d> } ", 
285
+	   //   u_comment, hdr->d_name, "",(int) sizeof(*d));
286
+  
280 287
         p_reclen = &hdr->d_reclen;
281 288
     
282 289
         {   register char* p = (char*) hdr; 
283 290
             register char* q = aligned4 (p + sizeof(*hdr) + u_namlen + 1);
284
-            *p_reclen = q - p;
291
+            *p_reclen = (uint16_t)(q - p);
285 292
             hdr = (struct zzip_dir_hdr*) q;
286 293
         }
287 294
     }/*for*/
288 295
     
289
-    if (!p_reclen)
290
-        return 0; /* 0 (sane) entries in zip directory... */
291
-    
292
-    *p_reclen = 0; /* mark end of list */
296
+    /*if (USE_MMAP && fd_map) 
297
+    {
298
+	HINT3("unmap *%p len=%i",   fd_map, u_rootsize+fd_gap);
299
+        _zzip_munmap(io->use_mmap, fd_map, u_rootsize+fd_gap);
300
+    }*/
293 301
     
294
-    if (hdr_return) 
295
-        *hdr_return = hdr0;
302
+    if (p_reclen)
303
+    {
304
+	*p_reclen = 0; /* mark end of list */
296 305
     
297
-    return 0;
306
+	if (hdr_return) 
307
+	    *hdr_return = hdr0;
308
+    } /* else zero (sane) entries */
309
+    return (entries ?  ZZIP_CORRUPTED : 0);
298 310
 }
299 311
 
300 312
 /* ------------------------- high-level interface ------------------------- */
... ...
@@ -444,13 +594,18 @@ __zzip_dir_parse (ZZIP_DIR* dir)
444 444
      *     { rv = EINVAL; goto error; } 
445 445
      */
446 446
 
447
+    //HINT2("------------------ fd=%i", (int) dir->fd);
447 448
     if ((filesize = dir->io->filesize(dir->fd)) < 0)
448 449
         { rv = ZZIP_DIR_STAT; goto error; }
449 450
 
451
+    //HINT2("------------------ filesize=%ld", (long) filesize);
450 452
     if ((rv = __zzip_find_disk_trailer(dir->fd, filesize, &trailer, 
451 453
                                        dir->io)) != 0)
452 454
         { goto error; }
453 455
                 
456
+    //HINT5("directory = { entries= %d/%d, size= %d, seek= %d } ", 
457
+	//  ZZIP_GET16(trailer.z_entries),  ZZIP_GET16(trailer.z_finalentries),
458
+	//  ZZIP_GET32(trailer.z_rootsize), ZZIP_GET32(trailer.z_rootseek));
454 459
     
455 460
     if ( (rv = __zzip_parse_root_directory(dir->fd, &trailer, &dir->hdr0, 
456 461
                                            dir->io)) != 0)
... ...
@@ -470,7 +625,7 @@ __zzip_try_open(zzip_char_t* filename, int filemode,
470 470
 {
471 471
     auto char file[PATH_MAX];
472 472
     int fd;
473
-    int len = strlen (filename);
473
+    zzip_size_t len = strlen (filename);
474 474
     
475 475
     if (len+4 >= PATH_MAX) return -1;
476 476
     memcpy(file, filename, len+1);
... ...
@@ -75,6 +75,9 @@ ZZIP_DIR*
75 75
 zzip_dir_fdopen_ext_io(int fd, zzip_error_t * errorcode_p,
76 76
                        zzip_strings_t* ext, const zzip_plugin_io_t io);
77 77
 
78
+ZZIP_DIR* /*depracated*/
79
+zzip_dir_alloc_ext_io (zzip_strings_t* ext, const zzip_plugin_io_t io);
80
+
78 81
 /* get 16/32 bits from little-endian zip-file to host byteorder */
79 82
 uint32_t __zzip_get32(unsigned char * s);
80 83
 uint16_t __zzip_get16(unsigned char * s);
... ...
@@ -3,12 +3,17 @@
3 3
  *	Guido Draheim <guidod@gmx.de>
4 4
  *	Tomi Ollila <Tomi.Ollila@iki.fi>
5 5
  *
6
- *	Copyright (c) 1999,2000,2001,2002 Guido Draheim
6
+ *	Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
7 7
  * 	    All rights reserved, 
8 8
  *          usage allowed under the restrictions of the
9 9
  *	    Lesser GNU General Public License 
10 10
  *          note the additional license information 
11 11
  *          that can be found in COPYING.ZZIP
12
+ *
13
+ * if you see "unknown symbol" errors, check first that `-I ..` is part of
14
+ * your compiler options - a special hint to VC/IDE users who tend to make up
15
+ * their own workspace files. All includes look like #include <zzip|*.h>, so
16
+ * you need to add an include path to the dir containing (!!) the ./zzip/ dir
12 17
  */
13 18
 
14 19
 #ifndef _ZZIP_ZZIP_H /* zziplib.h */
... ...
@@ -17,6 +22,8 @@
17 17
 #include <zzip-conf.h>
18 18
 
19 19
 #include <fcntl.h>
20
+#include <stddef.h> /* size_t and friends */
21
+/* msvc6 has neither ssize_t (we assume "int") nor off_t (assume "long") */
20 22
 
21 23
 #ifdef __cplusplus
22 24
 extern "C" {
... ...
@@ -72,6 +79,8 @@ typedef enum
72 72
 typedef  char _zzip_const * _zzip_const zzip_strings_t;
73 73
 typedef  char _zzip_const       zzip_char_t;
74 74
 typedef       _zzip_off_t       zzip_off_t;
75
+typedef       _zzip_size_t      zzip_size_t;
76
+typedef       _zzip_ssize_t     zzip_ssize_t;
75 77
 typedef struct zzip_dir		ZZIP_DIR;
76 78
 typedef struct zzip_file	ZZIP_FILE;
77 79
 typedef struct zzip_dirent 	ZZIP_DIRENT;
... ...
@@ -87,7 +96,7 @@ struct zzip_dirent
87 87
 
88 88
 /*
89 89
  * Getting error strings 
90
- * zzip-err.c
90
+ * zzip/err.c
91 91
  */
92 92
 _zzip_export    /* error in _opendir : */
93 93
 zzip_char_t* 	zzip_strerror(int errcode); 
... ...
@@ -100,7 +109,7 @@ int    	 	zzip_errno(int errcode);
100 100
 /*
101 101
  * Functions to grab information from ZZIP_DIR/ZZIP_FILE structure 
102 102
  * (if ever needed)
103
- * zzip-info.c
103
+ * zzip/info.c
104 104
  */
105 105
 _zzip_export
106 106
 int  	 	zzip_error(ZZIP_DIR * dir);
... ...
@@ -124,7 +133,7 @@ int             zzip_realfd(ZZIP_FILE * fp);
124 124
 
125 125
 /*
126 126
  * zip handle management
127
- * zzip-zip.c
127
+ * zzip/zip.c
128 128
  */
129 129
 _zzip_export
130 130
 ZZIP_DIR *      zzip_dir_alloc(zzip_strings_t* fileext);
... ...
@@ -147,8 +156,8 @@ int             zzip_dir_read(ZZIP_DIR * dir, ZZIP_DIRENT * dirent);
147 147
 
148 148
 /*
149 149
  * Scanning files in zip archive
150
- * zzip-dir.c
151
- * zzip-zip.c
150
+ * zzip/dir.c
151
+ * zzip/zip.c
152 152
  */
153 153
 _zzip_export
154 154
 ZZIP_DIR * 	zzip_opendir(zzip_char_t* filename);
... ...
@@ -165,30 +174,33 @@ void	 	zzip_seekdir(ZZIP_DIR * dir, zzip_off_t offset);
165 165
 
166 166
 /*
167 167
  * 'opening', 'closing' and reading invidual files in zip archive.
168
- * zzip-file.c
168
+ * zzip/file.c
169 169
  */
170
-
171 170
 _zzip_export
172 171
 ZZIP_FILE * 	zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int modes);
173 172
 _zzip_export
174 173
 int  		zzip_file_close(ZZIP_FILE * fp);
175 174
 _zzip_export
176
-int		zzip_file_read(ZZIP_FILE * fp, char* buf, int len);
175
+zzip_ssize_t	zzip_file_read(ZZIP_FILE * fp, char* buf, zzip_size_t len);
177 176
 
178 177
 _zzip_export
179 178
 ZZIP_FILE * 	zzip_open(zzip_char_t* name, int flags);
180 179
 _zzip_export
181 180
 int	 	zzip_close(ZZIP_FILE * fp);
182 181
 _zzip_export
183
-int	 	zzip_read(ZZIP_FILE * fp, char * buf, int len);
184
-
182
+zzip_ssize_t	zzip_read(ZZIP_FILE * fp, char * buf, zzip_size_t len);
185 183
 
184
+/*
185
+ * the stdc variant to open/read/close files. - Take note of the freopen()
186
+ * call as it may reuse an existing preparsed copy of a zip central directory
187
+ */
186 188
 _zzip_export
187 189
 ZZIP_FILE*      zzip_freopen(zzip_char_t* name, zzip_char_t* mode, ZZIP_FILE*);
188 190
 _zzip_export
189 191
 ZZIP_FILE*      zzip_fopen(zzip_char_t* name, zzip_char_t* mode);
190 192
 _zzip_export
191
-int             zzip_fread(void *ptr, int size, int nmemb, ZZIP_FILE *file);
193
+zzip_size_t     zzip_fread(void *ptr, zzip_size_t size, zzip_size_t nmemb, 
194
+			   ZZIP_FILE * file);
192 195
 _zzip_export
193 196
 int  		zzip_fclose(ZZIP_FILE * fp);
194 197
 
... ...
@@ -198,21 +210,18 @@ int  		zzip_fclose(ZZIP_FILE * fp);
198 198
 _zzip_export
199 199
 int             zzip_rewind(ZZIP_FILE *fp);
200 200
 _zzip_export
201
-int             zzip_seek(ZZIP_FILE * fp, int offset, int
202
-			       whence);
201
+zzip_off_t      zzip_seek(ZZIP_FILE * fp, zzip_off_t offset, int whence);
203 202
 _zzip_export
204
-int             zzip_tell(ZZIP_FILE * fp);
205
-
203
+zzip_off_t      zzip_tell(ZZIP_FILE * fp);
206 204
 
207 205
 /*
208 206
  * reading info of a single file 
209
- * zzip-stat.c
207
+ * zzip/stat.c
210 208
  */
211 209
 _zzip_export
212 210
 int		zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t* name, 
213 211
 			      ZZIP_STAT * zs, int flags);
214 212
 
215
-
216 213
 #ifdef ZZIP_LARGEFILE_RENAME
217 214
 #define zzip_open_shared_io  zzip_open_shared_io64
218 215
 #define zzip_open_ext_io     zzip_open_ext_io64
... ...
@@ -246,13 +255,73 @@ ZZIP_FILE * zzip_file_open_ext_io(ZZIP_DIR * dir,
246 246
 				  zzip_strings_t* ext, zzip_plugin_io_t io);
247 247
 
248 248
 _zzip_export
249
-ZZIP_DIR *  zzip_dir_open_ext_io(zzip_char_t* filename, 
249
+ZZIP_DIR *  zzip_dir_open_ext_io(zzip_char_t* filename,
250 250
 				 zzip_error_t* errcode_p,
251 251
 				 zzip_strings_t* ext, zzip_plugin_io_t io);
252 252
 
253
+#if defined _ZZIP_WRITE_SOURCE
254
+/* ........................................................................
255
+ * write support is not yet implemented
256
+ * zzip/write.c
257
+ */
258
+#define ZZIP_NO_CREAT 1
259
+
260
+ZZIP_DIR*    zzip_dir_creat_ext_io(zzip_char_t* name, int o_mode, 
261
+                                   zzip_strings_t* ext, zzip_plugin_io_t io);
262
+ZZIP_DIR*    zzip_dir_creat(zzip_char_t* name, int o_mode);
263
+int          zzip_file_mkdir(ZZIP_DIR* dir, zzip_char_t* name, int o_mode);
264
+ZZIP_FILE*   zzip_file_creat(ZZIP_DIR* dir, zzip_char_t* name, int o_mode);
265
+zzip_ssize_t zzip_file_write(ZZIP_FILE* file, 
266
+                             const void* ptr, zzip_size_t len);
267
+
268
+ZZIP_DIR*    zzip_createdir(zzip_char_t* name, int o_mode);
269
+zzip_ssize_t zzip_write(ZZIP_FILE* file, const void* ptr, zzip_size_t len);
270
+zzip_size_t  zzip_fwrite(const void* ptr, zzip_size_t len, 
271
+                         zzip_size_t multiply, ZZIP_FILE* file);
272
+#ifndef zzip_savefile
273
+#define zzip_savefile 0
274
+#define zzip_savefile_is_null
275
+#endif
276
+
277
+#ifdef _ZZIP_NO_INLINE
278
+#define zzip_mkdir(_name_,_mode_) \
279
+        zzip_file_mkdir((zzip_savefile),(_name_),(_mode_))
280
+#define zzip_creat(_name_,_mode_) \
281
+        zzip_file_creat((zzip_savefile),(_name_),(_mode_))
282
+#define zzip_sync() \
283
+      { zzip_closedir((zzip_savefile)); (zzip_savefile) = 0; }
284
+#define zzip_start(_name_,_mode_,_ext_) \
285
+      { if ((zzip_savefile)) zzip_closedir((zzip_savefile)); 
286
+         zzip_savefile = zzip_dir_creat(_name_, _mode_,_ext_); }
287
+
288
+#else
289
+
290
+_zzip_inline static int         zzip_mkdir(zzip_char_t* name, int o_mode)
291
+{                   return zzip_file_mkdir(zzip_savefile, name, o_mode); }
292
+_zzip_inline static ZZIP_FILE*  zzip_creat(zzip_char_t* name, int o_mode)
293
+{                   return zzip_file_creat(zzip_savefile, name, o_mode); }
294
+
295
+#ifndef zzip_savefile_is_null
296
+_zzip_inline static void        zzip_sync(void)
297
+{                           zzip_closedir(zzip_savefile); zzip_savefile = 0; }
298
+_zzip_inline static void        zzip_mkfifo(zzip_char_t* name, int o_mode)
299
+{       if ((zzip_savefile)) zzip_closedir (zzip_savefile);
300
+             zzip_savefile = zzip_createdir(_name_,_mode_); }
301
+#else
302
+_zzip_inline static void        zzip_sync(void) {}
303
+_zzip_inline static void        zzip_mkfifo(zzip_char_t* name, int o_mode) {}
304
+#endif
305
+#endif /* _ZZIP_NO_INLINE */
306
+#endif /* _ZZIP_WRITE_SOURCE */
307
+
253 308
 #ifdef __cplusplus
254 309
 };
255 310
 #endif
256 311
 
257 312
 #endif /* _ZZIPLIB_H */
258 313
 
314
+/* 
315
+ * Local variables:
316
+ * c-file-style: "stroustrup"
317
+ * End:
318
+ */
... ...
@@ -34,7 +34,7 @@ int main(int argc, char **argv)
34 34
 	int ret, opt_index, i, len;
35 35
 	struct optstruct *opt;
36 36
 
37
-	const char *getopt_parameters = "hvVc:s:f:";
37
+	const char *getopt_parameters = "hvVc:s:f:b:i:";
38 38
 
39 39
 	static struct option long_options[] = {
40 40
 	    {"help", 0, 0, 'h'},
... ...
@@ -47,6 +47,8 @@ int main(int argc, char **argv)
47 47
 	    {"command", 1, 0, 'c'},
48 48
 	    {"string", 1, 0, 's'},
49 49
 	    {"file", 1, 0, 'f'},
50
+	    {"build", 1, 0, 'b'},
51
+	    {"info", 1, 0, 'i'},
50 52
 	    {0, 0, 0, 0}
51 53
     	};
52 54
 
... ...
@@ -24,6 +24,9 @@
24 24
 #include <stdlib.h>
25 25
 #include <string.h>
26 26
 #include <unistd.h>
27
+#include <zlib.h>
28
+#include <time.h>
29
+#include <locale.h>
27 30
 #include <clamav.h>
28 31
 
29 32
 #include "options.h"
... ...
@@ -73,7 +76,7 @@ char *cut(const char *file, long int start, long int end)
73 73
 	exit(13);
74 74
     }
75 75
 
76
-    fname = gentemp(".");
76
+    fname = cl_gentemp(".");
77 77
     if((wd = fopen(fname, "wb")) == NULL) {
78 78
 	mprintf("!Can't create temporary file %s\n", fname);
79 79
 	exit(14);
... ...
@@ -102,7 +105,7 @@ char *cut(const char *file, long int start, long int end)
102 102
 
103 103
 char *change(const char *file, long int x)
104 104
 {
105
-	char *fname, buffer[BUFFSIZE];
105
+	char *fname, buffer[FBUFFSIZE];
106 106
 	int bytes, size, sum, ch;
107 107
 	FILE *rd, *wd;
108 108
 
... ...
@@ -112,13 +115,13 @@ char *change(const char *file, long int x)
112 112
 	exit(13);
113 113
     }
114 114
 
115
-    fname = gentemp(".");
115
+    fname = cl_gentemp(".");
116 116
     if((wd = fopen(fname, "wb+")) == NULL) {
117 117
 	mprintf("!Can't create temporary file %s\n", fname);
118 118
 	exit(14);
119 119
     }
120 120
 
121
-    while((bytes = fread(buffer, 1, BUFFSIZE, rd)) > 0)
121
+    while((bytes = fread(buffer, 1, FBUFFSIZE, rd)) > 0)
122 122
 	fwrite(buffer, 1, bytes, wd);
123 123
 
124 124
     fclose(rd);
... ...
@@ -134,7 +137,7 @@ char *change(const char *file, long int x)
134 134
 
135 135
 void sigtool(struct optstruct *opt)
136 136
 {
137
-	    char buffer[BUFFSIZE];
137
+	    char buffer[FBUFFSIZE];
138 138
 	    int bytes;
139 139
 	    char *pt;
140 140
 
... ...
@@ -158,12 +161,20 @@ void sigtool(struct optstruct *opt)
158 158
 
159 159
     if(optl(opt, "hex-dump")) {
160 160
 
161
-	while((bytes = read(0, buffer, BUFFSIZE)) > 0) {
161
+	while((bytes = read(0, buffer, FBUFFSIZE)) > 0) {
162 162
 	    pt = cl_str2hex(buffer, bytes);
163 163
 	    write(1, pt, 2 * bytes);
164 164
 	    free(pt);
165 165
 	}
166 166
 
167
+    } else if(optc(opt, 'b')) {
168
+
169
+	build(opt);
170
+
171
+    } else if(optc(opt, 'i')) {
172
+
173
+	cvdinfo(opt);
174
+
167 175
     } else {
168 176
 	    int jmp, lastjmp, start, end, found = 0, exec = 0, pos, filesize;
169 177
 	    char *c, *s, *f, *tmp, *signame, *bsigname, *f2;
... ...
@@ -330,7 +341,7 @@ void sigtool(struct optstruct *opt)
330 330
 	if(fileinfo(signame, 1) != -1) {
331 331
 	    mprintf("File %s exists.\n", signame);
332 332
 	    free(signame);
333
-	    signame = gentemp(".");
333
+	    signame = cl_gentemp(".");
334 334
 	}
335 335
 
336 336
 	bsigname = (char *) mcalloc(strlen(f) + 10, sizeof(char));
... ...
@@ -338,7 +349,7 @@ void sigtool(struct optstruct *opt)
338 338
 	if(fileinfo(bsigname, 1) != -1) {
339 339
 	    mprintf("File %s exists.\n", bsigname);
340 340
 	    free(bsigname);
341
-	    bsigname = gentemp(".");
341
+	    bsigname = cl_gentemp(".");
342 342
 	}
343 343
 
344 344
 	if((wd = fopen(signame, "wb")) == NULL) {
... ...
@@ -350,7 +361,7 @@ void sigtool(struct optstruct *opt)
350 350
 
351 351
 	mprintf("Saving signature in %s file.\n", signame);
352 352
 
353
-	while((bytes = fread(buffer, 1, BUFFSIZE, fd)) > 0) {
353
+	while((bytes = fread(buffer, 1, FBUFFSIZE, fd)) > 0) {
354 354
 	    pt = cl_str2hex(buffer, bytes);
355 355
 	    fwrite(pt, 1, 2 * bytes, wd);
356 356
 	    free(pt);
... ...
@@ -369,6 +380,204 @@ void sigtool(struct optstruct *opt)
369 369
     //free_opt(opt);
370 370
 }
371 371
 
372
+int build(struct optstruct *opt)
373
+{
374
+	int ret, no = 0, bytes, itmp;
375
+	struct stat foo;
376
+	char buffer[BUFFSIZE], *tarfile = NULL, *gzfile = NULL, header[257],
377
+	     smbuff[25], *pt;
378
+        struct cl_node *root = NULL;
379
+	FILE *tar, *cvd;
380
+	gzFile *gz;
381
+	time_t timet;
382
+	struct tm *brokent;
383
+
384
+    /* build a tar.gz archive
385
+     * we need: COPYING, viruses.db / viruses.db2
386
+     * in current working directory
387
+     */
388
+
389
+    if(stat("COPYING", &foo) == -1) {
390
+	mprintf("COPYING file not found in current working directory.\n");
391
+	exit(1);
392
+    }
393
+
394
+    if(stat("viruses.db", &foo) == -1 || stat("viruses.db2", &foo) == -1) {
395
+	mprintf("Virus database not found in current working directory.\n");
396
+	exit(1);
397
+    }
398
+
399
+    cl_debug(); /* enable debug messages */
400
+
401
+    if((ret = cl_loaddbdir(cl_retdbdir(), &root, &no))) {
402
+	mprintf("!Can't load database: %s\n", cl_strerror(ret));
403
+        exit(1);
404
+    }
405
+
406
+    cl_freetrie(root);
407
+
408
+    mprintf("Database properly parsed.\n");
409
+
410
+    if(!no)
411
+	mprintf("WARNING: There are no signatures in the database(s).\n");
412
+    else
413
+	mprintf("Signatures: %d\n", no);
414
+
415
+    tarfile = cl_gentemp(".");
416
+
417
+    switch(fork()) {
418
+	case -1:
419
+	    mprintf("!Can't fork.\n");
420
+	    exit(1);
421
+	case 0:
422
+	    {
423
+		char *args[] = { "tar", "-cvf", tarfile, "COPYING", "viruses.db", "viruses.db2", NULL };
424
+		execv("/bin/tar", args);
425
+		mprintf("!Can't execute tar\n");
426
+		perror("tar");
427
+		exit(1);
428
+	    }
429
+	default:
430
+	    wait(NULL);
431
+    }
432
+
433
+    if(stat(tarfile, &foo) == -1) {
434
+	mprintf("!Can't generate tar file.\n");
435
+	exit(1);
436
+    }
437
+
438
+    if((tar = fopen(tarfile, "rb")) == NULL) {
439
+	mprintf("!Can't open file %s\n", tarfile);
440
+	exit(1);
441
+    }
442
+
443
+    gzfile = cl_gentemp(".");
444
+    if((gz = gzopen(gzfile, "wb")) == NULL) {
445
+	mprintf("!Can't open file %s to write.\n", gzfile);
446
+	exit(1);
447
+    }
448
+
449
+    while((bytes = fread(buffer, 1, BUFFSIZE, tar)) > 0)
450
+	gzwrite(gz, buffer, bytes);
451
+
452
+    fclose(tar);
453
+    unlink(tarfile);
454
+    free(tarfile);
455
+
456
+    gzclose(gz);
457
+
458
+    /* generate header */
459
+
460
+    /* magic string */
461
+
462
+    strcpy(header, "ClamAV-VDB:");
463
+
464
+    /* time */
465
+
466
+    time(&timet);
467
+    brokent = localtime(&timet);
468
+    setlocale(LC_TIME, "C");
469
+    strftime(smbuff, 24, "%b-%d %H-%M %Z:", brokent);
470
+    strcat(header, smbuff);
471
+
472
+    /* version number */
473
+
474
+    // tutaj ma przeczytac naglowek z obecnej bazy o tej samej nazwie
475
+    // i uzyc o jeden wiekszy
476
+
477
+    mprintf("!Can't read database version number from current local database\n");
478
+    fflush(stdin);
479
+    mprintf("Please enter a version number for the new database: ");
480
+    scanf("%d", &itmp);
481
+    sprintf(smbuff, "%d:", itmp);
482
+    strcat(header, smbuff);
483
+
484
+    /* number of signatures */
485
+    sprintf(smbuff, "%d:", no);
486
+    strcat(header, smbuff);
487
+
488
+    /* functionality level */
489
+    // pobierac z cl_funclevel()
490
+    sprintf(smbuff, "%d:", 1);
491
+    strcat(header, smbuff);
492
+
493
+    /* MD5 */
494
+    pt = cl_md5file(gzfile);
495
+    strcat(header, pt);
496
+    strcat(header, ":");
497
+
498
+    /* digital signature */
499
+    strcat(header, ":");
500
+
501
+    /* builder */
502
+    fflush(stdin);
503
+    mprintf("Builder name: ");
504
+    //fgets(smbuff, 24, stdin);
505
+    fscanf(stdin, "%s:", &smbuff);
506
+    strcat(header, smbuff);
507
+    //strcat(header, ":");
508
+
509
+    /* fill up with spaces */
510
+    if(strlen(header) > 256) {
511
+	mprintf("!Generated signature is too long.\n");
512
+	exit(1);
513
+    }
514
+
515
+    while(strlen(header) < 256)
516
+	strcat(header, " ");
517
+
518
+    /* build the final database */
519
+
520
+    pt = getargc(opt, 'b');
521
+    if((cvd = fopen(pt, "wb")) == NULL) {
522
+	mprintf("!Can't write the final database %s\n", pt);
523
+	exit(1);
524
+    }
525
+
526
+    fwrite(header, 1, 256, cvd);
527
+
528
+    if((tar = fopen(gzfile, "rb")) == NULL) {
529
+	mprintf("!Can't open file %s for reading.\n", gzfile);
530
+	exit(1);
531
+    }
532
+
533
+    while((bytes = fread(buffer, 1, BUFFSIZE, tar)) > 0)
534
+	fwrite(buffer, 1, bytes, cvd);
535
+
536
+    fclose(tar);
537
+    fclose(cvd);
538
+
539
+    unlink(gzfile);
540
+    free(gzfile);
541
+
542
+    mprintf("Database %s created.\n", pt);
543
+
544
+    // teraz zaladuj baze
545
+}
546
+
547
+void cvdinfo(struct optstruct *opt)
548
+{
549
+	struct cl_cvd *cvd;
550
+	char *pt;
551
+
552
+    if((cvd = cl_cvdhead(getargc(opt, 'i'))) == NULL) {
553
+	mprintf("!Can't read CVD header from %s\n", getargc(opt, 'i'));
554
+	exit(1);
555
+    }
556
+
557
+    mprintf("Creation time: %s\n", cvd->time);
558
+    mprintf("Version: %d\n", cvd->version);
559
+    mprintf("# of signatures: %d\n", cvd->sigs);
560
+    mprintf("Functionality level: %d\n", cvd->fl);
561
+    mprintf("Builder: %s\n", cvd->builder);
562
+    mprintf("MD5: %s\n", cvd->md5);
563
+
564
+   // pt = cl_md5file( DODAC WERYFIKACJE
565
+    mprintf("Digital signature: %s\n", cvd->dsig);
566
+
567
+    // wyczysc cvd
568
+}
569
+
372 570
 void help(void)
373 571
 {
374 572
     mprintf("\n");
... ...
@@ -384,7 +593,9 @@ void help(void)
384 384
     mprintf("					string and send it to stdout\n");
385 385
     mprintf("   --command		    -c		scanner command string, with options\n");
386 386
     mprintf("   --string		    -s		'virus found' string in scan. output\n");
387
-    mprintf("   --file		    -f		infected file\n\n");
388
-
387
+    mprintf("   --file		    -f		infected file\n");
388
+    mprintf("\n	DATABASE DEVELOPING:\n\n");
389
+    mprintf("   --build NAME	    -b NAME		Build database\n");
390
+    
389 391
     exit(0);
390 392
 }