You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

718 lines
21 KiB

  1. /* zip.c -- IO on .zip files using zlib
  2. Version 0.15 beta, Mar 19th, 1998,
  3. Read zip.h for more info
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "zlib.h"
  9. #include "zip.h"
  10. #ifdef STDC
  11. # include <stddef.h>
  12. # include <string.h>
  13. # include <stdlib.h>
  14. #endif
  15. #ifdef NO_ERRNO_H
  16. extern int errno;
  17. #else
  18. # include <errno.h>
  19. #endif
  20. #ifndef local
  21. # define local static
  22. #endif
  23. /* compile with -Dlocal if your debugger can't find static symbols */
  24. #ifndef VERSIONMADEBY
  25. # define VERSIONMADEBY (0x0) /* platform depedent */
  26. #endif
  27. #ifndef Z_BUFSIZE
  28. #define Z_BUFSIZE (16384)
  29. #endif
  30. #ifndef Z_MAXFILENAMEINZIP
  31. #define Z_MAXFILENAMEINZIP (256)
  32. #endif
  33. #ifndef ALLOC
  34. # define ALLOC(size) (malloc(size))
  35. #endif
  36. #ifndef TRYFREE
  37. # define TRYFREE(p) {if (p) free(p);}
  38. #endif
  39. /*
  40. #define SIZECENTRALDIRITEM (0x2e)
  41. #define SIZEZIPLOCALHEADER (0x1e)
  42. */
  43. /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
  44. #ifndef SEEK_CUR
  45. #define SEEK_CUR 1
  46. #endif
  47. #ifndef SEEK_END
  48. #define SEEK_END 2
  49. #endif
  50. #ifndef SEEK_SET
  51. #define SEEK_SET 0
  52. #endif
  53. const char zip_copyright[] =
  54. " zip 0.15 Copyright 1998 Gilles Vollant ";
  55. #define SIZEDATA_INDATABLOCK (4096-(4*4))
  56. #define LOCALHEADERMAGIC (0x04034b50)
  57. #define CENTRALHEADERMAGIC (0x02014b50)
  58. #define ENDHEADERMAGIC (0x06054b50)
  59. #define FLAG_LOCALHEADER_OFFSET (0x06)
  60. #define CRC_LOCALHEADER_OFFSET (0x0e)
  61. #define SIZECENTRALHEADER (0x2e) /* 46 */
  62. typedef struct linkedlist_datablock_internal_s
  63. {
  64. struct linkedlist_datablock_internal_s* next_datablock;
  65. uLong avail_in_this_block;
  66. uLong filled_in_this_block;
  67. uLong unused; /* for future use and alignement */
  68. unsigned char data[SIZEDATA_INDATABLOCK];
  69. } linkedlist_datablock_internal;
  70. typedef struct linkedlist_data_s
  71. {
  72. linkedlist_datablock_internal* first_block;
  73. linkedlist_datablock_internal* last_block;
  74. } linkedlist_data;
  75. typedef struct
  76. {
  77. z_stream stream; /* zLib stream structure for inflate */
  78. int stream_initialised; /* 1 is stream is initialised */
  79. uInt pos_in_buffered_data; /* last written byte in buffered_data */
  80. uLong pos_local_header; /* offset of the local header of the file
  81. currenty writing */
  82. char* central_header; /* central header data for the current file */
  83. uLong size_centralheader; /* size of the central header for cur file */
  84. uLong flag; /* flag of the file currently writing */
  85. int method; /* compression method of file currenty wr.*/
  86. Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
  87. uLong dosDate;
  88. uLong crc32;
  89. } curfile_info;
  90. typedef struct
  91. {
  92. FILE * filezip;
  93. linkedlist_data central_dir;/* datablock with central dir in construction*/
  94. int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
  95. curfile_info ci; /* info on the file curretly writing */
  96. uLong begin_pos; /* position of the beginning of the zipfile */
  97. uLong number_entry;
  98. } zip_internal;
  99. local linkedlist_datablock_internal* allocate_new_datablock()
  100. {
  101. linkedlist_datablock_internal* ldi;
  102. ldi = (linkedlist_datablock_internal*)
  103. ALLOC(sizeof(linkedlist_datablock_internal));
  104. if (ldi!=NULL)
  105. {
  106. ldi->next_datablock = NULL ;
  107. ldi->filled_in_this_block = 0 ;
  108. ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
  109. }
  110. return ldi;
  111. }
  112. local void free_datablock(ldi)
  113. linkedlist_datablock_internal* ldi;
  114. {
  115. while (ldi!=NULL)
  116. {
  117. linkedlist_datablock_internal* ldinext = ldi->next_datablock;
  118. TRYFREE(ldi);
  119. ldi = ldinext;
  120. }
  121. }
  122. local void init_linkedlist(ll)
  123. linkedlist_data* ll;
  124. {
  125. ll->first_block = ll->last_block = NULL;
  126. }
  127. local void free_linkedlist(ll)
  128. linkedlist_data* ll;
  129. {
  130. free_datablock(ll->first_block);
  131. ll->first_block = ll->last_block = NULL;
  132. }
  133. local int add_data_in_datablock(ll,buf,len)
  134. linkedlist_data* ll;
  135. const void* buf;
  136. uLong len;
  137. {
  138. linkedlist_datablock_internal* ldi;
  139. const unsigned char* from_copy;
  140. if (ll==NULL)
  141. return ZIP_INTERNALERROR;
  142. if (ll->last_block == NULL)
  143. {
  144. ll->first_block = ll->last_block = allocate_new_datablock();
  145. if (ll->first_block == NULL)
  146. return ZIP_INTERNALERROR;
  147. }
  148. ldi = ll->last_block;
  149. from_copy = (unsigned char*)buf;
  150. while (len>0)
  151. {
  152. uInt copy_this;
  153. uInt i;
  154. unsigned char* to_copy;
  155. if (ldi->avail_in_this_block==0)
  156. {
  157. ldi->next_datablock = allocate_new_datablock();
  158. if (ldi->next_datablock == NULL)
  159. return ZIP_INTERNALERROR;
  160. ldi = ldi->next_datablock ;
  161. ll->last_block = ldi;
  162. }
  163. if (ldi->avail_in_this_block < len)
  164. copy_this = (uInt)ldi->avail_in_this_block;
  165. else
  166. copy_this = (uInt)len;
  167. to_copy = &(ldi->data[ldi->filled_in_this_block]);
  168. for (i=0;i<copy_this;i++)
  169. *(to_copy+i)=*(from_copy+i);
  170. ldi->filled_in_this_block += copy_this;
  171. ldi->avail_in_this_block -= copy_this;
  172. from_copy += copy_this ;
  173. len -= copy_this;
  174. }
  175. return ZIP_OK;
  176. }
  177. local int write_datablock(fout,ll)
  178. FILE * fout;
  179. linkedlist_data* ll;
  180. {
  181. linkedlist_datablock_internal* ldi;
  182. ldi = ll->first_block;
  183. while (ldi!=NULL)
  184. {
  185. if (ldi->filled_in_this_block > 0)
  186. if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1)
  187. return ZIP_ERRNO;
  188. ldi = ldi->next_datablock;
  189. }
  190. return ZIP_OK;
  191. }
  192. /****************************************************************************/
  193. /* ===========================================================================
  194. Outputs a long in LSB order to the given file
  195. nbByte == 1, 2 or 4 (byte, short or long)
  196. */
  197. local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte));
  198. local int ziplocal_putValue (file, x, nbByte)
  199. FILE *file;
  200. uLong x;
  201. int nbByte;
  202. {
  203. unsigned char buf[4];
  204. int n;
  205. for (n = 0; n < nbByte; n++) {
  206. buf[n] = (unsigned char)(x & 0xff);
  207. x >>= 8;
  208. }
  209. if (fwrite(buf,nbByte,1,file)!=1)
  210. return ZIP_ERRNO;
  211. else
  212. return ZIP_OK;
  213. }
  214. local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
  215. local void ziplocal_putValue_inmemory (dest, x, nbByte)
  216. void* dest;
  217. uLong x;
  218. int nbByte;
  219. {
  220. unsigned char* buf=(unsigned char*)dest;
  221. int n;
  222. for (n = 0; n < nbByte; n++) {
  223. buf[n] = (unsigned char)(x & 0xff);
  224. x >>= 8;
  225. }
  226. }
  227. /****************************************************************************/
  228. local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
  229. tm_zip* ptm;
  230. uLong dosDate;
  231. {
  232. uLong year = (uLong)ptm->tm_year;
  233. if (year>1980)
  234. year-=1980;
  235. else if (year>80)
  236. year-=80;
  237. return
  238. (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
  239. ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
  240. }
  241. /****************************************************************************/
  242. extern zipFile ZEXPORT zipOpen (pathname, append)
  243. const char *pathname;
  244. int append;
  245. {
  246. zip_internal ziinit;
  247. zip_internal* zi;
  248. ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab");
  249. if (ziinit.filezip == NULL)
  250. return NULL;
  251. ziinit.begin_pos = ftell(ziinit.filezip);
  252. ziinit.in_opened_file_inzip = 0;
  253. ziinit.ci.stream_initialised = 0;
  254. ziinit.number_entry = 0;
  255. init_linkedlist(&(ziinit.central_dir));
  256. zi = (zip_internal*)ALLOC(sizeof(zip_internal));
  257. if (zi==NULL)
  258. {
  259. fclose(ziinit.filezip);
  260. return NULL;
  261. }
  262. *zi = ziinit;
  263. return (zipFile)zi;
  264. }
  265. extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
  266. extrafield_local, size_extrafield_local,
  267. extrafield_global, size_extrafield_global,
  268. comment, method, level)
  269. zipFile file;
  270. const char* filename;
  271. const zip_fileinfo* zipfi;
  272. const void* extrafield_local;
  273. uInt size_extrafield_local;
  274. const void* extrafield_global;
  275. uInt size_extrafield_global;
  276. const char* comment;
  277. int method;
  278. int level;
  279. {
  280. zip_internal* zi;
  281. uInt size_filename;
  282. uInt size_comment;
  283. uInt i;
  284. int err = ZIP_OK;
  285. if (file == NULL)
  286. return ZIP_PARAMERROR;
  287. if ((method!=0) && (method!=Z_DEFLATED))
  288. return ZIP_PARAMERROR;
  289. zi = (zip_internal*)file;
  290. if (zi->in_opened_file_inzip == 1)
  291. {
  292. err = zipCloseFileInZip (file);
  293. if (err != ZIP_OK)
  294. return err;
  295. }
  296. if (filename==NULL)
  297. filename="-";
  298. if (comment==NULL)
  299. size_comment = 0;
  300. else
  301. size_comment = strlen(comment);
  302. size_filename = strlen(filename);
  303. if (zipfi == NULL)
  304. zi->ci.dosDate = 0;
  305. else
  306. {
  307. if (zipfi->dosDate != 0)
  308. zi->ci.dosDate = zipfi->dosDate;
  309. else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
  310. }
  311. zi->ci.flag = 0;
  312. if ((level==8) || (level==9))
  313. zi->ci.flag |= 2;
  314. if ((level==2))
  315. zi->ci.flag |= 4;
  316. if ((level==1))
  317. zi->ci.flag |= 6;
  318. zi->ci.crc32 = 0;
  319. zi->ci.method = method;
  320. zi->ci.stream_initialised = 0;
  321. zi->ci.pos_in_buffered_data = 0;
  322. zi->ci.pos_local_header = ftell(zi->filezip);
  323. zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
  324. size_extrafield_global + size_comment;
  325. zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
  326. ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
  327. /* version info */
  328. ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
  329. ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
  330. ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
  331. ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
  332. ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
  333. ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
  334. ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
  335. ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
  336. ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
  337. ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
  338. ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
  339. ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
  340. if (zipfi==NULL)
  341. ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
  342. else
  343. ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
  344. if (zipfi==NULL)
  345. ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
  346. else
  347. ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
  348. ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4);
  349. for (i=0;i<size_filename;i++)
  350. *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
  351. for (i=0;i<size_extrafield_global;i++)
  352. *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
  353. *(((const char*)extrafield_global)+i);
  354. for (i=0;i<size_comment;i++)
  355. *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
  356. size_extrafield_global+i) = *(filename+i);
  357. if (zi->ci.central_header == NULL)
  358. return ZIP_INTERNALERROR;
  359. /* write the local header */
  360. err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4);
  361. if (err==ZIP_OK)
  362. err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */
  363. if (err==ZIP_OK)
  364. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2);
  365. if (err==ZIP_OK)
  366. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2);
  367. if (err==ZIP_OK)
  368. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4);
  369. if (err==ZIP_OK)
  370. err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */
  371. if (err==ZIP_OK)
  372. err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */
  373. if (err==ZIP_OK)
  374. err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */
  375. if (err==ZIP_OK)
  376. err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
  377. if (err==ZIP_OK)
  378. err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
  379. if ((err==ZIP_OK) && (size_filename>0))
  380. if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
  381. err = ZIP_ERRNO;
  382. if ((err==ZIP_OK) && (size_extrafield_local>0))
  383. if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
  384. !=1)
  385. err = ZIP_ERRNO;
  386. zi->ci.stream.avail_in = (uInt)0;
  387. zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  388. zi->ci.stream.next_out = zi->ci.buffered_data;
  389. zi->ci.stream.total_in = 0;
  390. zi->ci.stream.total_out = 0;
  391. if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
  392. {
  393. zi->ci.stream.zalloc = (alloc_func)0;
  394. zi->ci.stream.zfree = (free_func)0;
  395. zi->ci.stream.opaque = (voidpf)0;
  396. err = deflateInit2(&zi->ci.stream, level,
  397. Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
  398. if (err==Z_OK)
  399. zi->ci.stream_initialised = 1;
  400. }
  401. if (err==Z_OK)
  402. zi->in_opened_file_inzip = 1;
  403. return err;
  404. }
  405. extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
  406. zipFile file;
  407. const voidp buf;
  408. unsigned len;
  409. {
  410. zip_internal* zi;
  411. int err=ZIP_OK;
  412. if (file == NULL)
  413. return ZIP_PARAMERROR;
  414. zi = (zip_internal*)file;
  415. if (zi->in_opened_file_inzip == 0)
  416. return ZIP_PARAMERROR;
  417. zi->ci.stream.next_in = buf;
  418. zi->ci.stream.avail_in = len;
  419. zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
  420. while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
  421. {
  422. if (zi->ci.stream.avail_out == 0)
  423. {
  424. if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  425. !=1)
  426. err = ZIP_ERRNO;
  427. zi->ci.pos_in_buffered_data = 0;
  428. zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  429. zi->ci.stream.next_out = zi->ci.buffered_data;
  430. }
  431. if (zi->ci.method == Z_DEFLATED)
  432. {
  433. uLong uTotalOutBefore = zi->ci.stream.total_out;
  434. err=deflate(&zi->ci.stream, Z_NO_FLUSH);
  435. zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
  436. }
  437. else
  438. {
  439. uInt copy_this,i;
  440. if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
  441. copy_this = zi->ci.stream.avail_in;
  442. else
  443. copy_this = zi->ci.stream.avail_out;
  444. for (i=0;i<copy_this;i++)
  445. *(((char*)zi->ci.stream.next_out)+i) =
  446. *(((const char*)zi->ci.stream.next_in)+i);
  447. {
  448. zi->ci.stream.avail_in -= copy_this;
  449. zi->ci.stream.avail_out-= copy_this;
  450. zi->ci.stream.next_in+= copy_this;
  451. zi->ci.stream.next_out+= copy_this;
  452. zi->ci.stream.total_in+= copy_this;
  453. zi->ci.stream.total_out+= copy_this;
  454. zi->ci.pos_in_buffered_data += copy_this;
  455. }
  456. }
  457. }
  458. return 0;
  459. }
  460. extern int ZEXPORT zipCloseFileInZip (file)
  461. zipFile file;
  462. {
  463. zip_internal* zi;
  464. int err=ZIP_OK;
  465. if (file == NULL)
  466. return ZIP_PARAMERROR;
  467. zi = (zip_internal*)file;
  468. if (zi->in_opened_file_inzip == 0)
  469. return ZIP_PARAMERROR;
  470. zi->ci.stream.avail_in = 0;
  471. if (zi->ci.method == Z_DEFLATED)
  472. while (err==ZIP_OK)
  473. {
  474. uLong uTotalOutBefore;
  475. if (zi->ci.stream.avail_out == 0)
  476. {
  477. if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  478. !=1)
  479. err = ZIP_ERRNO;
  480. zi->ci.pos_in_buffered_data = 0;
  481. zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  482. zi->ci.stream.next_out = zi->ci.buffered_data;
  483. }
  484. uTotalOutBefore = zi->ci.stream.total_out;
  485. err=deflate(&zi->ci.stream, Z_FINISH);
  486. zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
  487. }
  488. if (err==Z_STREAM_END)
  489. err=ZIP_OK; /* this is normal */
  490. if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
  491. if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  492. !=1)
  493. err = ZIP_ERRNO;
  494. if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
  495. {
  496. err=deflateEnd(&zi->ci.stream);
  497. zi->ci.stream_initialised = 0;
  498. }
  499. ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/
  500. ziplocal_putValue_inmemory(zi->ci.central_header+20,
  501. (uLong)zi->ci.stream.total_out,4); /*compr size*/
  502. ziplocal_putValue_inmemory(zi->ci.central_header+24,
  503. (uLong)zi->ci.stream.total_in,4); /*uncompr size*/
  504. if (err==ZIP_OK)
  505. err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
  506. (uLong)zi->ci.size_centralheader);
  507. free(zi->ci.central_header);
  508. if (err==ZIP_OK)
  509. {
  510. long cur_pos_inzip = ftell(zi->filezip);
  511. if (fseek(zi->filezip,
  512. zi->ci.pos_local_header + 14,SEEK_SET)!=0)
  513. err = ZIP_ERRNO;
  514. if (err==ZIP_OK)
  515. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */
  516. if (err==ZIP_OK) /* compressed size, unknown */
  517. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4);
  518. if (err==ZIP_OK) /* uncompressed size, unknown */
  519. err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4);
  520. if (fseek(zi->filezip,
  521. cur_pos_inzip,SEEK_SET)!=0)
  522. err = ZIP_ERRNO;
  523. }
  524. zi->number_entry ++;
  525. zi->in_opened_file_inzip = 0;
  526. return err;
  527. }
  528. extern int ZEXPORT zipClose (file, global_comment)
  529. zipFile file;
  530. const char* global_comment;
  531. {
  532. zip_internal* zi;
  533. int err = 0;
  534. uLong size_centraldir = 0;
  535. uLong centraldir_pos_inzip ;
  536. uInt size_global_comment;
  537. if (file == NULL)
  538. return ZIP_PARAMERROR;
  539. zi = (zip_internal*)file;
  540. if (zi->in_opened_file_inzip == 1)
  541. {
  542. err = zipCloseFileInZip (file);
  543. }
  544. if (global_comment==NULL)
  545. size_global_comment = 0;
  546. else
  547. size_global_comment = strlen(global_comment);
  548. centraldir_pos_inzip = ftell(zi->filezip);
  549. if (err==ZIP_OK)
  550. {
  551. linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
  552. while (ldi!=NULL)
  553. {
  554. if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
  555. if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
  556. 1,zi->filezip) !=1 )
  557. err = ZIP_ERRNO;
  558. size_centraldir += ldi->filled_in_this_block;
  559. ldi = ldi->next_datablock;
  560. }
  561. }
  562. free_datablock(zi->central_dir.first_block);
  563. if (err==ZIP_OK) /* Magic End */
  564. err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4);
  565. if (err==ZIP_OK) /* number of this disk */
  566. err = ziplocal_putValue(zi->filezip,(uLong)0,2);
  567. if (err==ZIP_OK) /* number of the disk with the start of the central directory */
  568. err = ziplocal_putValue(zi->filezip,(uLong)0,2);
  569. if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
  570. err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
  571. if (err==ZIP_OK) /* total number of entries in the central dir */
  572. err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
  573. if (err==ZIP_OK) /* size of the central directory */
  574. err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4);
  575. if (err==ZIP_OK) /* offset of start of central directory with respect to the
  576. starting disk number */
  577. err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4);
  578. if (err==ZIP_OK) /* zipfile comment length */
  579. err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
  580. if ((err==ZIP_OK) && (size_global_comment>0))
  581. if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
  582. err = ZIP_ERRNO;
  583. fclose(zi->filezip);
  584. TRYFREE(zi);
  585. return err;
  586. }