1 /* $NetBSD: zip.c,v 1.1.1.1 2006/01/14 20:11:00 christos Exp $ */
3 /* zip.c -- IO on .zip files using zlib
4 Version 1.01e, February 12th, 2005
6 27 Dec 2004 Rolf Kalbermatter
7 Modification to zipOpen2 to support globalComment retrieval.
9 Copyright (C) 1998-2005 Gilles Vollant
11 Read zip.h for more info
37 /* compile with -Dlocal if your debugger can't find static symbols */
40 # define VERSIONMADEBY (0x0) /* platform depedent */
44 #define Z_BUFSIZE (16384)
47 #ifndef Z_MAXFILENAMEINZIP
48 #define Z_MAXFILENAMEINZIP (256)
52 # define ALLOC(size) (malloc(size))
55 # define TRYFREE(p) {if (p) free(p);}
59 #define SIZECENTRALDIRITEM (0x2e)
60 #define SIZEZIPLOCALHEADER (0x1e)
63 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
78 #if MAX_MEM_LEVEL >= 8
79 # define DEF_MEM_LEVEL 8
81 # define DEF_MEM_LEVEL MAX_MEM_LEVEL
84 const char zip_copyright
[] =
85 " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
88 #define SIZEDATA_INDATABLOCK (4096-(4*4))
90 #define LOCALHEADERMAGIC (0x04034b50)
91 #define CENTRALHEADERMAGIC (0x02014b50)
92 #define ENDHEADERMAGIC (0x06054b50)
94 #define FLAG_LOCALHEADER_OFFSET (0x06)
95 #define CRC_LOCALHEADER_OFFSET (0x0e)
97 #define SIZECENTRALHEADER (0x2e) /* 46 */
99 typedef struct linkedlist_datablock_internal_s
101 struct linkedlist_datablock_internal_s
* next_datablock
;
102 uLong avail_in_this_block
;
103 uLong filled_in_this_block
;
104 uLong unused
; /* for future use and alignement */
105 unsigned char data
[SIZEDATA_INDATABLOCK
];
106 } linkedlist_datablock_internal
;
108 typedef struct linkedlist_data_s
110 linkedlist_datablock_internal
* first_block
;
111 linkedlist_datablock_internal
* last_block
;
117 z_stream stream
; /* zLib stream structure for inflate */
118 int stream_initialised
; /* 1 is stream is initialised */
119 uInt pos_in_buffered_data
; /* last written byte in buffered_data */
121 uLong pos_local_header
; /* offset of the local header of the file
123 char* central_header
; /* central header data for the current file */
124 uLong size_centralheader
; /* size of the central header for cur file */
125 uLong flag
; /* flag of the file currently writing */
127 int method
; /* compression method of file currenty wr.*/
128 int raw
; /* 1 for directly writing raw data */
129 Byte buffered_data
[Z_BUFSIZE
];/* buffer contain compressed data to be writ*/
134 unsigned long keys
[3]; /* keys defining the pseudo-random sequence */
135 const unsigned long* pcrc_32_tab
;
136 int crypt_header_size
;
142 zlib_filefunc_def z_filefunc
;
143 voidpf filestream
; /* io structore of the zipfile */
144 linkedlist_data central_dir
;/* datablock with central dir in construction*/
145 int in_opened_file_inzip
; /* 1 if a file in the zip is currently writ.*/
146 curfile_info ci
; /* info on the file curretly writing */
148 uLong begin_pos
; /* position of the beginning of the zipfile */
149 uLong add_position_when_writting_offset
;
151 #ifndef NO_ADDFILEINEXISTINGZIP
159 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
163 local linkedlist_datablock_internal
* allocate_new_datablock()
165 linkedlist_datablock_internal
* ldi
;
166 ldi
= (linkedlist_datablock_internal
*)
167 ALLOC(sizeof(linkedlist_datablock_internal
));
170 ldi
->next_datablock
= NULL
;
171 ldi
->filled_in_this_block
= 0 ;
172 ldi
->avail_in_this_block
= SIZEDATA_INDATABLOCK
;
177 local
void free_datablock(ldi
)
178 linkedlist_datablock_internal
* ldi
;
182 linkedlist_datablock_internal
* ldinext
= ldi
->next_datablock
;
188 local
void init_linkedlist(ll
)
191 ll
->first_block
= ll
->last_block
= NULL
;
194 local
void free_linkedlist(ll
)
197 free_datablock(ll
->first_block
);
198 ll
->first_block
= ll
->last_block
= NULL
;
202 local
int add_data_in_datablock(ll
,buf
,len
)
207 linkedlist_datablock_internal
* ldi
;
208 const unsigned char* from_copy
;
211 return ZIP_INTERNALERROR
;
213 if (ll
->last_block
== NULL
)
215 ll
->first_block
= ll
->last_block
= allocate_new_datablock();
216 if (ll
->first_block
== NULL
)
217 return ZIP_INTERNALERROR
;
220 ldi
= ll
->last_block
;
221 from_copy
= (unsigned char*)buf
;
227 unsigned char* to_copy
;
229 if (ldi
->avail_in_this_block
==0)
231 ldi
->next_datablock
= allocate_new_datablock();
232 if (ldi
->next_datablock
== NULL
)
233 return ZIP_INTERNALERROR
;
234 ldi
= ldi
->next_datablock
;
235 ll
->last_block
= ldi
;
238 if (ldi
->avail_in_this_block
< len
)
239 copy_this
= (uInt
)ldi
->avail_in_this_block
;
241 copy_this
= (uInt
)len
;
243 to_copy
= &(ldi
->data
[ldi
->filled_in_this_block
]);
245 for (i
=0;i
<copy_this
;i
++)
246 *(to_copy
+i
)=*(from_copy
+i
);
248 ldi
->filled_in_this_block
+= copy_this
;
249 ldi
->avail_in_this_block
-= copy_this
;
250 from_copy
+= copy_this
;
258 /****************************************************************************/
260 #ifndef NO_ADDFILEINEXISTINGZIP
261 /* ===========================================================================
262 Inputs a long in LSB order to the given file
263 nbByte == 1, 2 or 4 (byte, short or long)
266 local
int ziplocal_putValue
OF((const zlib_filefunc_def
* pzlib_filefunc_def
,
267 voidpf filestream
, uLong x
, int nbByte
));
268 local
int ziplocal_putValue (pzlib_filefunc_def
, filestream
, x
, nbByte
)
269 const zlib_filefunc_def
* pzlib_filefunc_def
;
274 unsigned char buf
[4];
276 for (n
= 0; n
< nbByte
; n
++)
278 buf
[n
] = (unsigned char)(x
& 0xff);
282 { /* data overflow - hack for ZIP64 (X Roche) */
283 for (n
= 0; n
< nbByte
; n
++)
289 if (ZWRITE(*pzlib_filefunc_def
,filestream
,buf
,nbByte
)!=(uLong
)nbByte
)
295 local
void ziplocal_putValue_inmemory
OF((void* dest
, uLong x
, int nbByte
));
296 local
void ziplocal_putValue_inmemory (dest
, x
, nbByte
)
301 unsigned char* buf
=(unsigned char*)dest
;
303 for (n
= 0; n
< nbByte
; n
++) {
304 buf
[n
] = (unsigned char)(x
& 0xff);
309 { /* data overflow - hack for ZIP64 */
310 for (n
= 0; n
< nbByte
; n
++)
317 /****************************************************************************/
320 local uLong
ziplocal_TmzDateToDosDate(ptm
,dosDate
)
324 uLong year
= (uLong
)ptm
->tm_year
;
330 (uLong
) (((ptm
->tm_mday
) + (32 * (ptm
->tm_mon
+1)) + (512 * year
)) << 16) |
331 ((ptm
->tm_sec
/2) + (32* ptm
->tm_min
) + (2048 * (uLong
)ptm
->tm_hour
));
335 /****************************************************************************/
337 local
int ziplocal_getByte
OF((
338 const zlib_filefunc_def
* pzlib_filefunc_def
,
342 local
int ziplocal_getByte(pzlib_filefunc_def
,filestream
,pi
)
343 const zlib_filefunc_def
* pzlib_filefunc_def
;
348 int err
= (int)ZREAD(*pzlib_filefunc_def
,filestream
,&c
,1);
356 if (ZERROR(*pzlib_filefunc_def
,filestream
))
364 /* ===========================================================================
365 Reads a long in LSB order from the given gz_stream. Sets
367 local
int ziplocal_getShort
OF((
368 const zlib_filefunc_def
* pzlib_filefunc_def
,
372 local
int ziplocal_getShort (pzlib_filefunc_def
,filestream
,pX
)
373 const zlib_filefunc_def
* pzlib_filefunc_def
;
381 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
385 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
395 local
int ziplocal_getLong
OF((
396 const zlib_filefunc_def
* pzlib_filefunc_def
,
400 local
int ziplocal_getLong (pzlib_filefunc_def
,filestream
,pX
)
401 const zlib_filefunc_def
* pzlib_filefunc_def
;
409 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
413 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
417 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
421 err
= ziplocal_getByte(pzlib_filefunc_def
,filestream
,&i
);
431 #ifndef BUFREADCOMMENT
432 #define BUFREADCOMMENT (0x400)
435 Locate the Central directory of a zipfile (at the end, just before
438 local uLong ziplocal_SearchCentralDir
OF((
439 const zlib_filefunc_def
* pzlib_filefunc_def
,
442 local uLong
ziplocal_SearchCentralDir(pzlib_filefunc_def
,filestream
)
443 const zlib_filefunc_def
* pzlib_filefunc_def
;
449 uLong uMaxBack
=0xffff; /* maximum size of global comment */
452 if (ZSEEK(*pzlib_filefunc_def
,filestream
,0,ZLIB_FILEFUNC_SEEK_END
) != 0)
456 uSizeFile
= ZTELL(*pzlib_filefunc_def
,filestream
);
458 if (uMaxBack
>uSizeFile
)
459 uMaxBack
= uSizeFile
;
461 buf
= (unsigned char*)ALLOC(BUFREADCOMMENT
+4);
466 while (uBackRead
<uMaxBack
)
468 uLong uReadSize
,uReadPos
;
470 if (uBackRead
+BUFREADCOMMENT
>uMaxBack
)
471 uBackRead
= uMaxBack
;
473 uBackRead
+=BUFREADCOMMENT
;
474 uReadPos
= uSizeFile
-uBackRead
;
476 uReadSize
= ((BUFREADCOMMENT
+4) < (uSizeFile
-uReadPos
)) ?
477 (BUFREADCOMMENT
+4) : (uSizeFile
-uReadPos
);
478 if (ZSEEK(*pzlib_filefunc_def
,filestream
,uReadPos
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
481 if (ZREAD(*pzlib_filefunc_def
,filestream
,buf
,uReadSize
)!=uReadSize
)
484 for (i
=(int)uReadSize
-3; (i
--)>0;)
485 if (((*(buf
+i
))==0x50) && ((*(buf
+i
+1))==0x4b) &&
486 ((*(buf
+i
+2))==0x05) && ((*(buf
+i
+3))==0x06))
488 uPosFound
= uReadPos
+i
;
498 #endif /* !NO_ADDFILEINEXISTINGZIP*/
500 /************************************************************/
501 extern zipFile ZEXPORT
zipOpen2 (pathname
, append
, globalcomment
, pzlib_filefunc_def
)
502 const char *pathname
;
504 zipcharpc
* globalcomment
;
505 zlib_filefunc_def
* pzlib_filefunc_def
;
512 if (pzlib_filefunc_def
==NULL
)
513 fill_fopen_filefunc(&ziinit
.z_filefunc
);
515 ziinit
.z_filefunc
= *pzlib_filefunc_def
;
517 ziinit
.filestream
= (*(ziinit
.z_filefunc
.zopen_file
))
518 (ziinit
.z_filefunc
.opaque
,
520 (append
== APPEND_STATUS_CREATE
) ?
521 (ZLIB_FILEFUNC_MODE_READ
| ZLIB_FILEFUNC_MODE_WRITE
| ZLIB_FILEFUNC_MODE_CREATE
) :
522 (ZLIB_FILEFUNC_MODE_READ
| ZLIB_FILEFUNC_MODE_WRITE
| ZLIB_FILEFUNC_MODE_EXISTING
));
524 if (ziinit
.filestream
== NULL
)
526 ziinit
.begin_pos
= ZTELL(ziinit
.z_filefunc
,ziinit
.filestream
);
527 ziinit
.in_opened_file_inzip
= 0;
528 ziinit
.ci
.stream_initialised
= 0;
529 ziinit
.number_entry
= 0;
530 ziinit
.add_position_when_writting_offset
= 0;
531 init_linkedlist(&(ziinit
.central_dir
));
534 zi
= (zip_internal
*)ALLOC(sizeof(zip_internal
));
537 ZCLOSE(ziinit
.z_filefunc
,ziinit
.filestream
);
541 /* now we add file in a zipfile */
542 # ifndef NO_ADDFILEINEXISTINGZIP
543 ziinit
.globalcomment
= NULL
;
544 if (append
== APPEND_STATUS_ADDINZIP
)
546 uLong byte_before_the_zipfile
;/* byte before the zipfile, (>0 for sfx)*/
548 uLong size_central_dir
; /* size of the central directory */
549 uLong offset_central_dir
; /* offset of start of central directory */
550 uLong central_pos
,uL
;
552 uLong number_disk
; /* number of the current dist, used for
553 spaning ZIP, unsupported, always 0*/
554 uLong number_disk_with_CD
; /* number the the disk with central dir, used
555 for spaning ZIP, unsupported, always 0*/
557 uLong number_entry_CD
; /* total number of entries in
559 (same than number_entry on nospan) */
562 central_pos
= ziplocal_SearchCentralDir(&ziinit
.z_filefunc
,ziinit
.filestream
);
566 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
567 central_pos
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
570 /* the signature, already checked */
571 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&uL
)!=ZIP_OK
)
574 /* number of this disk */
575 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_disk
)!=ZIP_OK
)
578 /* number of the disk with the start of the central directory */
579 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_disk_with_CD
)!=ZIP_OK
)
582 /* total number of entries in the central dir on this disk */
583 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_entry
)!=ZIP_OK
)
586 /* total number of entries in the central dir */
587 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&number_entry_CD
)!=ZIP_OK
)
590 if ((number_entry_CD
!=number_entry
) ||
591 (number_disk_with_CD
!=0) ||
595 /* size of the central directory */
596 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_central_dir
)!=ZIP_OK
)
599 /* offset of start of central directory with respect to the
600 starting disk number */
601 if (ziplocal_getLong(&ziinit
.z_filefunc
, ziinit
.filestream
,&offset_central_dir
)!=ZIP_OK
)
604 /* zipfile global comment length */
605 if (ziplocal_getShort(&ziinit
.z_filefunc
, ziinit
.filestream
,&size_comment
)!=ZIP_OK
)
608 if ((central_pos
<offset_central_dir
+size_central_dir
) &&
614 ZCLOSE(ziinit
.z_filefunc
, ziinit
.filestream
);
620 ziinit
.globalcomment
= ALLOC(size_comment
+1);
621 if (ziinit
.globalcomment
)
623 size_comment
= ZREAD(ziinit
.z_filefunc
, ziinit
.filestream
,ziinit
.globalcomment
,size_comment
);
624 ziinit
.globalcomment
[size_comment
]=0;
628 byte_before_the_zipfile
= central_pos
-
629 (offset_central_dir
+size_central_dir
);
630 ziinit
.add_position_when_writting_offset
= byte_before_the_zipfile
;
633 uLong size_central_dir_to_read
= size_central_dir
;
634 size_t buf_size
= SIZEDATA_INDATABLOCK
;
635 void* buf_read
= (void*)ALLOC(buf_size
);
636 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
637 offset_central_dir
+ byte_before_the_zipfile
,
638 ZLIB_FILEFUNC_SEEK_SET
) != 0)
641 while ((size_central_dir_to_read
>0) && (err
==ZIP_OK
))
643 uLong read_this
= SIZEDATA_INDATABLOCK
;
644 if (read_this
> size_central_dir_to_read
)
645 read_this
= size_central_dir_to_read
;
646 if (ZREAD(ziinit
.z_filefunc
, ziinit
.filestream
,buf_read
,read_this
) != read_this
)
650 err
= add_data_in_datablock(&ziinit
.central_dir
,buf_read
,
652 size_central_dir_to_read
-=read_this
;
656 ziinit
.begin_pos
= byte_before_the_zipfile
;
657 ziinit
.number_entry
= number_entry_CD
;
659 if (ZSEEK(ziinit
.z_filefunc
, ziinit
.filestream
,
660 offset_central_dir
+byte_before_the_zipfile
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
666 *globalcomment
= ziinit
.globalcomment
;
668 # endif /* !NO_ADDFILEINEXISTINGZIP*/
672 # ifndef NO_ADDFILEINEXISTINGZIP
673 TRYFREE(ziinit
.globalcomment
);
674 # endif /* !NO_ADDFILEINEXISTINGZIP*/
685 extern zipFile ZEXPORT
zipOpen (pathname
, append
)
686 const char *pathname
;
689 return zipOpen2(pathname
,append
,NULL
,NULL
);
692 extern int ZEXPORT
zipOpenNewFileInZip3 (file
, filename
, zipfi
,
693 extrafield_local
, size_extrafield_local
,
694 extrafield_global
, size_extrafield_global
,
695 comment
, method
, level
, raw
,
696 windowBits
, memLevel
, strategy
,
697 password
, crcForCrypting
)
699 const char* filename
;
700 const zip_fileinfo
* zipfi
;
701 const void* extrafield_local
;
702 uInt size_extrafield_local
;
703 const void* extrafield_global
;
704 uInt size_extrafield_global
;
712 const char* password
;
713 uLong crcForCrypting
;
722 if (password
!= NULL
)
723 return ZIP_PARAMERROR
;
727 return ZIP_PARAMERROR
;
728 if ((method
!=0) && (method
!=Z_DEFLATED
))
729 return ZIP_PARAMERROR
;
731 zi
= (zip_internal
*)file
;
733 if (zi
->in_opened_file_inzip
== 1)
735 err
= zipCloseFileInZip (file
);
747 size_comment
= (uInt
)strlen(comment
);
749 size_filename
= (uInt
)strlen(filename
);
755 if (zipfi
->dosDate
!= 0)
756 zi
->ci
.dosDate
= zipfi
->dosDate
;
757 else zi
->ci
.dosDate
= ziplocal_TmzDateToDosDate(&zipfi
->tmz_date
,zipfi
->dosDate
);
761 if ((level
==8) || (level
==9))
767 if (password
!= NULL
)
771 zi
->ci
.method
= method
;
773 zi
->ci
.stream_initialised
= 0;
774 zi
->ci
.pos_in_buffered_data
= 0;
776 zi
->ci
.pos_local_header
= ZTELL(zi
->z_filefunc
,zi
->filestream
) ;
777 zi
->ci
.size_centralheader
= SIZECENTRALHEADER
+ size_filename
+
778 size_extrafield_global
+ size_comment
;
779 zi
->ci
.central_header
= (char*)ALLOC((uInt
)zi
->ci
.size_centralheader
);
781 ziplocal_putValue_inmemory(zi
->ci
.central_header
,(uLong
)CENTRALHEADERMAGIC
,4);
783 ziplocal_putValue_inmemory(zi
->ci
.central_header
+4,(uLong
)VERSIONMADEBY
,2);
784 ziplocal_putValue_inmemory(zi
->ci
.central_header
+6,(uLong
)20,2);
785 ziplocal_putValue_inmemory(zi
->ci
.central_header
+8,(uLong
)zi
->ci
.flag
,2);
786 ziplocal_putValue_inmemory(zi
->ci
.central_header
+10,(uLong
)zi
->ci
.method
,2);
787 ziplocal_putValue_inmemory(zi
->ci
.central_header
+12,(uLong
)zi
->ci
.dosDate
,4);
788 ziplocal_putValue_inmemory(zi
->ci
.central_header
+16,(uLong
)0,4); /*crc*/
789 ziplocal_putValue_inmemory(zi
->ci
.central_header
+20,(uLong
)0,4); /*compr size*/
790 ziplocal_putValue_inmemory(zi
->ci
.central_header
+24,(uLong
)0,4); /*uncompr size*/
791 ziplocal_putValue_inmemory(zi
->ci
.central_header
+28,(uLong
)size_filename
,2);
792 ziplocal_putValue_inmemory(zi
->ci
.central_header
+30,(uLong
)size_extrafield_global
,2);
793 ziplocal_putValue_inmemory(zi
->ci
.central_header
+32,(uLong
)size_comment
,2);
794 ziplocal_putValue_inmemory(zi
->ci
.central_header
+34,(uLong
)0,2); /*disk nm start*/
797 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)0,2);
799 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)zipfi
->internal_fa
,2);
802 ziplocal_putValue_inmemory(zi
->ci
.central_header
+38,(uLong
)0,4);
804 ziplocal_putValue_inmemory(zi
->ci
.central_header
+38,(uLong
)zipfi
->external_fa
,4);
806 ziplocal_putValue_inmemory(zi
->ci
.central_header
+42,(uLong
)zi
->ci
.pos_local_header
- zi
->add_position_when_writting_offset
,4);
808 for (i
=0;i
<size_filename
;i
++)
809 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+i
) = *(filename
+i
);
811 for (i
=0;i
<size_extrafield_global
;i
++)
812 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+size_filename
+i
) =
813 *(((const char*)extrafield_global
)+i
);
815 for (i
=0;i
<size_comment
;i
++)
816 *(zi
->ci
.central_header
+SIZECENTRALHEADER
+size_filename
+
817 size_extrafield_global
+i
) = *(comment
+i
);
818 if (zi
->ci
.central_header
== NULL
)
819 return ZIP_INTERNALERROR
;
821 /* write the local header */
822 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)LOCALHEADERMAGIC
,4);
825 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)20,2);/* version needed to extract */
827 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.flag
,2);
830 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.method
,2);
833 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->ci
.dosDate
,4);
836 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* crc 32, unknown */
838 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* compressed size, unknown */
840 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,4); /* uncompressed size, unknown */
843 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_filename
,2);
846 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_extrafield_local
,2);
848 if ((err
==ZIP_OK
) && (size_filename
>0))
849 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,filename
,size_filename
)!=size_filename
)
852 if ((err
==ZIP_OK
) && (size_extrafield_local
>0))
853 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,extrafield_local
,size_extrafield_local
)
854 !=size_extrafield_local
)
857 zi
->ci
.stream
.avail_in
= (uInt
)0;
858 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
859 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
860 zi
->ci
.stream
.total_in
= 0;
861 zi
->ci
.stream
.total_out
= 0;
863 if ((err
==ZIP_OK
) && (zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
865 zi
->ci
.stream
.zalloc
= (alloc_func
)0;
866 zi
->ci
.stream
.zfree
= (free_func
)0;
867 zi
->ci
.stream
.opaque
= (voidpf
)0;
870 windowBits
= -windowBits
;
872 err
= deflateInit2(&zi
->ci
.stream
, level
,
873 Z_DEFLATED
, windowBits
, memLevel
, strategy
);
876 zi
->ci
.stream_initialised
= 1;
879 zi
->ci
.crypt_header_size
= 0;
880 if ((err
==Z_OK
) && (password
!= NULL
))
882 unsigned char bufHead
[RAND_HEAD_LEN
];
883 unsigned int sizeHead
;
885 zi
->ci
.pcrc_32_tab
= get_crc_table();
886 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
888 sizeHead
=crypthead(password
,bufHead
,RAND_HEAD_LEN
,zi
->ci
.keys
,zi
->ci
.pcrc_32_tab
,crcForCrypting
);
889 zi
->ci
.crypt_header_size
= sizeHead
;
891 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,bufHead
,sizeHead
) != sizeHead
)
897 zi
->in_opened_file_inzip
= 1;
901 extern int ZEXPORT
zipOpenNewFileInZip2(file
, filename
, zipfi
,
902 extrafield_local
, size_extrafield_local
,
903 extrafield_global
, size_extrafield_global
,
904 comment
, method
, level
, raw
)
906 const char* filename
;
907 const zip_fileinfo
* zipfi
;
908 const void* extrafield_local
;
909 uInt size_extrafield_local
;
910 const void* extrafield_global
;
911 uInt size_extrafield_global
;
917 return zipOpenNewFileInZip3 (file
, filename
, zipfi
,
918 extrafield_local
, size_extrafield_local
,
919 extrafield_global
, size_extrafield_global
,
920 comment
, method
, level
, raw
,
921 -MAX_WBITS
, DEF_MEM_LEVEL
, Z_DEFAULT_STRATEGY
,
925 extern int ZEXPORT
zipOpenNewFileInZip (file
, filename
, zipfi
,
926 extrafield_local
, size_extrafield_local
,
927 extrafield_global
, size_extrafield_global
,
928 comment
, method
, level
)
930 const char* filename
;
931 const zip_fileinfo
* zipfi
;
932 const void* extrafield_local
;
933 uInt size_extrafield_local
;
934 const void* extrafield_global
;
935 uInt size_extrafield_global
;
940 return zipOpenNewFileInZip2 (file
, filename
, zipfi
,
941 extrafield_local
, size_extrafield_local
,
942 extrafield_global
, size_extrafield_global
,
943 comment
, method
, level
, 0);
946 local
int zipFlushWriteBuffer(zi
)
951 if (zi
->ci
.encrypt
!= 0)
956 for (i
=0;i
<zi
->ci
.pos_in_buffered_data
;i
++)
957 zi
->ci
.buffered_data
[i
] = zencode(zi
->ci
.keys
, zi
->ci
.pcrc_32_tab
,
958 zi
->ci
.buffered_data
[i
],t
);
961 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,zi
->ci
.buffered_data
,zi
->ci
.pos_in_buffered_data
)
962 !=zi
->ci
.pos_in_buffered_data
)
964 zi
->ci
.pos_in_buffered_data
= 0;
968 extern int ZEXPORT
zipWriteInFileInZip (file
, buf
, len
)
977 return ZIP_PARAMERROR
;
978 zi
= (zip_internal
*)file
;
980 if (zi
->in_opened_file_inzip
== 0)
981 return ZIP_PARAMERROR
;
983 zi
->ci
.stream
.next_in
= (void*)buf
;
984 zi
->ci
.stream
.avail_in
= len
;
985 zi
->ci
.crc32
= crc32(zi
->ci
.crc32
,buf
,len
);
987 while ((err
==ZIP_OK
) && (zi
->ci
.stream
.avail_in
>0))
989 if (zi
->ci
.stream
.avail_out
== 0)
991 if (zipFlushWriteBuffer(zi
) == ZIP_ERRNO
)
993 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
994 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
1001 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1003 uLong uTotalOutBefore
= zi
->ci
.stream
.total_out
;
1004 err
=deflate(&zi
->ci
.stream
, Z_NO_FLUSH
);
1005 zi
->ci
.pos_in_buffered_data
+= (uInt
)(zi
->ci
.stream
.total_out
- uTotalOutBefore
) ;
1011 if (zi
->ci
.stream
.avail_in
< zi
->ci
.stream
.avail_out
)
1012 copy_this
= zi
->ci
.stream
.avail_in
;
1014 copy_this
= zi
->ci
.stream
.avail_out
;
1015 for (i
=0;i
<copy_this
;i
++)
1016 *(((char*)zi
->ci
.stream
.next_out
)+i
) =
1017 *(((const char*)zi
->ci
.stream
.next_in
)+i
);
1019 zi
->ci
.stream
.avail_in
-= copy_this
;
1020 zi
->ci
.stream
.avail_out
-= copy_this
;
1021 zi
->ci
.stream
.next_in
+= copy_this
;
1022 zi
->ci
.stream
.next_out
+= copy_this
;
1023 zi
->ci
.stream
.total_in
+= copy_this
;
1024 zi
->ci
.stream
.total_out
+= copy_this
;
1025 zi
->ci
.pos_in_buffered_data
+= copy_this
;
1033 extern int ZEXPORT
zipCloseFileInZipRaw (file
, uncompressed_size
, crc32
)
1035 uLong uncompressed_size
;
1039 uLong compressed_size
;
1043 return ZIP_PARAMERROR
;
1044 zi
= (zip_internal
*)file
;
1046 if (zi
->in_opened_file_inzip
== 0)
1047 return ZIP_PARAMERROR
;
1048 zi
->ci
.stream
.avail_in
= 0;
1050 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1053 uLong uTotalOutBefore
;
1054 if (zi
->ci
.stream
.avail_out
== 0)
1056 if (zipFlushWriteBuffer(zi
) == ZIP_ERRNO
)
1058 zi
->ci
.stream
.avail_out
= (uInt
)Z_BUFSIZE
;
1059 zi
->ci
.stream
.next_out
= zi
->ci
.buffered_data
;
1061 uTotalOutBefore
= zi
->ci
.stream
.total_out
;
1062 err
=deflate(&zi
->ci
.stream
, Z_FINISH
);
1063 zi
->ci
.pos_in_buffered_data
+= (uInt
)(zi
->ci
.stream
.total_out
- uTotalOutBefore
) ;
1066 if (err
==Z_STREAM_END
)
1067 err
=ZIP_OK
; /* this is normal */
1069 if ((zi
->ci
.pos_in_buffered_data
>0) && (err
==ZIP_OK
))
1070 if (zipFlushWriteBuffer(zi
)==ZIP_ERRNO
)
1073 if ((zi
->ci
.method
== Z_DEFLATED
) && (!zi
->ci
.raw
))
1075 err
=deflateEnd(&zi
->ci
.stream
);
1076 zi
->ci
.stream_initialised
= 0;
1081 crc32
= (uLong
)zi
->ci
.crc32
;
1082 uncompressed_size
= (uLong
)zi
->ci
.stream
.total_in
;
1084 compressed_size
= (uLong
)zi
->ci
.stream
.total_out
;
1086 compressed_size
+= zi
->ci
.crypt_header_size
;
1089 ziplocal_putValue_inmemory(zi
->ci
.central_header
+16,crc32
,4); /*crc*/
1090 ziplocal_putValue_inmemory(zi
->ci
.central_header
+20,
1091 compressed_size
,4); /*compr size*/
1092 if (zi
->ci
.stream
.data_type
== Z_ASCII
)
1093 ziplocal_putValue_inmemory(zi
->ci
.central_header
+36,(uLong
)Z_ASCII
,2);
1094 ziplocal_putValue_inmemory(zi
->ci
.central_header
+24,
1095 uncompressed_size
,4); /*uncompr size*/
1098 err
= add_data_in_datablock(&zi
->central_dir
,zi
->ci
.central_header
,
1099 (uLong
)zi
->ci
.size_centralheader
);
1100 free(zi
->ci
.central_header
);
1104 long cur_pos_inzip
= ZTELL(zi
->z_filefunc
,zi
->filestream
);
1105 if (ZSEEK(zi
->z_filefunc
,zi
->filestream
,
1106 zi
->ci
.pos_local_header
+ 14,ZLIB_FILEFUNC_SEEK_SET
)!=0)
1110 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,crc32
,4); /* crc 32, unknown */
1112 if (err
==ZIP_OK
) /* compressed size, unknown */
1113 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,compressed_size
,4);
1115 if (err
==ZIP_OK
) /* uncompressed size, unknown */
1116 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,uncompressed_size
,4);
1118 if (ZSEEK(zi
->z_filefunc
,zi
->filestream
,
1119 cur_pos_inzip
,ZLIB_FILEFUNC_SEEK_SET
)!=0)
1123 zi
->number_entry
++;
1124 zi
->in_opened_file_inzip
= 0;
1129 extern int ZEXPORT
zipCloseFileInZip (file
)
1132 return zipCloseFileInZipRaw (file
,0,0);
1135 extern int ZEXPORT
zipClose (file
, global_comment
)
1137 const char* global_comment
;
1141 uLong size_centraldir
= 0;
1142 uLong centraldir_pos_inzip
;
1143 uInt size_global_comment
;
1145 return ZIP_PARAMERROR
;
1146 zi
= (zip_internal
*)file
;
1148 if (zi
->in_opened_file_inzip
== 1)
1150 err
= zipCloseFileInZip (file
);
1153 #ifndef NO_ADDFILEINEXISTINGZIP
1154 if (global_comment
==NULL
)
1155 global_comment
= zi
->globalcomment
;
1157 if (global_comment
==NULL
)
1158 size_global_comment
= 0;
1160 size_global_comment
= (uInt
)strlen(global_comment
);
1162 centraldir_pos_inzip
= ZTELL(zi
->z_filefunc
,zi
->filestream
);
1165 linkedlist_datablock_internal
* ldi
= zi
->central_dir
.first_block
;
1168 if ((err
==ZIP_OK
) && (ldi
->filled_in_this_block
>0))
1169 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,
1170 ldi
->data
,ldi
->filled_in_this_block
)
1171 !=ldi
->filled_in_this_block
)
1174 size_centraldir
+= ldi
->filled_in_this_block
;
1175 ldi
= ldi
->next_datablock
;
1178 free_datablock(zi
->central_dir
.first_block
);
1180 if (err
==ZIP_OK
) /* Magic End */
1181 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)ENDHEADERMAGIC
,4);
1183 if (err
==ZIP_OK
) /* number of this disk */
1184 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,2);
1186 if (err
==ZIP_OK
) /* number of the disk with the start of the central directory */
1187 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)0,2);
1189 if (err
==ZIP_OK
) /* total number of entries in the central dir on this disk */
1190 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->number_entry
,2);
1192 if (err
==ZIP_OK
) /* total number of entries in the central dir */
1193 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)zi
->number_entry
,2);
1195 if (err
==ZIP_OK
) /* size of the central directory */
1196 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_centraldir
,4);
1198 if (err
==ZIP_OK
) /* offset of start of central directory with respect to the
1199 starting disk number */
1200 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,
1201 (uLong
)(centraldir_pos_inzip
- zi
->add_position_when_writting_offset
),4);
1203 if (err
==ZIP_OK
) /* zipfile comment length */
1204 err
= ziplocal_putValue(&zi
->z_filefunc
,zi
->filestream
,(uLong
)size_global_comment
,2);
1206 if ((err
==ZIP_OK
) && (size_global_comment
>0))
1207 if (ZWRITE(zi
->z_filefunc
,zi
->filestream
,
1208 global_comment
,size_global_comment
) != size_global_comment
)
1211 if (ZCLOSE(zi
->z_filefunc
,zi
->filestream
) != 0)
1215 #ifndef NO_ADDFILEINEXISTINGZIP
1216 TRYFREE(zi
->globalcomment
);