1 /* Made up from data.c and other supplementary files of dictd-1.0.11 for the
2 * GoldenDict program.
3 */
4
5 /* data.c --
6 * Created: Tue Jul 16 12:45:41 1996 by faith@dict.org
7 * Revised: Sat Mar 30 10:46:06 2002 by faith@dict.org
8 * Copyright 1996, 1997, 1998, 2000, 2002 Rickard E. Faith (faith@dict.org)
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 1, or (at your option) any
13 * later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Suite 500, Boston, MA 02110, USA.
23 */
24
25 #include <stdlib.h>
26 #include <time.h>
27 #include "dictzip.h"
28 #include <limits.h>
29 #include <stdarg.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include "ufile.hh"
35
36 #define BUFFERSIZE 10240
37
38 #define OUT_BUFFER_SIZE 0xffffL
39
40 #define IN_BUFFER_SIZE ((unsigned long)((double)(OUT_BUFFER_SIZE - 12) * 0.89))
41
42 /* For gzip-compatible header, as defined in RFC 1952 */
43
44 /* Magic for GZIP (rfc1952) */
45 #define GZ_MAGIC1 0x1f /* First magic byte */
46 #define GZ_MAGIC2 0x8b /* Second magic byte */
47
48 /* FLaGs (bitmapped), from rfc1952 */
49 #define GZ_FTEXT 0x01 /* Set for ASCII text */
50 #define GZ_FHCRC 0x02 /* Header CRC16 */
51 #define GZ_FEXTRA 0x04 /* Optional field (random access index) */
52 #define GZ_FNAME 0x08 /* Original name */
53 #define GZ_COMMENT 0x10 /* Zero-terminated, human-readable comment */
54 #define GZ_MAX 2 /* Maximum compression */
55 #define GZ_FAST 4 /* Fasted compression */
56
57 /* These are from rfc1952 */
58 #define GZ_OS_FAT 0 /* FAT filesystem (MS-DOS, OS/2, NT/Win32) */
59 #define GZ_OS_AMIGA 1 /* Amiga */
60 #define GZ_OS_VMS 2 /* VMS (or OpenVMS) */
61 #define GZ_OS_UNIX 3 /* Unix */
62 #define GZ_OS_VMCMS 4 /* VM/CMS */
63 #define GZ_OS_ATARI 5 /* Atari TOS */
64 #define GZ_OS_HPFS 6 /* HPFS filesystem (OS/2, NT) */
65 #define GZ_OS_MAC 7 /* Macintosh */
66 #define GZ_OS_Z 8 /* Z-System */
67 #define GZ_OS_CPM 9 /* CP/M */
68 #define GZ_OS_TOPS20 10 /* TOPS-20 */
69 #define GZ_OS_NTFS 11 /* NTFS filesystem (NT) */
70 #define GZ_OS_QDOS 12 /* QDOS */
71 #define GZ_OS_ACORN 13 /* Acorn RISCOS */
72 #define GZ_OS_UNKNOWN 255 /* unknown */
73
74 #define GZ_RND_S1 'R' /* First magic for random access format */
75 #define GZ_RND_S2 'A' /* Second magic for random access format */
76
77 #define GZ_ID1 0 /* GZ_MAGIC1 */
78 #define GZ_ID2 1 /* GZ_MAGIC2 */
79 #define GZ_CM 2 /* Compression Method (Z_DEFALTED) */
80 #define GZ_FLG 3 /* FLaGs (see above) */
81 #define GZ_MTIME 4 /* Modification TIME */
82 #define GZ_XFL 8 /* eXtra FLags (GZ_MAX or GZ_FAST) */
83 #define GZ_OS 9 /* Operating System */
84 #define GZ_XLEN 10 /* eXtra LENgth (16bit) */
85 #define GZ_FEXTRA_START 12 /* Start of extra fields */
86 #define GZ_SI1 12 /* Subfield ID1 */
87 #define GZ_SI2 13 /* Subfield ID2 */
88 #define GZ_SUBLEN 14 /* Subfield length (16bit) */
89 #define GZ_VERSION 16 /* Version for subfield format */
90 #define GZ_CHUNKLEN 18 /* Chunk length (16bit) */
91 #define GZ_CHUNKCNT 20 /* Number of chunks (16bit) */
92 #define GZ_RNDDATA 22 /* Random access data (16bit) */
93
94
95 #define DBG_VERBOSE (0<<30|1<< 0) /* Verbose */
96 #define DBG_ZIP (0<<30|1<< 1) /* Zip */
97 #define DBG_UNZIP (0<<30|1<< 2) /* Unzip */
98 #define DBG_SEARCH (0<<30|1<< 3) /* Search */
99 #define DBG_SCAN (0<<30|1<< 4) /* Config file scan */
100 #define DBG_PARSE (0<<30|1<< 5) /* Config file parse */
101 #define DBG_INIT (0<<30|1<< 6) /* Database initialization */
102 #define DBG_PORT (0<<30|1<< 7) /* Log port number for connections */
103 #define DBG_LEV (0<<30|1<< 8) /* Levenshtein matching */
104 #define DBG_AUTH (0<<30|1<< 9) /* Debug authentication */
105 #define DBG_NODETACH (0<<30|1<<10) /* Don't detach as a background proc. */
106 #define DBG_NOFORK (0<<30|1<<11) /* Don't fork (single threaded) */
107 #define DBG_ALT (0<<30|1<<12) /* altcompare() */
108
109 #define LOG_SERVER (0<<30|1<< 0) /* Log server diagnostics */
110 #define LOG_CONNECT (0<<30|1<< 1) /* Log connection information */
111 #define LOG_STATS (0<<30|1<< 2) /* Log termination information */
112 #define LOG_COMMAND (0<<30|1<< 3) /* Log commands */
113 #define LOG_FOUND (0<<30|1<< 4) /* Log words found */
114 #define LOG_NOTFOUND (0<<30|1<< 5) /* Log words not found */
115 #define LOG_CLIENT (0<<30|1<< 6) /* Log client */
116 #define LOG_HOST (0<<30|1<< 7) /* Log remote host name */
117 #define LOG_TIMESTAMP (0<<30|1<< 8) /* Log with timestamps */
118 #define LOG_MIN (0<<30|1<< 9) /* Log a few minimal things */
119 #define LOG_AUTH (0<<30|1<<10) /* Log authentication denials */
120
121 #define DICT_LOG_TERM 0
122 #define DICT_LOG_DEFINE 1
123 #define DICT_LOG_MATCH 2
124 #define DICT_LOG_NOMATCH 3
125 #define DICT_LOG_CLIENT 4
126 #define DICT_LOG_TRACE 5
127 #define DICT_LOG_COMMAND 6
128 #define DICT_LOG_AUTH 7
129 #define DICT_LOG_CONNECT 8
130
131 #define DICT_UNKNOWN 0
132 #define DICT_TEXT 1
133 #define DICT_GZIP 2
134 #define DICT_DZIP 3
135
136 #include <ctype.h>
137 #include <fcntl.h>
138 #include <assert.h>
139
140 #include <sys/stat.h>
141
142 #define USE_CACHE 1
143
144 #define dict_data_filter( ... )
145 #define PRINTF( ... )
146
147 #define xmalloc malloc
148 #define xfree free
149
150 static const char * _err_programName = "GoldenDict";
151
152 #define log_error( ... )
153 #define log_error_va( ... )
154
err_fatal(const char * routine,const char * format,...)155 static void err_fatal( const char *routine, const char *format, ... )
156 {
157 va_list ap;
158
159 fflush( stdout );
160 if (_err_programName) {
161 if (routine)
162 fprintf( stderr, "%s (%s): ", _err_programName, routine );
163 else
164 fprintf( stderr, "%s: ", _err_programName );
165 } else {
166 if (routine) fprintf( stderr, "%s: ", routine );
167 }
168
169 va_start( ap, format );
170 vfprintf( stderr, format, ap );
171 log_error_va( routine, format, ap );
172 va_end( ap );
173
174 fflush( stderr );
175 fflush( stdout );
176 // exit ( 1 );
177 }
178
179 /* \doc |err_fatal_errno| flushes "stdout", prints a fatal error report on
180 "stderr", prints the system error corresponding to |errno|, flushes
181 "stderr" and "stdout", and calls |exit|. |routine| is the name of the
182 routine in which the error took place. */
183
err_fatal_errno(const char * routine,const char * format,...)184 static void err_fatal_errno( const char *routine, const char *format, ... )
185 {
186 va_list ap;
187 int errorno = errno;
188
189 fflush( stdout );
190 if (_err_programName) {
191 if (routine)
192 fprintf( stderr, "%s (%s): ", _err_programName, routine );
193 else
194 fprintf( stderr, "%s: ", _err_programName );
195 } else {
196 if (routine) fprintf( stderr, "%s: ", routine );
197 }
198
199 va_start( ap, format );
200 vfprintf( stderr, format, ap );
201 log_error_va( routine, format, ap );
202 va_end( ap );
203
204 #if HAVE_STRERROR
205 fprintf( stderr, "%s: %s\n", routine, strerror( errorno ) );
206 log_error( routine, "%s: %s\n", routine, strerror( errorno ) );
207 #else
208 errno = errorno;
209 perror( routine );
210 log_error( routine, "%s: errno = %d\n", routine, errorno );
211 #endif
212
213 fflush( stderr );
214 fflush( stdout );
215 // exit( 1 );
216 }
217
218 /* \doc |err_internal| flushes "stdout", prints the fatal error message,
219 flushes "stderr" and "stdout", and calls |abort| so that a core dump is
220 generated. */
221
err_internal(const char * routine,const char * format,...)222 static void err_internal( const char *routine, const char *format, ... )
223 {
224 va_list ap;
225
226 fflush( stdout );
227 if (_err_programName) {
228 if (routine)
229 fprintf( stderr, "%s (%s): Internal error\n ",
230 _err_programName, routine );
231 else
232 fprintf( stderr, "%s: Internal error\n ", _err_programName );
233 } else {
234 if (routine) fprintf( stderr, "%s: Internal error\n ", routine );
235 else fprintf( stderr, "Internal error\n " );
236 }
237
238 va_start( ap, format );
239 vfprintf( stderr, format, ap );
240 log_error( routine, format, ap );
241 va_end( ap );
242
243 if (_err_programName)
244 fprintf( stderr, "Aborting %s...\n", _err_programName );
245 else
246 fprintf( stderr, "Aborting...\n" );
247 fflush( stderr );
248 fflush( stdout );
249 // abort();
250 }
251
252 #ifndef __func__
253 # ifdef __FUNCTION__
254 # define __func__ __FUNCTION__
255 # else
256 # define __func__ __FILE__
257 # endif
258 #endif
259
dict_read_header(const char * filename,dictData * header,int computeCRC)260 static enum DZ_ERRORS dict_read_header( const char *filename,
261 dictData *header,
262 int computeCRC )
263 {
264 FILE *str;
265 int id1, id2, si1, si2;
266 char buffer[BUFFERSIZE];
267 int extraLength, subLength;
268 int i;
269 char *pt;
270 int c;
271 struct stat sb;
272 unsigned long crc = crc32( 0L, Z_NULL, 0 );
273 int count;
274 unsigned long offset;
275
276 if (!(str = gd_fopen( filename, "rb" )))
277 {
278 err_fatal_errno( __func__,
279 "Cannot open data file \"%s\" for read\n", filename );
280 return DZ_ERR_OPENFILE;
281 }
282
283 header->filename = NULL;//str_find( filename );
284 header->headerLength = GZ_XLEN - 1;
285 header->type = DICT_UNKNOWN;
286
287 id1 = getc( str );
288 id2 = getc( str );
289
290 if (id1 != GZ_MAGIC1 || id2 != GZ_MAGIC2) {
291 header->type = DICT_TEXT;
292 fstat( fileno( str ), &sb );
293 header->compressedLength = header->length = sb.st_size;
294 header->origFilename = NULL;//str_find( filename );
295 header->mtime = sb.st_mtime;
296 if (computeCRC) {
297 rewind( str );
298 while (!feof( str )) {
299 if ((count = fread( buffer, 1, BUFFERSIZE, str ))) {
300 crc = crc32( crc, (Bytef *)buffer, count );
301 }
302 }
303 }
304 header->crc = crc;
305 fclose( str );
306 return DZ_NOERROR;
307 }
308 header->type = DICT_GZIP;
309
310 header->method = getc( str );
311 header->flags = getc( str );
312 header->mtime = getc( str ) << 0;
313 header->mtime |= getc( str ) << 8;
314 header->mtime |= getc( str ) << 16;
315 header->mtime |= getc( str ) << 24;
316 header->extraFlags = getc( str );
317 header->os = getc( str );
318
319 if (header->flags & GZ_FEXTRA) {
320 extraLength = getc( str ) << 0;
321 extraLength |= getc( str ) << 8;
322 header->headerLength += extraLength + 2;
323 si1 = getc( str );
324 si2 = getc( str );
325
326 if (si1 == GZ_RND_S1 && si2 == GZ_RND_S2) {
327 subLength = getc( str ) << 0;
328 subLength |= getc( str ) << 8;
329 header->version = getc( str ) << 0;
330 header->version |= getc( str ) << 8;
331
332 if (header->version != 1)
333 {
334 err_internal( __func__,
335 "dzip header version %d not supported\n",
336 header->version );
337 fclose( str );
338 return DZ_ERR_UNSUPPORTED_FORMAT;
339 }
340
341 header->chunkLength = getc( str ) << 0;
342 header->chunkLength |= getc( str ) << 8;
343 header->chunkCount = getc( str ) << 0;
344 header->chunkCount |= getc( str ) << 8;
345
346 if (header->chunkCount <= 0) {
347 fclose( str );
348 return DZ_ERR_INVALID_FORMAT;
349 }
350 header->chunks = xmalloc( sizeof( header->chunks[0] )
351 * header->chunkCount );
352 if( header->chunks == 0 ) {
353 return DZ_ERR_NOMEMORY;
354 }
355
356 for (i = 0; i < header->chunkCount; i++) {
357 header->chunks[i] = getc( str ) << 0;
358 header->chunks[i] |= getc( str ) << 8;
359 }
360 header->type = DICT_DZIP;
361 } else {
362 fseek( str, header->headerLength, SEEK_SET );
363 }
364 }
365
366 if (header->flags & GZ_FNAME) { /* FIXME! Add checking against header len */
367 pt = buffer;
368 while ((c = getc( str )) && c != EOF){
369 *pt++ = c;
370
371 if (pt == buffer + sizeof (buffer)){
372 err_fatal (
373 __func__,
374 "too long FNAME field in dzip file \"%s\"\n", filename);
375 fclose( str );
376 if( header->chunks )
377 free( header->chunks );
378 return DZ_ERR_INVALID_FORMAT;
379 }
380 }
381
382 *pt = '\0';
383 header->origFilename = NULL;//str_find( buffer );
384 header->headerLength += strlen( buffer ) + 1;
385 } else {
386 header->origFilename = NULL;
387 }
388
389 if (header->flags & GZ_COMMENT) { /* FIXME! Add checking for header len */
390 pt = buffer;
391 while ((c = getc( str )) && c != EOF){
392 *pt++ = c;
393
394 if (pt == buffer + sizeof (buffer)){
395 err_fatal (
396 __func__,
397 "too long COMMENT field in dzip file \"%s\"\n", filename);
398 fclose( str );
399 if( header->chunks )
400 free( header->chunks );
401 return DZ_ERR_INVALID_FORMAT;
402 }
403 }
404
405 *pt = '\0';
406 header->comment = NULL;//str_find( buffer );
407 header->headerLength += strlen( buffer ) + 1;
408 } else {
409 header->comment = NULL;
410 }
411
412 if (header->flags & GZ_FHCRC) {
413 getc( str );
414 getc( str );
415 header->headerLength += 2;
416 }
417
418 if (ftell( str ) != header->headerLength + 1)
419 {
420 err_internal( __func__,
421 "File position (%lu) != header length + 1 (%d)\n",
422 ftell( str ), header->headerLength + 1 );
423 fclose( str );
424 if( header->chunks )
425 free( header->chunks );
426 return DZ_ERR_INVALID_FORMAT;
427 }
428
429 fseek( str, -8, SEEK_END );
430 header->crc = getc( str ) << 0;
431 header->crc |= getc( str ) << 8;
432 header->crc |= getc( str ) << 16;
433 header->crc |= getc( str ) << 24;
434 header->length = getc( str ) << 0;
435 header->length |= getc( str ) << 8;
436 header->length |= getc( str ) << 16;
437 header->length |= getc( str ) << 24;
438 header->compressedLength = ftell( str );
439
440 /* Compute offsets */
441 header->offsets = xmalloc( sizeof( header->offsets[0] )
442 * header->chunkCount );
443 if( header->offsets == 0 ) {
444 if( header->chunks )
445 free( header->chunks );
446 return DZ_ERR_NOMEMORY;
447 }
448
449 for (offset = header->headerLength + 1, i = 0;
450 i < header->chunkCount;
451 i++)
452 {
453 header->offsets[i] = offset;
454 offset += header->chunks[i];
455 }
456
457 fclose( str );
458 return DZ_NOERROR;
459 }
460
dict_data_open(const char * filename,enum DZ_ERRORS * error,int computeCRC)461 dictData *dict_data_open( const char *filename,
462 enum DZ_ERRORS * error,
463 int computeCRC )
464 {
465 dictData *h = NULL;
466 // struct stat sb;
467 int j;
468
469 if (!filename)
470 {
471 *error = DZ_ERR_OPENFILE;
472 return NULL;
473 }
474
475 h = xmalloc( sizeof( struct dictData ) );
476 if( h == 0 )
477 {
478 *error = DZ_ERR_NOMEMORY;
479 return 0;
480 }
481
482 memset( h, 0, sizeof( struct dictData ) );
483 #ifdef __WIN32
484 h->fd = INVALID_HANDLE_VALUE;
485 #endif
486 h->initialized = 0;
487
488 for(;;)
489 {
490 #ifdef __WIN32
491 wchar_t wname[16384];
492 #endif
493 *error = dict_read_header( filename, h, computeCRC );
494 if ( *error != DZ_NOERROR ) {
495 break; /*
496 err_fatal( __func__,
497 "\"%s\" not in text or dzip format\n", filename );*/
498 }
499
500 #ifdef __WIN32
501 if( MultiByteToWideChar( CP_UTF8, 0, filename, -1, wname, 16384 ) == 0 )
502 {
503 *error = DZ_ERR_OPENFILE;
504 break;
505 }
506
507 h->fd = CreateFileW( wname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
508 OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, 0);
509 if( h->fd == INVALID_HANDLE_VALUE )
510 {
511 *error = DZ_ERR_OPENFILE;
512 break;
513 }
514
515 h->size = GetFileSize( h->fd, 0 );
516 #else
517 h->fd = gd_fopen( filename, "rb" );
518
519 if ( !h->fd )
520 {
521 *error = DZ_ERR_OPENFILE;
522 break;
523 /*err_fatal_errno( __func__,
524 "Cannot open data file \"%s\"\n", filename );*/
525 }
526
527 fseek( h->fd, 0, SEEK_END );
528
529 h->size = ftell( h->fd );
530 #endif
531
532 for (j = 0; j < DICT_CACHE_SIZE; j++) {
533 h->cache[j].chunk = -1;
534 h->cache[j].stamp = -1;
535 h->cache[j].inBuffer = NULL;
536 h->cache[j].count = 0;
537 }
538
539 *error = DZ_NOERROR;
540 return h;
541 }
542 dict_data_close( h );
543 return( 0 );
544 }
545
dict_data_close(dictData * header)546 void dict_data_close( dictData *header )
547 {
548 int i;
549
550 if (!header)
551 return;
552
553 #ifdef __WIN32
554 if ( header->fd != INVALID_HANDLE_VALUE )
555 CloseHandle( header->fd );
556 #else
557 if ( header->fd )
558 fclose( header->fd );
559 #endif
560
561 if (header->chunks) xfree( header->chunks );
562 if (header->offsets) xfree( header->offsets );
563
564 if (header->initialized) {
565 if (inflateEnd( &header->zStream ))
566 err_internal( __func__,
567 "Cannot shut down inflation engine: %s\n",
568 header->zStream.msg );
569 }
570
571 for (i = 0; i < DICT_CACHE_SIZE; ++i){
572 if (header -> cache [i].inBuffer)
573 xfree (header -> cache [i].inBuffer);
574 }
575
576 memset( header, 0, sizeof( struct dictData ) );
577 xfree( header );
578 }
579
dict_data_read_(dictData * h,unsigned long start,unsigned long size,const char * preFilter,const char * postFilter)580 char *dict_data_read_ (
581 dictData *h, unsigned long start, unsigned long size,
582 const char *preFilter, const char *postFilter )
583 {
584 char * buffer;
585 char * pt;
586 unsigned long end;
587 int count;
588 char *inBuffer;
589 char outBuffer[OUT_BUFFER_SIZE];
590 int firstChunk, lastChunk;
591 int firstOffset, lastOffset;
592 int i, j;
593 int found, target, lastStamp;
594 (void) preFilter;
595 (void) postFilter;
596
597 end = start + size;
598
599 buffer = xmalloc( size + 1 );
600 if( !buffer )
601 {
602 strcpy( h->errorString, dz_error_str( DZ_ERR_NOMEMORY ) );
603 return 0;
604 }
605
606 if ( !size )
607 {
608 *buffer = 0;
609 return buffer;
610 }
611
612 PRINTF(DBG_UNZIP,
613 ("dict_data_read( %p, %lu, %lu, %s, %s )\n",
614 h, start, size, preFilter, postFilter ));
615
616 assert( h != NULL);
617 switch (h->type) {
618 case DICT_GZIP:
619 /*
620 err_fatal( __func__,
621 "Cannot seek on pure gzip format files.\n"
622 "Use plain text (for performance)"
623 " or dzip format (for space savings).\n" );
624 break;
625 */
626 strcpy( h->errorString, "Cannot seek on pure gzip format files" );
627 xfree( buffer );
628 return 0;
629 case DICT_TEXT:
630 {
631 #ifdef __WIN32
632 long hiPtr = 0;
633 DWORD pos = SetFilePointer( h->fd, start, &hiPtr, FILE_BEGIN );
634 DWORD readed = 0;
635 if( pos != INVALID_SET_FILE_POINTER || GetLastError() != NO_ERROR )
636 ReadFile( h->fd, buffer, size, &readed, 0 );
637 if( size != readed )
638 #else
639 if ( fseek( h->fd, start, SEEK_SET ) != 0 ||
640 fread( buffer, size, 1, h->fd ) != 1 )
641 #endif
642 {
643 strcpy( h->errorString, dz_error_str( DZ_ERR_READFILE ) );
644 xfree( buffer );
645 return 0;
646 }
647
648 buffer[size] = '\0';
649 }
650 break;
651 case DICT_DZIP:
652 if (!h->initialized) {
653 h->zStream.zalloc = NULL;
654 h->zStream.zfree = NULL;
655 h->zStream.opaque = NULL;
656 h->zStream.next_in = 0;
657 h->zStream.avail_in = 0;
658 h->zStream.next_out = NULL;
659 h->zStream.avail_out = 0;
660 if (inflateInit2( &h->zStream, -15 ) != Z_OK)
661 /*
662 err_internal( __func__,
663 "Cannot initialize inflation engine: %s\n",
664 h->zStream.msg );
665 */
666 {
667 sprintf( h->errorString, "Cannot initialize inflation engine: %s", h->zStream.msg );
668 xfree( buffer );
669 return 0;
670 }
671 ++h->initialized;
672 }
673 firstChunk = start / h->chunkLength;
674 firstOffset = start - firstChunk * h->chunkLength;
675 lastChunk = end / h->chunkLength;
676 lastOffset = end - lastChunk * h->chunkLength;
677 PRINTF(DBG_UNZIP,
678 (" start = %lu, end = %lu\n"
679 "firstChunk = %d, firstOffset = %d,"
680 " lastChunk = %d, lastOffset = %d\n",
681 start, end, firstChunk, firstOffset, lastChunk, lastOffset ));
682 for (pt = buffer, i = firstChunk; i <= lastChunk; i++) {
683
684 /* Access cache */
685 found = 0;
686 target = 0;
687 lastStamp = INT_MAX;
688 for (j = 0; j < DICT_CACHE_SIZE; j++) {
689 #if USE_CACHE
690 if (h->cache[j].chunk == i) {
691 found = 1;
692 target = j;
693 break;
694 }
695 #endif
696 if (h->cache[j].stamp < lastStamp) {
697 lastStamp = h->cache[j].stamp;
698 target = j;
699 }
700 }
701
702 h->cache[target].stamp = ++h->stamp;
703 if( h->stamp < 0 )
704 {
705 h->stamp = 0;
706 for (j = 0; j < DICT_CACHE_SIZE; j++)
707 h->cache[j].stamp = -1;
708 }
709 if (found) {
710 count = h->cache[target].count;
711 inBuffer = h->cache[target].inBuffer;
712 } else {
713 #ifdef __WIN32
714 DWORD pos ;
715 DWORD readed;
716 #endif
717 h->cache[target].chunk = -1;
718 if (!h->cache[target].inBuffer)
719 h->cache[target].inBuffer = xmalloc( h->chunkLength );
720 inBuffer = h->cache[target].inBuffer;
721 if( !inBuffer )
722 {
723 strcpy( h->errorString, dz_error_str( DZ_ERR_NOMEMORY ) );
724 xfree( buffer );
725 return 0;
726 }
727
728 if (h->chunks[i] >= OUT_BUFFER_SIZE ) {
729 /*
730 err_internal( __func__,
731 "h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
732 i, h->chunks[i], OUT_BUFFER_SIZE );
733 */
734 sprintf( h->errorString, "h->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
735 i, h->chunks[i], OUT_BUFFER_SIZE );
736 xfree( buffer );
737 return 0;
738 }
739
740 #ifdef __WIN32
741 pos = SetFilePointer( h->fd, h->offsets[ i ], 0, FILE_BEGIN );
742 readed = 0;
743 if( pos != INVALID_SET_FILE_POINTER || GetLastError() != NO_ERROR )
744 ReadFile( h->fd, outBuffer, h->chunks[ i ], &readed, 0 );
745 if( h->chunks[ i ] != (int)readed )
746 #else
747 if ( fseek( h->fd, h->offsets[ i ], SEEK_SET ) != 0 ||
748 fread( outBuffer, h->chunks[ i ], 1, h->fd ) != 1 )
749 #endif
750 {
751 strcpy( h->errorString, dz_error_str( DZ_ERR_READFILE ) );
752 xfree( buffer );
753 return 0;
754 }
755
756 dict_data_filter( outBuffer, &count, OUT_BUFFER_SIZE, preFilter );
757
758 h->zStream.next_in = (Bytef *)outBuffer;
759 h->zStream.avail_in = h->chunks[i];
760 h->zStream.next_out = (Bytef *)inBuffer;
761 h->zStream.avail_out = h->chunkLength;
762 if (inflate( &h->zStream, Z_PARTIAL_FLUSH ) != Z_OK)
763 {
764 // err_fatal( __func__, "inflate: %s\n", h->zStream.msg );
765 sprintf( h->errorString, "inflate: %s\n", h->zStream.msg );
766 xfree( buffer );
767 return 0;
768 }
769 if (h->zStream.avail_in)
770 /*
771 err_internal( __func__,
772 "inflate did not flush (%d pending, %d avail)\n",
773 h->zStream.avail_in, h->zStream.avail_out );
774 */
775 {
776 sprintf( h->errorString, "inflate did not flush (%d pending, %d avail)\n",
777 h->zStream.avail_in, h->zStream.avail_out );
778 xfree( buffer );
779 return 0;
780 }
781
782 count = h->chunkLength - h->zStream.avail_out;
783 dict_data_filter( inBuffer, &count, h->chunkLength, postFilter );
784
785 h->cache[target].count = count;
786 h->cache[target].chunk = i;
787 }
788
789 if (i == firstChunk) {
790 if (i == lastChunk) {
791 memcpy( pt, inBuffer + firstOffset, lastOffset-firstOffset);
792 pt += lastOffset - firstOffset;
793 } else {
794 if (count != h->chunkLength )
795 /*
796 err_internal( __func__,
797 "Length = %d instead of %d\n",
798 count, h->chunkLength );
799 */
800 {
801 sprintf( h->errorString, "Length = %d instead of %d\n",
802 count, h->chunkLength );
803 xfree( buffer );
804 return 0;
805 }
806 memcpy( pt, inBuffer + firstOffset,
807 h->chunkLength - firstOffset );
808 pt += h->chunkLength - firstOffset;
809 }
810 } else if (i == lastChunk) {
811 memcpy( pt, inBuffer, lastOffset );
812 pt += lastOffset;
813 } else {
814 assert( count == h->chunkLength );
815 memcpy( pt, inBuffer, h->chunkLength );
816 pt += h->chunkLength;
817 }
818 }
819 *pt = '\0';
820 break;
821 case DICT_UNKNOWN:
822 // err_fatal( __func__, "Cannot read unknown file type\n" );
823 strcpy( h->errorString, "Cannot read unknown file type" );
824 xfree( buffer );
825 return 0;
826 }
827 h->errorString[ 0 ] = 0;
828 return buffer;
829 }
830
dict_error_str(dictData * data)831 char *dict_error_str( dictData *data )
832 {
833 return data->errorString;
834 }
835
dz_error_str(enum DZ_ERRORS error)836 const char * dz_error_str( enum DZ_ERRORS error )
837 {
838 switch( error )
839 {
840 case DZ_NOERROR: return "No error";
841 case DZ_ERR_OPENFILE: return "Open file error";
842 case DZ_ERR_READFILE: return "Read file error";
843 case DZ_ERR_INVALID_FORMAT: return "Invalid file format";
844 case DZ_ERR_UNSUPPORTED_FORMAT: return "Unsupported file format";
845 case DZ_ERR_NOMEMORY: return "Memory allocation error";
846 case DZ_ERR_INTERNAL: return "Internal error";
847 }
848 return "Unknown error";
849 }
850