|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "signtool.h" |
|
6 #include "zip.h" |
|
7 #include "zlib.h" |
|
8 #include "prmem.h" |
|
9 |
|
10 static void inttox (int in, char *out); |
|
11 static void longtox (long in, char *out); |
|
12 |
|
13 /**************************************************************** |
|
14 * |
|
15 * J z i p O p e n |
|
16 * |
|
17 * Opens a new ZIP file and creates a new ZIPfile structure to |
|
18 * control the process of installing files into a zip. |
|
19 */ |
|
20 ZIPfile* |
|
21 JzipOpen(char *filename, char *comment) |
|
22 { |
|
23 ZIPfile * zipfile; |
|
24 PRExplodedTime prtime; |
|
25 |
|
26 zipfile = PORT_ZAlloc(sizeof(ZIPfile)); |
|
27 if (!zipfile) |
|
28 out_of_memory(); |
|
29 |
|
30 /* Construct time and date */ |
|
31 PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime); |
|
32 zipfile->date = ((prtime.tm_year - 1980) << 9) | |
|
33 ((prtime.tm_month + 1) << 5) | |
|
34 prtime.tm_mday; |
|
35 zipfile->time = (prtime.tm_hour << 11) | |
|
36 (prtime.tm_min << 5) | |
|
37 (prtime.tm_sec & 0x3f); |
|
38 |
|
39 zipfile->fp = NULL; |
|
40 if (filename && |
|
41 (zipfile->fp = PR_Open(filename, |
|
42 PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) == NULL) { |
|
43 char *nsprErr; |
|
44 if (PR_GetErrorTextLength()) { |
|
45 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
46 PR_GetErrorText(nsprErr); |
|
47 } else { |
|
48 nsprErr = NULL; |
|
49 } |
|
50 PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n", |
|
51 PROGRAM_NAME, |
|
52 filename, nsprErr ? nsprErr : ""); |
|
53 if (nsprErr) |
|
54 PR_Free(nsprErr); |
|
55 errorCount++; |
|
56 exit (ERRX); |
|
57 } |
|
58 |
|
59 zipfile->list = NULL; |
|
60 if (filename) { |
|
61 zipfile->filename = PORT_ZAlloc(strlen(filename) + 1); |
|
62 if (!zipfile->filename) |
|
63 out_of_memory(); |
|
64 PORT_Strcpy(zipfile->filename, filename); |
|
65 } |
|
66 if (comment) { |
|
67 zipfile->comment = PORT_ZAlloc(strlen(comment) + 1); |
|
68 if (!zipfile->comment) |
|
69 out_of_memory(); |
|
70 PORT_Strcpy(zipfile->comment, comment); |
|
71 } |
|
72 |
|
73 return zipfile; |
|
74 } |
|
75 |
|
76 |
|
77 static |
|
78 void* |
|
79 my_alloc_func(void*opaque, uInt items, uInt size) |
|
80 { |
|
81 return PORT_Alloc(items * size); |
|
82 } |
|
83 |
|
84 |
|
85 static |
|
86 void |
|
87 my_free_func(void*opaque, void*address) |
|
88 { |
|
89 PORT_Free(address); |
|
90 } |
|
91 |
|
92 |
|
93 static |
|
94 void |
|
95 handle_zerror(int err, char *msg) |
|
96 { |
|
97 if (!msg) { |
|
98 msg = ""; |
|
99 } |
|
100 |
|
101 errorCount++; /* unless Z_OK...see below */ |
|
102 |
|
103 switch (err) { |
|
104 case Z_OK: |
|
105 PR_fprintf(errorFD, "No error: %s\n", msg); |
|
106 errorCount--; /* this was incremented above */ |
|
107 break; |
|
108 case Z_MEM_ERROR: |
|
109 PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg); |
|
110 break; |
|
111 case Z_STREAM_ERROR: |
|
112 PR_fprintf(errorFD, "Invalid compression level: %s\n", msg); |
|
113 break; |
|
114 case Z_VERSION_ERROR: |
|
115 PR_fprintf(errorFD, "Incompatible compression library version: %s\n", |
|
116 msg); |
|
117 break; |
|
118 case Z_DATA_ERROR: |
|
119 PR_fprintf(errorFD, "Compression data error: %s\n", msg); |
|
120 break; |
|
121 default: |
|
122 PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg); |
|
123 break; |
|
124 } |
|
125 } |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 /**************************************************************** |
|
131 * |
|
132 * J z i p A d d |
|
133 * |
|
134 * Adds a new file into a ZIP file. The ZIP file must have already |
|
135 * been opened with JzipOpen. |
|
136 */ |
|
137 int |
|
138 JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level) |
|
139 { |
|
140 ZIPentry * entry; |
|
141 PRFileDesc * readfp; |
|
142 PRFileDesc * zipfp; |
|
143 unsigned long crc; |
|
144 unsigned long local_size_pos; |
|
145 int num; |
|
146 int err; |
|
147 int deflate_percent; |
|
148 z_stream zstream; |
|
149 Bytef inbuf[BUFSIZ]; |
|
150 Bytef outbuf[BUFSIZ]; |
|
151 |
|
152 |
|
153 if ( !fullname || !filename || !zipfile) { |
|
154 return - 1; |
|
155 } |
|
156 |
|
157 zipfp = zipfile->fp; |
|
158 if (!zipfp) |
|
159 return - 1; |
|
160 |
|
161 |
|
162 if ( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) { |
|
163 char *nsprErr; |
|
164 if (PR_GetErrorTextLength()) { |
|
165 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
166 PR_GetErrorText(nsprErr); |
|
167 } else { |
|
168 nsprErr = NULL; |
|
169 } |
|
170 PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : |
|
171 ""); |
|
172 errorCount++; |
|
173 if (nsprErr) |
|
174 PR_Free(nsprErr); |
|
175 exit(ERRX); |
|
176 } |
|
177 |
|
178 /* |
|
179 * Make sure the input file is not the output file. |
|
180 * Add a few bytes to the end of the JAR file and see if the input file |
|
181 * twitches |
|
182 */ |
|
183 { |
|
184 PRInt32 endOfJar; |
|
185 PRInt32 inputSize; |
|
186 PRBool isSame; |
|
187 |
|
188 inputSize = PR_Available(readfp); |
|
189 |
|
190 endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR); |
|
191 |
|
192 if (PR_Write(zipfp, "abcde", 5) < 5) { |
|
193 char *nsprErr; |
|
194 |
|
195 if (PR_GetErrorTextLength()) { |
|
196 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
197 PR_GetErrorText(nsprErr); |
|
198 } else { |
|
199 nsprErr = NULL; |
|
200 } |
|
201 PR_fprintf(errorFD, "Writing to zip file: %s\n", |
|
202 nsprErr ? nsprErr : ""); |
|
203 if (nsprErr) |
|
204 PR_Free(nsprErr); |
|
205 errorCount++; |
|
206 exit(ERRX); |
|
207 } |
|
208 |
|
209 isSame = (PR_Available(readfp) != inputSize); |
|
210 |
|
211 PR_Seek(zipfp, endOfJar, PR_SEEK_SET); |
|
212 |
|
213 if (isSame) { |
|
214 /* It's the same file! Forget it! */ |
|
215 PR_Close(readfp); |
|
216 return 0; |
|
217 } |
|
218 } |
|
219 |
|
220 if (verbosity >= 0) { |
|
221 PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename); |
|
222 } |
|
223 |
|
224 entry = PORT_ZAlloc(sizeof(ZIPentry)); |
|
225 if (!entry) |
|
226 out_of_memory(); |
|
227 |
|
228 entry->filename = PORT_Strdup(filename); |
|
229 entry->comment = NULL; |
|
230 |
|
231 /* Set up local file header */ |
|
232 longtox(LSIG, entry->local.signature); |
|
233 inttox(strlen(filename), entry->local.filename_len); |
|
234 inttox(zipfile->time, entry->local.time); |
|
235 inttox(zipfile->date, entry->local.date); |
|
236 inttox(Z_DEFLATED, entry->local.method); |
|
237 |
|
238 /* Set up central directory entry */ |
|
239 longtox(CSIG, entry->central.signature); |
|
240 inttox(strlen(filename), entry->central.filename_len); |
|
241 if (entry->comment) { |
|
242 inttox(strlen(entry->comment), entry->central.commentfield_len); |
|
243 } |
|
244 longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR), |
|
245 entry->central.localhdr_offset); |
|
246 inttox(zipfile->time, entry->central.time); |
|
247 inttox(zipfile->date, entry->central.date); |
|
248 inttox(Z_DEFLATED, entry->central.method); |
|
249 |
|
250 /* Compute crc. Too bad we have to process the whole file to do this*/ |
|
251 crc = crc32(0L, NULL, 0); |
|
252 while ( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { |
|
253 crc = crc32(crc, inbuf, num); |
|
254 } |
|
255 PR_Seek(readfp, 0L, PR_SEEK_SET); |
|
256 |
|
257 /* Store CRC */ |
|
258 longtox(crc, entry->local.crc32); |
|
259 longtox(crc, entry->central.crc32); |
|
260 |
|
261 /* Stick this entry onto the end of the list */ |
|
262 entry->next = NULL; |
|
263 if ( zipfile->list == NULL ) { |
|
264 /* First entry */ |
|
265 zipfile->list = entry; |
|
266 } else { |
|
267 ZIPentry * pe; |
|
268 |
|
269 pe = zipfile->list; |
|
270 while (pe->next != NULL) { |
|
271 pe = pe->next; |
|
272 } |
|
273 pe->next = entry; |
|
274 } |
|
275 |
|
276 /* |
|
277 * Start writing stuff out |
|
278 */ |
|
279 |
|
280 local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18; |
|
281 /* File header */ |
|
282 if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal )) |
|
283 < sizeof(struct ZipLocal )) { |
|
284 char *nsprErr; |
|
285 if (PR_GetErrorTextLength()) { |
|
286 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
287 PR_GetErrorText(nsprErr); |
|
288 } else { |
|
289 nsprErr = NULL; |
|
290 } |
|
291 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : |
|
292 ""); |
|
293 if (nsprErr) |
|
294 PR_Free(nsprErr); |
|
295 errorCount++; |
|
296 exit(ERRX); |
|
297 } |
|
298 |
|
299 /* File Name */ |
|
300 if ( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) { |
|
301 char *nsprErr; |
|
302 if (PR_GetErrorTextLength()) { |
|
303 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
304 PR_GetErrorText(nsprErr); |
|
305 } else { |
|
306 nsprErr = NULL; |
|
307 } |
|
308 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : |
|
309 ""); |
|
310 if (nsprErr) |
|
311 PR_Free(nsprErr); |
|
312 errorCount++; |
|
313 exit(ERRX); |
|
314 } |
|
315 |
|
316 /* |
|
317 * File data |
|
318 */ |
|
319 /* Initialize zstream */ |
|
320 zstream.zalloc = my_alloc_func; |
|
321 zstream.zfree = my_free_func; |
|
322 zstream.opaque = NULL; |
|
323 zstream.next_in = inbuf; |
|
324 zstream.avail_in = BUFSIZ; |
|
325 zstream.next_out = outbuf; |
|
326 zstream.avail_out = BUFSIZ; |
|
327 /* Setting the windowBits to -MAX_WBITS is an undocumented feature of |
|
328 * zlib (see deflate.c in zlib). It is the same thing that Java does |
|
329 * when you specify the nowrap option for deflation in java.util.zip. |
|
330 * It causes zlib to leave out its headers and footers, which don't |
|
331 * work in PKZIP files. |
|
332 */ |
|
333 err = deflateInit2(&zstream, compression_level, Z_DEFLATED, |
|
334 -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY); |
|
335 if (err != Z_OK) { |
|
336 handle_zerror(err, zstream.msg); |
|
337 exit(ERRX); |
|
338 } |
|
339 |
|
340 while ( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { |
|
341 zstream.next_in = inbuf; |
|
342 /* Process this chunk of data */ |
|
343 while (zstream.avail_in > 0) { |
|
344 err = deflate(&zstream, Z_NO_FLUSH); |
|
345 if (err != Z_OK) { |
|
346 handle_zerror(err, zstream.msg); |
|
347 exit(ERRX); |
|
348 } |
|
349 if (zstream.avail_out <= 0) { |
|
350 if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { |
|
351 char *nsprErr; |
|
352 if (PR_GetErrorTextLength()) { |
|
353 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
354 PR_GetErrorText(nsprErr); |
|
355 } else { |
|
356 nsprErr = NULL; |
|
357 } |
|
358 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
359 nsprErr ? nsprErr : ""); |
|
360 if (nsprErr) |
|
361 PR_Free(nsprErr); |
|
362 errorCount++; |
|
363 exit(ERRX); |
|
364 } |
|
365 zstream.next_out = outbuf; |
|
366 zstream.avail_out = BUFSIZ; |
|
367 } |
|
368 } |
|
369 } |
|
370 |
|
371 /* Now flush everything */ |
|
372 while (1) { |
|
373 err = deflate(&zstream, Z_FINISH); |
|
374 if (err == Z_STREAM_END) { |
|
375 break; |
|
376 } else if (err == Z_OK) { |
|
377 /* output buffer full, repeat */ |
|
378 } else { |
|
379 handle_zerror(err, zstream.msg); |
|
380 exit(ERRX); |
|
381 } |
|
382 if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { |
|
383 char *nsprErr; |
|
384 if (PR_GetErrorTextLength()) { |
|
385 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
386 PR_GetErrorText(nsprErr); |
|
387 } else { |
|
388 nsprErr = NULL; |
|
389 } |
|
390 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
391 nsprErr ? nsprErr : ""); |
|
392 if (nsprErr) |
|
393 PR_Free(nsprErr); |
|
394 errorCount++; |
|
395 exit(ERRX); |
|
396 } |
|
397 zstream.avail_out = BUFSIZ; |
|
398 zstream.next_out = outbuf; |
|
399 } |
|
400 |
|
401 /* If there's any output left, write it out. */ |
|
402 if (zstream.next_out != outbuf) { |
|
403 if ( PR_Write(zipfp, outbuf, zstream.next_out - outbuf) < |
|
404 zstream.next_out - outbuf) { |
|
405 char *nsprErr; |
|
406 if (PR_GetErrorTextLength()) { |
|
407 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
408 PR_GetErrorText(nsprErr); |
|
409 } else { |
|
410 nsprErr = NULL; |
|
411 } |
|
412 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
413 nsprErr ? nsprErr : ""); |
|
414 if (nsprErr) |
|
415 PR_Free(nsprErr); |
|
416 errorCount++; |
|
417 exit(ERRX); |
|
418 } |
|
419 zstream.avail_out = BUFSIZ; |
|
420 zstream.next_out = outbuf; |
|
421 } |
|
422 |
|
423 /* Now that we know the compressed size, write this to the headers */ |
|
424 longtox(zstream.total_in, entry->local.orglen); |
|
425 longtox(zstream.total_out, entry->local.size); |
|
426 if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) { |
|
427 char *nsprErr; |
|
428 if (PR_GetErrorTextLength()) { |
|
429 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
430 PR_GetErrorText(nsprErr); |
|
431 } else { |
|
432 nsprErr = NULL; |
|
433 } |
|
434 PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : ""); |
|
435 if (nsprErr) |
|
436 PR_Free(nsprErr); |
|
437 errorCount++; |
|
438 exit(ERRX); |
|
439 } |
|
440 if ( PR_Write(zipfp, entry->local.size, 8) != 8) { |
|
441 char *nsprErr; |
|
442 if (PR_GetErrorTextLength()) { |
|
443 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
444 PR_GetErrorText(nsprErr); |
|
445 } else { |
|
446 nsprErr = NULL; |
|
447 } |
|
448 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); |
|
449 if (nsprErr) |
|
450 PR_Free(nsprErr); |
|
451 errorCount++; |
|
452 exit(ERRX); |
|
453 } |
|
454 if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) { |
|
455 char *nsprErr; |
|
456 if (PR_GetErrorTextLength()) { |
|
457 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
458 PR_GetErrorText(nsprErr); |
|
459 } else { |
|
460 nsprErr = NULL; |
|
461 } |
|
462 PR_fprintf(errorFD, "Accessing zip file: %s\n", |
|
463 nsprErr ? nsprErr : ""); |
|
464 if (nsprErr) |
|
465 PR_Free(nsprErr); |
|
466 errorCount++; |
|
467 exit(ERRX); |
|
468 } |
|
469 longtox(zstream.total_in, entry->central.orglen); |
|
470 longtox(zstream.total_out, entry->central.size); |
|
471 |
|
472 /* Close out the deflation operation */ |
|
473 err = deflateEnd(&zstream); |
|
474 if (err != Z_OK) { |
|
475 handle_zerror(err, zstream.msg); |
|
476 exit(ERRX); |
|
477 } |
|
478 |
|
479 PR_Close(readfp); |
|
480 |
|
481 if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) { |
|
482 deflate_percent = (int) |
|
483 ((zstream.total_in - zstream.total_out) *100 / zstream.total_in); |
|
484 } else { |
|
485 deflate_percent = 0; |
|
486 } |
|
487 if (verbosity >= 0) { |
|
488 PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent); |
|
489 } |
|
490 |
|
491 return 0; |
|
492 } |
|
493 |
|
494 |
|
495 /******************************************************************** |
|
496 * J z i p C l o s e |
|
497 * |
|
498 * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!! |
|
499 */ |
|
500 int |
|
501 JzipClose(ZIPfile *zipfile) |
|
502 { |
|
503 ZIPentry * pe, *dead; |
|
504 PRFileDesc * zipfp; |
|
505 struct ZipEnd zipend; |
|
506 unsigned int entrycount = 0; |
|
507 |
|
508 if (!zipfile) { |
|
509 return - 1; |
|
510 } |
|
511 |
|
512 if (!zipfile->filename) { |
|
513 /* bogus */ |
|
514 return 0; |
|
515 } |
|
516 |
|
517 zipfp = zipfile->fp; |
|
518 zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR); |
|
519 |
|
520 /* Write out all the central directories */ |
|
521 pe = zipfile->list; |
|
522 while (pe) { |
|
523 entrycount++; |
|
524 |
|
525 /* Write central directory info */ |
|
526 if ( PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral )) |
|
527 < sizeof(struct ZipCentral )) { |
|
528 char *nsprErr; |
|
529 if (PR_GetErrorTextLength()) { |
|
530 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
531 PR_GetErrorText(nsprErr); |
|
532 } else { |
|
533 nsprErr = NULL; |
|
534 } |
|
535 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
536 nsprErr ? nsprErr : ""); |
|
537 if (nsprErr) |
|
538 PR_Free(nsprErr); |
|
539 errorCount++; |
|
540 exit(ERRX); |
|
541 } |
|
542 |
|
543 /* Write filename */ |
|
544 if ( PR_Write(zipfp, pe->filename, strlen(pe->filename)) |
|
545 < strlen(pe->filename)) { |
|
546 char *nsprErr; |
|
547 if (PR_GetErrorTextLength()) { |
|
548 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
549 PR_GetErrorText(nsprErr); |
|
550 } else { |
|
551 nsprErr = NULL; |
|
552 } |
|
553 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
554 nsprErr ? nsprErr : ""); |
|
555 if (nsprErr) |
|
556 PR_Free(nsprErr); |
|
557 errorCount++; |
|
558 exit(ERRX); |
|
559 } |
|
560 |
|
561 /* Write file comment */ |
|
562 if (pe->comment) { |
|
563 if ( PR_Write(zipfp, pe->comment, strlen(pe->comment)) |
|
564 < strlen(pe->comment)) { |
|
565 char *nsprErr; |
|
566 if (PR_GetErrorTextLength()) { |
|
567 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
568 PR_GetErrorText(nsprErr); |
|
569 } else { |
|
570 nsprErr = NULL; |
|
571 } |
|
572 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
573 nsprErr ? nsprErr : ""); |
|
574 if (nsprErr) |
|
575 PR_Free(nsprErr); |
|
576 errorCount++; |
|
577 exit(ERRX); |
|
578 } |
|
579 } |
|
580 |
|
581 /* Delete the structure */ |
|
582 dead = pe; |
|
583 pe = pe->next; |
|
584 if (dead->filename) { |
|
585 PORT_Free(dead->filename); |
|
586 } |
|
587 if (dead->comment) { |
|
588 PORT_Free(dead->comment); |
|
589 } |
|
590 PORT_Free(dead); |
|
591 } |
|
592 zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR); |
|
593 |
|
594 /* Create the ZipEnd structure */ |
|
595 PORT_Memset(&zipend, 0, sizeof(zipend)); |
|
596 longtox(ESIG, zipend.signature); |
|
597 inttox(entrycount, zipend.total_entries_disk); |
|
598 inttox(entrycount, zipend.total_entries_archive); |
|
599 longtox(zipfile->central_end - zipfile->central_start, |
|
600 zipend.central_dir_size); |
|
601 longtox(zipfile->central_start, zipend.offset_central_dir); |
|
602 if (zipfile->comment) { |
|
603 inttox(strlen(zipfile->comment), zipend.commentfield_len); |
|
604 } |
|
605 |
|
606 /* Write out ZipEnd xtructure */ |
|
607 if ( PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) { |
|
608 char *nsprErr; |
|
609 if (PR_GetErrorTextLength()) { |
|
610 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
611 PR_GetErrorText(nsprErr); |
|
612 } else { |
|
613 nsprErr = NULL; |
|
614 } |
|
615 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
616 nsprErr ? nsprErr : ""); |
|
617 if (nsprErr) |
|
618 PR_Free(nsprErr); |
|
619 errorCount++; |
|
620 exit(ERRX); |
|
621 } |
|
622 |
|
623 /* Write out Zipfile comment */ |
|
624 if (zipfile->comment) { |
|
625 if ( PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment)) |
|
626 < strlen(zipfile->comment)) { |
|
627 char *nsprErr; |
|
628 if (PR_GetErrorTextLength()) { |
|
629 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); |
|
630 PR_GetErrorText(nsprErr); |
|
631 } else { |
|
632 nsprErr = NULL; |
|
633 } |
|
634 PR_fprintf(errorFD, "Writing zip data: %s\n", |
|
635 nsprErr ? nsprErr : ""); |
|
636 if (nsprErr) |
|
637 PR_Free(nsprErr); |
|
638 errorCount++; |
|
639 exit(ERRX); |
|
640 } |
|
641 } |
|
642 |
|
643 PR_Close(zipfp); |
|
644 |
|
645 /* Free the memory of the zipfile structure */ |
|
646 if (zipfile->filename) { |
|
647 PORT_Free(zipfile->filename); |
|
648 } |
|
649 if (zipfile->comment) { |
|
650 PORT_Free(zipfile->comment); |
|
651 } |
|
652 PORT_Free(zipfile); |
|
653 |
|
654 return 0; |
|
655 } |
|
656 |
|
657 |
|
658 /********************************************** |
|
659 * i n t t o x |
|
660 * |
|
661 * Converts a two byte ugly endianed integer |
|
662 * to our platform's integer. |
|
663 * |
|
664 */ |
|
665 |
|
666 static void inttox (int in, char *out) |
|
667 { |
|
668 out [0] = (in & 0xFF); |
|
669 out [1] = (in & 0xFF00) >> 8; |
|
670 } |
|
671 |
|
672 |
|
673 /********************************************* |
|
674 * l o n g t o x |
|
675 * |
|
676 * Converts a four byte ugly endianed integer |
|
677 * to our platform's integer. |
|
678 * |
|
679 */ |
|
680 |
|
681 static void longtox (long in, char *out) |
|
682 { |
|
683 out [0] = (in & 0xFF); |
|
684 out [1] = (in & 0xFF00) >> 8; |
|
685 out [2] = (in & 0xFF0000) >> 16; |
|
686 out [3] = (in & 0xFF000000) >> 24; |
|
687 } |
|
688 |
|
689 |