source: trunk/third/zlib/contrib/minizip/unzip.c @ 15211

Revision 15211, 33.7 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15210, which included commits to RCS files with non-trunk default branches.
Line 
1/* unzip.c -- IO on .zip files using zlib
2   Version 0.15 beta, Mar 19th, 1998,
3
4   Read unzip.h for more info
5*/
6
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include "zlib.h"
12#include "unzip.h"
13
14#ifdef STDC
15#  include <stddef.h>
16#  include <string.h>
17#  include <stdlib.h>
18#endif
19#ifdef NO_ERRNO_H
20    extern int errno;
21#else
22#   include <errno.h>
23#endif
24
25
26#ifndef local
27#  define local static
28#endif
29/* compile with -Dlocal if your debugger can't find static symbols */
30
31
32
33#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
34                      !defined(CASESENSITIVITYDEFAULT_NO)
35#define CASESENSITIVITYDEFAULT_NO
36#endif
37
38
39#ifndef UNZ_BUFSIZE
40#define UNZ_BUFSIZE (16384)
41#endif
42
43#ifndef UNZ_MAXFILENAMEINZIP
44#define UNZ_MAXFILENAMEINZIP (256)
45#endif
46
47#ifndef ALLOC
48# define ALLOC(size) (malloc(size))
49#endif
50#ifndef TRYFREE
51# define TRYFREE(p) {if (p) free(p);}
52#endif
53
54#define SIZECENTRALDIRITEM (0x2e)
55#define SIZEZIPLOCALHEADER (0x1e)
56
57
58/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
59
60#ifndef SEEK_CUR
61#define SEEK_CUR    1
62#endif
63
64#ifndef SEEK_END
65#define SEEK_END    2
66#endif
67
68#ifndef SEEK_SET
69#define SEEK_SET    0
70#endif
71
72const char unz_copyright[] =
73   " unzip 0.15 Copyright 1998 Gilles Vollant ";
74
75/* unz_file_info_interntal contain internal info about a file in zipfile*/
76typedef struct unz_file_info_internal_s
77{
78    uLong offset_curfile;/* relative offset of local header 4 bytes */
79} unz_file_info_internal;
80
81
82/* file_in_zip_read_info_s contain internal information about a file in zipfile,
83    when reading and decompress it */
84typedef struct
85{
86        char  *read_buffer;         /* internal buffer for compressed data */
87        z_stream stream;            /* zLib stream structure for inflate */
88
89        uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
90        uLong stream_initialised;   /* flag set if stream structure is initialised*/
91
92        uLong offset_local_extrafield;/* offset of the local extra field */
93        uInt  size_local_extrafield;/* size of the local extra field */
94        uLong pos_local_extrafield;   /* position in the local extra field in read*/
95
96        uLong crc32;                /* crc32 of all data uncompressed */
97        uLong crc32_wait;           /* crc32 we must obtain after decompress all */
98        uLong rest_read_compressed; /* number of byte to be decompressed */
99        uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
100        FILE* file;                 /* io structore of the zipfile */
101        uLong compression_method;   /* compression method (0==store) */
102        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
103} file_in_zip_read_info_s;
104
105
106/* unz_s contain internal information about the zipfile
107*/
108typedef struct
109{
110        FILE* file;                 /* io structore of the zipfile */
111        unz_global_info gi;       /* public global information */
112        uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
113        uLong num_file;             /* number of the current file in the zipfile*/
114        uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
115        uLong current_file_ok;      /* flag about the usability of the current file*/
116        uLong central_pos;          /* position of the beginning of the central dir*/
117
118        uLong size_central_dir;     /* size of the central directory  */
119        uLong offset_central_dir;   /* offset of start of central directory with
120                                                                   respect to the starting disk number */
121
122        unz_file_info cur_file_info; /* public info about the current file in zip*/
123        unz_file_info_internal cur_file_info_internal; /* private info about it*/
124    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
125                                            file if we are decompressing it */
126} unz_s;
127
128
129/* ===========================================================================
130     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
131   for end of file.
132   IN assertion: the stream s has been sucessfully opened for reading.
133*/
134
135
136local int unzlocal_getByte(fin,pi)
137        FILE *fin;
138        int *pi;
139{
140    unsigned char c;
141        int err = fread(&c, 1, 1, fin);
142    if (err==1)
143    {
144        *pi = (int)c;
145        return UNZ_OK;
146    }
147    else
148    {
149        if (ferror(fin))
150            return UNZ_ERRNO;
151        else
152            return UNZ_EOF;
153    }
154}
155
156
157/* ===========================================================================
158   Reads a long in LSB order from the given gz_stream. Sets
159*/
160local int unzlocal_getShort (fin,pX)
161        FILE* fin;
162    uLong *pX;
163{
164    uLong x ;
165    int i;
166    int err;
167
168    err = unzlocal_getByte(fin,&i);
169    x = (uLong)i;
170   
171    if (err==UNZ_OK)
172        err = unzlocal_getByte(fin,&i);
173    x += ((uLong)i)<<8;
174   
175    if (err==UNZ_OK)
176        *pX = x;
177    else
178        *pX = 0;
179    return err;
180}
181
182local int unzlocal_getLong (fin,pX)
183        FILE* fin;
184    uLong *pX;
185{
186    uLong x ;
187    int i;
188    int err;
189
190    err = unzlocal_getByte(fin,&i);
191    x = (uLong)i;
192   
193    if (err==UNZ_OK)
194        err = unzlocal_getByte(fin,&i);
195    x += ((uLong)i)<<8;
196
197    if (err==UNZ_OK)
198        err = unzlocal_getByte(fin,&i);
199    x += ((uLong)i)<<16;
200
201    if (err==UNZ_OK)
202        err = unzlocal_getByte(fin,&i);
203    x += ((uLong)i)<<24;
204   
205    if (err==UNZ_OK)
206        *pX = x;
207    else
208        *pX = 0;
209    return err;
210}
211
212
213/* My own strcmpi / strcasecmp */
214local int strcmpcasenosensitive_internal (fileName1,fileName2)
215        const char* fileName1;
216        const char* fileName2;
217{
218        for (;;)
219        {
220                char c1=*(fileName1++);
221                char c2=*(fileName2++);
222                if ((c1>='a') && (c1<='z'))
223                        c1 -= 0x20;
224                if ((c2>='a') && (c2<='z'))
225                        c2 -= 0x20;
226                if (c1=='\0')
227                        return ((c2=='\0') ? 0 : -1);
228                if (c2=='\0')
229                        return 1;
230                if (c1<c2)
231                        return -1;
232                if (c1>c2)
233                        return 1;
234        }
235}
236
237
238#ifdef  CASESENSITIVITYDEFAULT_NO
239#define CASESENSITIVITYDEFAULTVALUE 2
240#else
241#define CASESENSITIVITYDEFAULTVALUE 1
242#endif
243
244#ifndef STRCMPCASENOSENTIVEFUNCTION
245#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
246#endif
247
248/*
249   Compare two filename (fileName1,fileName2).
250   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
251   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
252                                                                or strcasecmp)
253   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
254        (like 1 on Unix, 2 on Windows)
255
256*/
257extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
258        const char* fileName1;
259        const char* fileName2;
260        int iCaseSensitivity;
261{
262        if (iCaseSensitivity==0)
263                iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
264
265        if (iCaseSensitivity==1)
266                return strcmp(fileName1,fileName2);
267
268        return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
269}
270
271#define BUFREADCOMMENT (0x400)
272
273/*
274  Locate the Central directory of a zipfile (at the end, just before
275    the global comment)
276*/
277local uLong unzlocal_SearchCentralDir(fin)
278        FILE *fin;
279{
280        unsigned char* buf;
281        uLong uSizeFile;
282        uLong uBackRead;
283        uLong uMaxBack=0xffff; /* maximum size of global comment */
284        uLong uPosFound=0;
285       
286        if (fseek(fin,0,SEEK_END) != 0)
287                return 0;
288
289
290        uSizeFile = ftell( fin );
291       
292        if (uMaxBack>uSizeFile)
293                uMaxBack = uSizeFile;
294
295        buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
296        if (buf==NULL)
297                return 0;
298
299        uBackRead = 4;
300        while (uBackRead<uMaxBack)
301        {
302                uLong uReadSize,uReadPos ;
303                int i;
304                if (uBackRead+BUFREADCOMMENT>uMaxBack)
305                        uBackRead = uMaxBack;
306                else
307                        uBackRead+=BUFREADCOMMENT;
308                uReadPos = uSizeFile-uBackRead ;
309               
310                uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
311                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
312                if (fseek(fin,uReadPos,SEEK_SET)!=0)
313                        break;
314
315                if (fread(buf,(uInt)uReadSize,1,fin)!=1)
316                        break;
317
318                for (i=(int)uReadSize-3; (i--)>0;)
319                        if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
320                                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
321                        {
322                                uPosFound = uReadPos+i;
323                                break;
324                        }
325
326                if (uPosFound!=0)
327                        break;
328        }
329        TRYFREE(buf);
330        return uPosFound;
331}
332
333/*
334  Open a Zip file. path contain the full pathname (by example,
335     on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
336         "zlib/zlib109.zip".
337         If the zipfile cannot be opened (file don't exist or in not valid), the
338           return value is NULL.
339     Else, the return value is a unzFile Handle, usable with other function
340           of this unzip package.
341*/
342extern unzFile ZEXPORT unzOpen (path)
343        const char *path;
344{
345        unz_s us;
346        unz_s *s;
347        uLong central_pos,uL;
348        FILE * fin ;
349
350        uLong number_disk;          /* number of the current dist, used for
351                                                                   spaning ZIP, unsupported, always 0*/
352        uLong number_disk_with_CD;  /* number the the disk with central dir, used
353                                                                   for spaning ZIP, unsupported, always 0*/
354        uLong number_entry_CD;      /* total number of entries in
355                                       the central dir
356                                       (same than number_entry on nospan) */
357
358        int err=UNZ_OK;
359
360    if (unz_copyright[0]!=' ')
361        return NULL;
362
363    fin=fopen(path,"rb");
364        if (fin==NULL)
365                return NULL;
366
367        central_pos = unzlocal_SearchCentralDir(fin);
368        if (central_pos==0)
369                err=UNZ_ERRNO;
370
371        if (fseek(fin,central_pos,SEEK_SET)!=0)
372                err=UNZ_ERRNO;
373
374        /* the signature, already checked */
375        if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
376                err=UNZ_ERRNO;
377
378        /* number of this disk */
379        if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
380                err=UNZ_ERRNO;
381
382        /* number of the disk with the start of the central directory */
383        if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
384                err=UNZ_ERRNO;
385
386        /* total number of entries in the central dir on this disk */
387        if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
388                err=UNZ_ERRNO;
389
390        /* total number of entries in the central dir */
391        if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
392                err=UNZ_ERRNO;
393
394        if ((number_entry_CD!=us.gi.number_entry) ||
395                (number_disk_with_CD!=0) ||
396                (number_disk!=0))
397                err=UNZ_BADZIPFILE;
398
399        /* size of the central directory */
400        if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
401                err=UNZ_ERRNO;
402
403        /* offset of start of central directory with respect to the
404              starting disk number */
405        if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
406                err=UNZ_ERRNO;
407
408        /* zipfile comment length */
409        if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
410                err=UNZ_ERRNO;
411
412        if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
413                (err==UNZ_OK))
414                err=UNZ_BADZIPFILE;
415
416        if (err!=UNZ_OK)
417        {
418                fclose(fin);
419                return NULL;
420        }
421
422        us.file=fin;
423        us.byte_before_the_zipfile = central_pos -
424                                    (us.offset_central_dir+us.size_central_dir);
425        us.central_pos = central_pos;
426    us.pfile_in_zip_read = NULL;
427       
428
429        s=(unz_s*)ALLOC(sizeof(unz_s));
430        *s=us;
431        unzGoToFirstFile((unzFile)s);   
432        return (unzFile)s;     
433}
434
435
436/*
437  Close a ZipFile opened with unzipOpen.
438  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
439    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
440  return UNZ_OK if there is no problem. */
441extern int ZEXPORT unzClose (file)
442        unzFile file;
443{
444        unz_s* s;
445        if (file==NULL)
446                return UNZ_PARAMERROR;
447        s=(unz_s*)file;
448
449    if (s->pfile_in_zip_read!=NULL)
450        unzCloseCurrentFile(file);
451
452        fclose(s->file);
453        TRYFREE(s);
454        return UNZ_OK;
455}
456
457
458/*
459  Write info about the ZipFile in the *pglobal_info structure.
460  No preparation of the structure is needed
461  return UNZ_OK if there is no problem. */
462extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
463        unzFile file;
464        unz_global_info *pglobal_info;
465{
466        unz_s* s;
467        if (file==NULL)
468                return UNZ_PARAMERROR;
469        s=(unz_s*)file;
470        *pglobal_info=s->gi;
471        return UNZ_OK;
472}
473
474
475/*
476   Translate date/time from Dos format to tm_unz (readable more easilty)
477*/
478local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
479    uLong ulDosDate;
480    tm_unz* ptm;
481{
482    uLong uDate;
483    uDate = (uLong)(ulDosDate>>16);
484    ptm->tm_mday = (uInt)(uDate&0x1f) ;
485    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
486    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
487
488    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
489    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
490    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
491}
492
493/*
494  Get Info about the current file in the zipfile, with internal only info
495*/
496local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
497                                                  unz_file_info *pfile_info,
498                                                  unz_file_info_internal
499                                                  *pfile_info_internal,
500                                                  char *szFileName,
501                                                                                                  uLong fileNameBufferSize,
502                                                  void *extraField,
503                                                                                                  uLong extraFieldBufferSize,
504                                                  char *szComment,
505                                                                                                  uLong commentBufferSize));
506
507local int unzlocal_GetCurrentFileInfoInternal (file,
508                                              pfile_info,
509                                              pfile_info_internal,
510                                              szFileName, fileNameBufferSize,
511                                              extraField, extraFieldBufferSize,
512                                              szComment,  commentBufferSize)
513        unzFile file;
514        unz_file_info *pfile_info;
515        unz_file_info_internal *pfile_info_internal;
516        char *szFileName;
517        uLong fileNameBufferSize;
518        void *extraField;
519        uLong extraFieldBufferSize;
520        char *szComment;
521        uLong commentBufferSize;
522{
523        unz_s* s;
524        unz_file_info file_info;
525        unz_file_info_internal file_info_internal;
526        int err=UNZ_OK;
527        uLong uMagic;
528        long lSeek=0;
529
530        if (file==NULL)
531                return UNZ_PARAMERROR;
532        s=(unz_s*)file;
533        if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
534                err=UNZ_ERRNO;
535
536
537        /* we check the magic */
538        if (err==UNZ_OK)
539                if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
540                        err=UNZ_ERRNO;
541                else if (uMagic!=0x02014b50)
542                        err=UNZ_BADZIPFILE;
543
544        if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
545                err=UNZ_ERRNO;
546
547        if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
548                err=UNZ_ERRNO;
549
550        if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
551                err=UNZ_ERRNO;
552
553        if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
554                err=UNZ_ERRNO;
555
556        if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
557                err=UNZ_ERRNO;
558
559    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
560
561        if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
562                err=UNZ_ERRNO;
563
564        if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
565                err=UNZ_ERRNO;
566
567        if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
568                err=UNZ_ERRNO;
569
570        if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
571                err=UNZ_ERRNO;
572
573        if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
574                err=UNZ_ERRNO;
575
576        if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
577                err=UNZ_ERRNO;
578
579        if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
580                err=UNZ_ERRNO;
581
582        if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
583                err=UNZ_ERRNO;
584
585        if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
586                err=UNZ_ERRNO;
587
588        if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
589                err=UNZ_ERRNO;
590
591        lSeek+=file_info.size_filename;
592        if ((err==UNZ_OK) && (szFileName!=NULL))
593        {
594                uLong uSizeRead ;
595                if (file_info.size_filename<fileNameBufferSize)
596                {
597                        *(szFileName+file_info.size_filename)='\0';
598                        uSizeRead = file_info.size_filename;
599                }
600                else
601                        uSizeRead = fileNameBufferSize;
602
603                if ((file_info.size_filename>0) && (fileNameBufferSize>0))
604                        if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
605                                err=UNZ_ERRNO;
606                lSeek -= uSizeRead;
607        }
608
609       
610        if ((err==UNZ_OK) && (extraField!=NULL))
611        {
612                uLong uSizeRead ;
613                if (file_info.size_file_extra<extraFieldBufferSize)
614                        uSizeRead = file_info.size_file_extra;
615                else
616                        uSizeRead = extraFieldBufferSize;
617
618                if (lSeek!=0)
619                        if (fseek(s->file,lSeek,SEEK_CUR)==0)
620                                lSeek=0;
621                        else
622                                err=UNZ_ERRNO;
623                if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
624                        if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
625                                err=UNZ_ERRNO;
626                lSeek += file_info.size_file_extra - uSizeRead;
627        }
628        else
629                lSeek+=file_info.size_file_extra;
630
631       
632        if ((err==UNZ_OK) && (szComment!=NULL))
633        {
634                uLong uSizeRead ;
635                if (file_info.size_file_comment<commentBufferSize)
636                {
637                        *(szComment+file_info.size_file_comment)='\0';
638                        uSizeRead = file_info.size_file_comment;
639                }
640                else
641                        uSizeRead = commentBufferSize;
642
643                if (lSeek!=0)
644                        if (fseek(s->file,lSeek,SEEK_CUR)==0)
645                                lSeek=0;
646                        else
647                                err=UNZ_ERRNO;
648                if ((file_info.size_file_comment>0) && (commentBufferSize>0))
649                        if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
650                                err=UNZ_ERRNO;
651                lSeek+=file_info.size_file_comment - uSizeRead;
652        }
653        else
654                lSeek+=file_info.size_file_comment;
655
656        if ((err==UNZ_OK) && (pfile_info!=NULL))
657                *pfile_info=file_info;
658
659        if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
660                *pfile_info_internal=file_info_internal;
661
662        return err;
663}
664
665
666
667/*
668  Write info about the ZipFile in the *pglobal_info structure.
669  No preparation of the structure is needed
670  return UNZ_OK if there is no problem.
671*/
672extern int ZEXPORT unzGetCurrentFileInfo (file,
673                                                  pfile_info,
674                                                  szFileName, fileNameBufferSize,
675                                                  extraField, extraFieldBufferSize,
676                                                  szComment,  commentBufferSize)
677        unzFile file;
678        unz_file_info *pfile_info;
679        char *szFileName;
680        uLong fileNameBufferSize;
681        void *extraField;
682        uLong extraFieldBufferSize;
683        char *szComment;
684        uLong commentBufferSize;
685{
686        return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
687                                                                                                szFileName,fileNameBufferSize,
688                                                                                                extraField,extraFieldBufferSize,
689                                                                                                szComment,commentBufferSize);
690}
691
692/*
693  Set the current file of the zipfile to the first file.
694  return UNZ_OK if there is no problem
695*/
696extern int ZEXPORT unzGoToFirstFile (file)
697        unzFile file;
698{
699        int err=UNZ_OK;
700        unz_s* s;
701        if (file==NULL)
702                return UNZ_PARAMERROR;
703        s=(unz_s*)file;
704        s->pos_in_central_dir=s->offset_central_dir;
705        s->num_file=0;
706        err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
707                                                                                         &s->cur_file_info_internal,
708                                                                                         NULL,0,NULL,0,NULL,0);
709        s->current_file_ok = (err == UNZ_OK);
710        return err;
711}
712
713
714/*
715  Set the current file of the zipfile to the next file.
716  return UNZ_OK if there is no problem
717  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
718*/
719extern int ZEXPORT unzGoToNextFile (file)
720        unzFile file;
721{
722        unz_s* s;       
723        int err;
724
725        if (file==NULL)
726                return UNZ_PARAMERROR;
727        s=(unz_s*)file;
728        if (!s->current_file_ok)
729                return UNZ_END_OF_LIST_OF_FILE;
730        if (s->num_file+1==s->gi.number_entry)
731                return UNZ_END_OF_LIST_OF_FILE;
732
733        s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
734                        s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
735        s->num_file++;
736        err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
737                                                                                           &s->cur_file_info_internal,
738                                                                                           NULL,0,NULL,0,NULL,0);
739        s->current_file_ok = (err == UNZ_OK);
740        return err;
741}
742
743
744/*
745  Try locate the file szFileName in the zipfile.
746  For the iCaseSensitivity signification, see unzipStringFileNameCompare
747
748  return value :
749  UNZ_OK if the file is found. It becomes the current file.
750  UNZ_END_OF_LIST_OF_FILE if the file is not found
751*/
752extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
753        unzFile file;
754        const char *szFileName;
755        int iCaseSensitivity;
756{
757        unz_s* s;       
758        int err;
759
760       
761        uLong num_fileSaved;
762        uLong pos_in_central_dirSaved;
763
764
765        if (file==NULL)
766                return UNZ_PARAMERROR;
767
768    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
769        return UNZ_PARAMERROR;
770
771        s=(unz_s*)file;
772        if (!s->current_file_ok)
773                return UNZ_END_OF_LIST_OF_FILE;
774
775        num_fileSaved = s->num_file;
776        pos_in_central_dirSaved = s->pos_in_central_dir;
777
778        err = unzGoToFirstFile(file);
779
780        while (err == UNZ_OK)
781        {
782                char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
783                unzGetCurrentFileInfo(file,NULL,
784                                                                szCurrentFileName,sizeof(szCurrentFileName)-1,
785                                                                NULL,0,NULL,0);
786                if (unzStringFileNameCompare(szCurrentFileName,
787                                                                                szFileName,iCaseSensitivity)==0)
788                        return UNZ_OK;
789                err = unzGoToNextFile(file);
790        }
791
792        s->num_file = num_fileSaved ;
793        s->pos_in_central_dir = pos_in_central_dirSaved ;
794        return err;
795}
796
797
798/*
799  Read the local header of the current zipfile
800  Check the coherency of the local header and info in the end of central
801        directory about this file
802  store in *piSizeVar the size of extra info in local header
803        (filename and size of extra field data)
804*/
805local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
806                                                                                                        poffset_local_extrafield,
807                                                                                                        psize_local_extrafield)
808        unz_s* s;
809        uInt* piSizeVar;
810        uLong *poffset_local_extrafield;
811        uInt  *psize_local_extrafield;
812{
813        uLong uMagic,uData,uFlags;
814        uLong size_filename;
815        uLong size_extra_field;
816        int err=UNZ_OK;
817
818        *piSizeVar = 0;
819        *poffset_local_extrafield = 0;
820        *psize_local_extrafield = 0;
821
822        if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
823                                                                s->byte_before_the_zipfile,SEEK_SET)!=0)
824                return UNZ_ERRNO;
825
826
827        if (err==UNZ_OK)
828                if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
829                        err=UNZ_ERRNO;
830                else if (uMagic!=0x04034b50)
831                        err=UNZ_BADZIPFILE;
832
833        if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
834                err=UNZ_ERRNO;
835/*
836        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
837                err=UNZ_BADZIPFILE;
838*/
839        if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
840                err=UNZ_ERRNO;
841
842        if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
843                err=UNZ_ERRNO;
844        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
845                err=UNZ_BADZIPFILE;
846
847    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
848                         (s->cur_file_info.compression_method!=Z_DEFLATED))
849        err=UNZ_BADZIPFILE;
850
851        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
852                err=UNZ_ERRNO;
853
854        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
855                err=UNZ_ERRNO;
856        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
857                                      ((uFlags & 8)==0))
858                err=UNZ_BADZIPFILE;
859
860        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
861                err=UNZ_ERRNO;
862        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
863                                                          ((uFlags & 8)==0))
864                err=UNZ_BADZIPFILE;
865
866        if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
867                err=UNZ_ERRNO;
868        else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
869                                                          ((uFlags & 8)==0))
870                err=UNZ_BADZIPFILE;
871
872
873        if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
874                err=UNZ_ERRNO;
875        else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
876                err=UNZ_BADZIPFILE;
877
878        *piSizeVar += (uInt)size_filename;
879
880        if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
881                err=UNZ_ERRNO;
882        *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
883                                                                        SIZEZIPLOCALHEADER + size_filename;
884        *psize_local_extrafield = (uInt)size_extra_field;
885
886        *piSizeVar += (uInt)size_extra_field;
887
888        return err;
889}
890                                                                                               
891/*
892  Open for reading data the current file in the zipfile.
893  If there is no error and the file is opened, the return value is UNZ_OK.
894*/
895extern int ZEXPORT unzOpenCurrentFile (file)
896        unzFile file;
897{
898        int err=UNZ_OK;
899        int Store;
900        uInt iSizeVar;
901        unz_s* s;
902        file_in_zip_read_info_s* pfile_in_zip_read_info;
903        uLong offset_local_extrafield;  /* offset of the local extra field */
904        uInt  size_local_extrafield;    /* size of the local extra field */
905
906        if (file==NULL)
907                return UNZ_PARAMERROR;
908        s=(unz_s*)file;
909        if (!s->current_file_ok)
910                return UNZ_PARAMERROR;
911
912    if (s->pfile_in_zip_read != NULL)
913        unzCloseCurrentFile(file);
914
915        if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
916                                &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
917                return UNZ_BADZIPFILE;
918
919        pfile_in_zip_read_info = (file_in_zip_read_info_s*)
920                                                                            ALLOC(sizeof(file_in_zip_read_info_s));
921        if (pfile_in_zip_read_info==NULL)
922                return UNZ_INTERNALERROR;
923
924        pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
925        pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
926        pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
927        pfile_in_zip_read_info->pos_local_extrafield=0;
928
929        if (pfile_in_zip_read_info->read_buffer==NULL)
930        {
931                TRYFREE(pfile_in_zip_read_info);
932                return UNZ_INTERNALERROR;
933        }
934
935        pfile_in_zip_read_info->stream_initialised=0;
936       
937        if ((s->cur_file_info.compression_method!=0) &&
938        (s->cur_file_info.compression_method!=Z_DEFLATED))
939                err=UNZ_BADZIPFILE;
940        Store = s->cur_file_info.compression_method==0;
941
942        pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
943        pfile_in_zip_read_info->crc32=0;
944        pfile_in_zip_read_info->compression_method =
945            s->cur_file_info.compression_method;
946        pfile_in_zip_read_info->file=s->file;
947        pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
948
949    pfile_in_zip_read_info->stream.total_out = 0;
950
951        if (!Store)
952        {
953          pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
954          pfile_in_zip_read_info->stream.zfree = (free_func)0;
955          pfile_in_zip_read_info->stream.opaque = (voidpf)0;
956     
957          err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
958          if (err == Z_OK)
959            pfile_in_zip_read_info->stream_initialised=1;
960        /* windowBits is passed < 0 to tell that there is no zlib header.
961         * Note that in this case inflate *requires* an extra "dummy" byte
962         * after the compressed stream in order to complete decompression and
963         * return Z_STREAM_END.
964         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
965         * size of both compressed and uncompressed data
966         */
967        }
968        pfile_in_zip_read_info->rest_read_compressed =
969            s->cur_file_info.compressed_size ;
970        pfile_in_zip_read_info->rest_read_uncompressed =
971            s->cur_file_info.uncompressed_size ;
972
973       
974        pfile_in_zip_read_info->pos_in_zipfile =
975            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
976                          iSizeVar;
977       
978        pfile_in_zip_read_info->stream.avail_in = (uInt)0;
979
980
981        s->pfile_in_zip_read = pfile_in_zip_read_info;
982    return UNZ_OK;
983}
984
985
986/*
987  Read bytes from the current file.
988  buf contain buffer where data must be copied
989  len the size of buf.
990
991  return the number of byte copied if somes bytes are copied
992  return 0 if the end of file was reached
993  return <0 with error code if there is an error
994    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
995*/
996extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
997        unzFile file;
998        voidp buf;
999        unsigned len;
1000{
1001        int err=UNZ_OK;
1002        uInt iRead = 0;
1003        unz_s* s;
1004        file_in_zip_read_info_s* pfile_in_zip_read_info;
1005        if (file==NULL)
1006                return UNZ_PARAMERROR;
1007        s=(unz_s*)file;
1008    pfile_in_zip_read_info=s->pfile_in_zip_read;
1009
1010        if (pfile_in_zip_read_info==NULL)
1011                return UNZ_PARAMERROR;
1012
1013
1014        if ((pfile_in_zip_read_info->read_buffer == NULL))
1015                return UNZ_END_OF_LIST_OF_FILE;
1016        if (len==0)
1017                return 0;
1018
1019        pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1020
1021        pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1022       
1023        if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1024                pfile_in_zip_read_info->stream.avail_out =
1025                  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1026
1027        while (pfile_in_zip_read_info->stream.avail_out>0)
1028        {
1029                if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1030            (pfile_in_zip_read_info->rest_read_compressed>0))
1031                {
1032                        uInt uReadThis = UNZ_BUFSIZE;
1033                        if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1034                                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1035                        if (uReadThis == 0)
1036                                return UNZ_EOF;
1037                        if (fseek(pfile_in_zip_read_info->file,
1038                      pfile_in_zip_read_info->pos_in_zipfile +
1039                         pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1040                                return UNZ_ERRNO;
1041                        if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1042                         pfile_in_zip_read_info->file)!=1)
1043                                return UNZ_ERRNO;
1044                        pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1045
1046                        pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1047                       
1048                        pfile_in_zip_read_info->stream.next_in =
1049                (Bytef*)pfile_in_zip_read_info->read_buffer;
1050                        pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1051                }
1052
1053                if (pfile_in_zip_read_info->compression_method==0)
1054                {
1055                        uInt uDoCopy,i ;
1056                        if (pfile_in_zip_read_info->stream.avail_out <
1057                            pfile_in_zip_read_info->stream.avail_in)
1058                                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1059                        else
1060                                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1061                               
1062                        for (i=0;i<uDoCopy;i++)
1063                                *(pfile_in_zip_read_info->stream.next_out+i) =
1064                        *(pfile_in_zip_read_info->stream.next_in+i);
1065                                       
1066                        pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1067                                                                pfile_in_zip_read_info->stream.next_out,
1068                                                                uDoCopy);
1069                        pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1070                        pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1071                        pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1072                        pfile_in_zip_read_info->stream.next_out += uDoCopy;
1073                        pfile_in_zip_read_info->stream.next_in += uDoCopy;
1074            pfile_in_zip_read_info->stream.total_out += uDoCopy;
1075                        iRead += uDoCopy;
1076                }
1077                else
1078                {
1079                        uLong uTotalOutBefore,uTotalOutAfter;
1080                        const Bytef *bufBefore;
1081                        uLong uOutThis;
1082                        int flush=Z_SYNC_FLUSH;
1083
1084                        uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1085                        bufBefore = pfile_in_zip_read_info->stream.next_out;
1086
1087                        /*
1088                        if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1089                                 pfile_in_zip_read_info->stream.avail_out) &&
1090                                (pfile_in_zip_read_info->rest_read_compressed == 0))
1091                                flush = Z_FINISH;
1092                        */
1093                        err=inflate(&pfile_in_zip_read_info->stream,flush);
1094
1095                        uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1096                        uOutThis = uTotalOutAfter-uTotalOutBefore;
1097                       
1098                        pfile_in_zip_read_info->crc32 =
1099                crc32(pfile_in_zip_read_info->crc32,bufBefore,
1100                        (uInt)(uOutThis));
1101
1102                        pfile_in_zip_read_info->rest_read_uncompressed -=
1103                uOutThis;
1104
1105                        iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1106           
1107                        if (err==Z_STREAM_END)
1108                                return (iRead==0) ? UNZ_EOF : iRead;
1109                        if (err!=Z_OK)
1110                                break;
1111                }
1112        }
1113
1114        if (err==Z_OK)
1115                return iRead;
1116        return err;
1117}
1118
1119
1120/*
1121  Give the current position in uncompressed data
1122*/
1123extern z_off_t ZEXPORT unztell (file)
1124        unzFile file;
1125{
1126        unz_s* s;
1127        file_in_zip_read_info_s* pfile_in_zip_read_info;
1128        if (file==NULL)
1129                return UNZ_PARAMERROR;
1130        s=(unz_s*)file;
1131    pfile_in_zip_read_info=s->pfile_in_zip_read;
1132
1133        if (pfile_in_zip_read_info==NULL)
1134                return UNZ_PARAMERROR;
1135
1136        return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1137}
1138
1139
1140/*
1141  return 1 if the end of file was reached, 0 elsewhere
1142*/
1143extern int ZEXPORT unzeof (file)
1144        unzFile file;
1145{
1146        unz_s* s;
1147        file_in_zip_read_info_s* pfile_in_zip_read_info;
1148        if (file==NULL)
1149                return UNZ_PARAMERROR;
1150        s=(unz_s*)file;
1151    pfile_in_zip_read_info=s->pfile_in_zip_read;
1152
1153        if (pfile_in_zip_read_info==NULL)
1154                return UNZ_PARAMERROR;
1155       
1156        if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1157                return 1;
1158        else
1159                return 0;
1160}
1161
1162
1163
1164/*
1165  Read extra field from the current file (opened by unzOpenCurrentFile)
1166  This is the local-header version of the extra field (sometimes, there is
1167    more info in the local-header version than in the central-header)
1168
1169  if buf==NULL, it return the size of the local extra field that can be read
1170
1171  if buf!=NULL, len is the size of the buffer, the extra header is copied in
1172        buf.
1173  the return value is the number of bytes copied in buf, or (if <0)
1174        the error code
1175*/
1176extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1177        unzFile file;
1178        voidp buf;
1179        unsigned len;
1180{
1181        unz_s* s;
1182        file_in_zip_read_info_s* pfile_in_zip_read_info;
1183        uInt read_now;
1184        uLong size_to_read;
1185
1186        if (file==NULL)
1187                return UNZ_PARAMERROR;
1188        s=(unz_s*)file;
1189    pfile_in_zip_read_info=s->pfile_in_zip_read;
1190
1191        if (pfile_in_zip_read_info==NULL)
1192                return UNZ_PARAMERROR;
1193
1194        size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1195                                pfile_in_zip_read_info->pos_local_extrafield);
1196
1197        if (buf==NULL)
1198                return (int)size_to_read;
1199       
1200        if (len>size_to_read)
1201                read_now = (uInt)size_to_read;
1202        else
1203                read_now = (uInt)len ;
1204
1205        if (read_now==0)
1206                return 0;
1207       
1208        if (fseek(pfile_in_zip_read_info->file,
1209              pfile_in_zip_read_info->offset_local_extrafield +
1210                          pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1211                return UNZ_ERRNO;
1212
1213        if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1214                return UNZ_ERRNO;
1215
1216        return (int)read_now;
1217}
1218
1219/*
1220  Close the file in zip opened with unzipOpenCurrentFile
1221  Return UNZ_CRCERROR if all the file was read but the CRC is not good
1222*/
1223extern int ZEXPORT unzCloseCurrentFile (file)
1224        unzFile file;
1225{
1226        int err=UNZ_OK;
1227
1228        unz_s* s;
1229        file_in_zip_read_info_s* pfile_in_zip_read_info;
1230        if (file==NULL)
1231                return UNZ_PARAMERROR;
1232        s=(unz_s*)file;
1233    pfile_in_zip_read_info=s->pfile_in_zip_read;
1234
1235        if (pfile_in_zip_read_info==NULL)
1236                return UNZ_PARAMERROR;
1237
1238
1239        if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1240        {
1241                if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1242                        err=UNZ_CRCERROR;
1243        }
1244
1245
1246        TRYFREE(pfile_in_zip_read_info->read_buffer);
1247        pfile_in_zip_read_info->read_buffer = NULL;
1248        if (pfile_in_zip_read_info->stream_initialised)
1249                inflateEnd(&pfile_in_zip_read_info->stream);
1250
1251        pfile_in_zip_read_info->stream_initialised = 0;
1252        TRYFREE(pfile_in_zip_read_info);
1253
1254    s->pfile_in_zip_read=NULL;
1255
1256        return err;
1257}
1258
1259
1260/*
1261  Get the global comment string of the ZipFile, in the szComment buffer.
1262  uSizeBuf is the size of the szComment buffer.
1263  return the number of byte copied or an error code <0
1264*/
1265extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1266        unzFile file;
1267        char *szComment;
1268        uLong uSizeBuf;
1269{
1270        int err=UNZ_OK;
1271        unz_s* s;
1272        uLong uReadThis ;
1273        if (file==NULL)
1274                return UNZ_PARAMERROR;
1275        s=(unz_s*)file;
1276
1277        uReadThis = uSizeBuf;
1278        if (uReadThis>s->gi.size_comment)
1279                uReadThis = s->gi.size_comment;
1280
1281        if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1282                return UNZ_ERRNO;
1283
1284        if (uReadThis>0)
1285    {
1286      *szComment='\0';
1287          if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1288                return UNZ_ERRNO;
1289    }
1290
1291        if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1292                *(szComment+s->gi.size_comment)='\0';
1293        return (int)uReadThis;
1294}
Note: See TracBrowser for help on using the repository browser.