1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/signtool/zip.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,689 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "signtool.h" 1.9 +#include "zip.h" 1.10 +#include "zlib.h" 1.11 +#include "prmem.h" 1.12 + 1.13 +static void inttox (int in, char *out); 1.14 +static void longtox (long in, char *out); 1.15 + 1.16 +/**************************************************************** 1.17 + * 1.18 + * J z i p O p e n 1.19 + * 1.20 + * Opens a new ZIP file and creates a new ZIPfile structure to 1.21 + * control the process of installing files into a zip. 1.22 + */ 1.23 +ZIPfile* 1.24 +JzipOpen(char *filename, char *comment) 1.25 +{ 1.26 + ZIPfile * zipfile; 1.27 + PRExplodedTime prtime; 1.28 + 1.29 + zipfile = PORT_ZAlloc(sizeof(ZIPfile)); 1.30 + if (!zipfile) 1.31 + out_of_memory(); 1.32 + 1.33 + /* Construct time and date */ 1.34 + PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime); 1.35 + zipfile->date = ((prtime.tm_year - 1980) << 9) | 1.36 + ((prtime.tm_month + 1) << 5) | 1.37 + prtime.tm_mday; 1.38 + zipfile->time = (prtime.tm_hour << 11) | 1.39 + (prtime.tm_min << 5) | 1.40 + (prtime.tm_sec & 0x3f); 1.41 + 1.42 + zipfile->fp = NULL; 1.43 + if (filename && 1.44 + (zipfile->fp = PR_Open(filename, 1.45 + PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) == NULL) { 1.46 + char *nsprErr; 1.47 + if (PR_GetErrorTextLength()) { 1.48 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.49 + PR_GetErrorText(nsprErr); 1.50 + } else { 1.51 + nsprErr = NULL; 1.52 + } 1.53 + PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n", 1.54 + PROGRAM_NAME, 1.55 + filename, nsprErr ? nsprErr : ""); 1.56 + if (nsprErr) 1.57 + PR_Free(nsprErr); 1.58 + errorCount++; 1.59 + exit (ERRX); 1.60 + } 1.61 + 1.62 + zipfile->list = NULL; 1.63 + if (filename) { 1.64 + zipfile->filename = PORT_ZAlloc(strlen(filename) + 1); 1.65 + if (!zipfile->filename) 1.66 + out_of_memory(); 1.67 + PORT_Strcpy(zipfile->filename, filename); 1.68 + } 1.69 + if (comment) { 1.70 + zipfile->comment = PORT_ZAlloc(strlen(comment) + 1); 1.71 + if (!zipfile->comment) 1.72 + out_of_memory(); 1.73 + PORT_Strcpy(zipfile->comment, comment); 1.74 + } 1.75 + 1.76 + return zipfile; 1.77 +} 1.78 + 1.79 + 1.80 +static 1.81 +void* 1.82 +my_alloc_func(void*opaque, uInt items, uInt size) 1.83 +{ 1.84 + return PORT_Alloc(items * size); 1.85 +} 1.86 + 1.87 + 1.88 +static 1.89 +void 1.90 +my_free_func(void*opaque, void*address) 1.91 +{ 1.92 + PORT_Free(address); 1.93 +} 1.94 + 1.95 + 1.96 +static 1.97 +void 1.98 +handle_zerror(int err, char *msg) 1.99 +{ 1.100 + if (!msg) { 1.101 + msg = ""; 1.102 + } 1.103 + 1.104 + errorCount++; /* unless Z_OK...see below */ 1.105 + 1.106 + switch (err) { 1.107 + case Z_OK: 1.108 + PR_fprintf(errorFD, "No error: %s\n", msg); 1.109 + errorCount--; /* this was incremented above */ 1.110 + break; 1.111 + case Z_MEM_ERROR: 1.112 + PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg); 1.113 + break; 1.114 + case Z_STREAM_ERROR: 1.115 + PR_fprintf(errorFD, "Invalid compression level: %s\n", msg); 1.116 + break; 1.117 + case Z_VERSION_ERROR: 1.118 + PR_fprintf(errorFD, "Incompatible compression library version: %s\n", 1.119 + msg); 1.120 + break; 1.121 + case Z_DATA_ERROR: 1.122 + PR_fprintf(errorFD, "Compression data error: %s\n", msg); 1.123 + break; 1.124 + default: 1.125 + PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg); 1.126 + break; 1.127 + } 1.128 +} 1.129 + 1.130 + 1.131 + 1.132 + 1.133 +/**************************************************************** 1.134 + * 1.135 + * J z i p A d d 1.136 + * 1.137 + * Adds a new file into a ZIP file. The ZIP file must have already 1.138 + * been opened with JzipOpen. 1.139 + */ 1.140 +int 1.141 +JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level) 1.142 +{ 1.143 + ZIPentry * entry; 1.144 + PRFileDesc * readfp; 1.145 + PRFileDesc * zipfp; 1.146 + unsigned long crc; 1.147 + unsigned long local_size_pos; 1.148 + int num; 1.149 + int err; 1.150 + int deflate_percent; 1.151 + z_stream zstream; 1.152 + Bytef inbuf[BUFSIZ]; 1.153 + Bytef outbuf[BUFSIZ]; 1.154 + 1.155 + 1.156 + if ( !fullname || !filename || !zipfile) { 1.157 + return - 1; 1.158 + } 1.159 + 1.160 + zipfp = zipfile->fp; 1.161 + if (!zipfp) 1.162 + return - 1; 1.163 + 1.164 + 1.165 + if ( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) { 1.166 + char *nsprErr; 1.167 + if (PR_GetErrorTextLength()) { 1.168 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.169 + PR_GetErrorText(nsprErr); 1.170 + } else { 1.171 + nsprErr = NULL; 1.172 + } 1.173 + PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : 1.174 + ""); 1.175 + errorCount++; 1.176 + if (nsprErr) 1.177 + PR_Free(nsprErr); 1.178 + exit(ERRX); 1.179 + } 1.180 + 1.181 + /* 1.182 + * Make sure the input file is not the output file. 1.183 + * Add a few bytes to the end of the JAR file and see if the input file 1.184 + * twitches 1.185 + */ 1.186 + { 1.187 + PRInt32 endOfJar; 1.188 + PRInt32 inputSize; 1.189 + PRBool isSame; 1.190 + 1.191 + inputSize = PR_Available(readfp); 1.192 + 1.193 + endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR); 1.194 + 1.195 + if (PR_Write(zipfp, "abcde", 5) < 5) { 1.196 + char *nsprErr; 1.197 + 1.198 + if (PR_GetErrorTextLength()) { 1.199 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.200 + PR_GetErrorText(nsprErr); 1.201 + } else { 1.202 + nsprErr = NULL; 1.203 + } 1.204 + PR_fprintf(errorFD, "Writing to zip file: %s\n", 1.205 + nsprErr ? nsprErr : ""); 1.206 + if (nsprErr) 1.207 + PR_Free(nsprErr); 1.208 + errorCount++; 1.209 + exit(ERRX); 1.210 + } 1.211 + 1.212 + isSame = (PR_Available(readfp) != inputSize); 1.213 + 1.214 + PR_Seek(zipfp, endOfJar, PR_SEEK_SET); 1.215 + 1.216 + if (isSame) { 1.217 + /* It's the same file! Forget it! */ 1.218 + PR_Close(readfp); 1.219 + return 0; 1.220 + } 1.221 + } 1.222 + 1.223 + if (verbosity >= 0) { 1.224 + PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename); 1.225 + } 1.226 + 1.227 + entry = PORT_ZAlloc(sizeof(ZIPentry)); 1.228 + if (!entry) 1.229 + out_of_memory(); 1.230 + 1.231 + entry->filename = PORT_Strdup(filename); 1.232 + entry->comment = NULL; 1.233 + 1.234 + /* Set up local file header */ 1.235 + longtox(LSIG, entry->local.signature); 1.236 + inttox(strlen(filename), entry->local.filename_len); 1.237 + inttox(zipfile->time, entry->local.time); 1.238 + inttox(zipfile->date, entry->local.date); 1.239 + inttox(Z_DEFLATED, entry->local.method); 1.240 + 1.241 + /* Set up central directory entry */ 1.242 + longtox(CSIG, entry->central.signature); 1.243 + inttox(strlen(filename), entry->central.filename_len); 1.244 + if (entry->comment) { 1.245 + inttox(strlen(entry->comment), entry->central.commentfield_len); 1.246 + } 1.247 + longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR), 1.248 + entry->central.localhdr_offset); 1.249 + inttox(zipfile->time, entry->central.time); 1.250 + inttox(zipfile->date, entry->central.date); 1.251 + inttox(Z_DEFLATED, entry->central.method); 1.252 + 1.253 + /* Compute crc. Too bad we have to process the whole file to do this*/ 1.254 + crc = crc32(0L, NULL, 0); 1.255 + while ( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { 1.256 + crc = crc32(crc, inbuf, num); 1.257 + } 1.258 + PR_Seek(readfp, 0L, PR_SEEK_SET); 1.259 + 1.260 + /* Store CRC */ 1.261 + longtox(crc, entry->local.crc32); 1.262 + longtox(crc, entry->central.crc32); 1.263 + 1.264 + /* Stick this entry onto the end of the list */ 1.265 + entry->next = NULL; 1.266 + if ( zipfile->list == NULL ) { 1.267 + /* First entry */ 1.268 + zipfile->list = entry; 1.269 + } else { 1.270 + ZIPentry * pe; 1.271 + 1.272 + pe = zipfile->list; 1.273 + while (pe->next != NULL) { 1.274 + pe = pe->next; 1.275 + } 1.276 + pe->next = entry; 1.277 + } 1.278 + 1.279 + /* 1.280 + * Start writing stuff out 1.281 + */ 1.282 + 1.283 + local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18; 1.284 + /* File header */ 1.285 + if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal )) 1.286 + < sizeof(struct ZipLocal )) { 1.287 + char *nsprErr; 1.288 + if (PR_GetErrorTextLength()) { 1.289 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.290 + PR_GetErrorText(nsprErr); 1.291 + } else { 1.292 + nsprErr = NULL; 1.293 + } 1.294 + PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : 1.295 + ""); 1.296 + if (nsprErr) 1.297 + PR_Free(nsprErr); 1.298 + errorCount++; 1.299 + exit(ERRX); 1.300 + } 1.301 + 1.302 + /* File Name */ 1.303 + if ( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) { 1.304 + char *nsprErr; 1.305 + if (PR_GetErrorTextLength()) { 1.306 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.307 + PR_GetErrorText(nsprErr); 1.308 + } else { 1.309 + nsprErr = NULL; 1.310 + } 1.311 + PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : 1.312 + ""); 1.313 + if (nsprErr) 1.314 + PR_Free(nsprErr); 1.315 + errorCount++; 1.316 + exit(ERRX); 1.317 + } 1.318 + 1.319 + /* 1.320 + * File data 1.321 + */ 1.322 + /* Initialize zstream */ 1.323 + zstream.zalloc = my_alloc_func; 1.324 + zstream.zfree = my_free_func; 1.325 + zstream.opaque = NULL; 1.326 + zstream.next_in = inbuf; 1.327 + zstream.avail_in = BUFSIZ; 1.328 + zstream.next_out = outbuf; 1.329 + zstream.avail_out = BUFSIZ; 1.330 + /* Setting the windowBits to -MAX_WBITS is an undocumented feature of 1.331 + * zlib (see deflate.c in zlib). It is the same thing that Java does 1.332 + * when you specify the nowrap option for deflation in java.util.zip. 1.333 + * It causes zlib to leave out its headers and footers, which don't 1.334 + * work in PKZIP files. 1.335 + */ 1.336 + err = deflateInit2(&zstream, compression_level, Z_DEFLATED, 1.337 + -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY); 1.338 + if (err != Z_OK) { 1.339 + handle_zerror(err, zstream.msg); 1.340 + exit(ERRX); 1.341 + } 1.342 + 1.343 + while ( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) { 1.344 + zstream.next_in = inbuf; 1.345 + /* Process this chunk of data */ 1.346 + while (zstream.avail_in > 0) { 1.347 + err = deflate(&zstream, Z_NO_FLUSH); 1.348 + if (err != Z_OK) { 1.349 + handle_zerror(err, zstream.msg); 1.350 + exit(ERRX); 1.351 + } 1.352 + if (zstream.avail_out <= 0) { 1.353 + if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { 1.354 + char *nsprErr; 1.355 + if (PR_GetErrorTextLength()) { 1.356 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.357 + PR_GetErrorText(nsprErr); 1.358 + } else { 1.359 + nsprErr = NULL; 1.360 + } 1.361 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.362 + nsprErr ? nsprErr : ""); 1.363 + if (nsprErr) 1.364 + PR_Free(nsprErr); 1.365 + errorCount++; 1.366 + exit(ERRX); 1.367 + } 1.368 + zstream.next_out = outbuf; 1.369 + zstream.avail_out = BUFSIZ; 1.370 + } 1.371 + } 1.372 + } 1.373 + 1.374 + /* Now flush everything */ 1.375 + while (1) { 1.376 + err = deflate(&zstream, Z_FINISH); 1.377 + if (err == Z_STREAM_END) { 1.378 + break; 1.379 + } else if (err == Z_OK) { 1.380 + /* output buffer full, repeat */ 1.381 + } else { 1.382 + handle_zerror(err, zstream.msg); 1.383 + exit(ERRX); 1.384 + } 1.385 + if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) { 1.386 + char *nsprErr; 1.387 + if (PR_GetErrorTextLength()) { 1.388 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.389 + PR_GetErrorText(nsprErr); 1.390 + } else { 1.391 + nsprErr = NULL; 1.392 + } 1.393 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.394 + nsprErr ? nsprErr : ""); 1.395 + if (nsprErr) 1.396 + PR_Free(nsprErr); 1.397 + errorCount++; 1.398 + exit(ERRX); 1.399 + } 1.400 + zstream.avail_out = BUFSIZ; 1.401 + zstream.next_out = outbuf; 1.402 + } 1.403 + 1.404 + /* If there's any output left, write it out. */ 1.405 + if (zstream.next_out != outbuf) { 1.406 + if ( PR_Write(zipfp, outbuf, zstream.next_out - outbuf) < 1.407 + zstream.next_out - outbuf) { 1.408 + char *nsprErr; 1.409 + if (PR_GetErrorTextLength()) { 1.410 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.411 + PR_GetErrorText(nsprErr); 1.412 + } else { 1.413 + nsprErr = NULL; 1.414 + } 1.415 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.416 + nsprErr ? nsprErr : ""); 1.417 + if (nsprErr) 1.418 + PR_Free(nsprErr); 1.419 + errorCount++; 1.420 + exit(ERRX); 1.421 + } 1.422 + zstream.avail_out = BUFSIZ; 1.423 + zstream.next_out = outbuf; 1.424 + } 1.425 + 1.426 + /* Now that we know the compressed size, write this to the headers */ 1.427 + longtox(zstream.total_in, entry->local.orglen); 1.428 + longtox(zstream.total_out, entry->local.size); 1.429 + if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) { 1.430 + char *nsprErr; 1.431 + if (PR_GetErrorTextLength()) { 1.432 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.433 + PR_GetErrorText(nsprErr); 1.434 + } else { 1.435 + nsprErr = NULL; 1.436 + } 1.437 + PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : ""); 1.438 + if (nsprErr) 1.439 + PR_Free(nsprErr); 1.440 + errorCount++; 1.441 + exit(ERRX); 1.442 + } 1.443 + if ( PR_Write(zipfp, entry->local.size, 8) != 8) { 1.444 + char *nsprErr; 1.445 + if (PR_GetErrorTextLength()) { 1.446 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.447 + PR_GetErrorText(nsprErr); 1.448 + } else { 1.449 + nsprErr = NULL; 1.450 + } 1.451 + PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : ""); 1.452 + if (nsprErr) 1.453 + PR_Free(nsprErr); 1.454 + errorCount++; 1.455 + exit(ERRX); 1.456 + } 1.457 + if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) { 1.458 + char *nsprErr; 1.459 + if (PR_GetErrorTextLength()) { 1.460 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.461 + PR_GetErrorText(nsprErr); 1.462 + } else { 1.463 + nsprErr = NULL; 1.464 + } 1.465 + PR_fprintf(errorFD, "Accessing zip file: %s\n", 1.466 + nsprErr ? nsprErr : ""); 1.467 + if (nsprErr) 1.468 + PR_Free(nsprErr); 1.469 + errorCount++; 1.470 + exit(ERRX); 1.471 + } 1.472 + longtox(zstream.total_in, entry->central.orglen); 1.473 + longtox(zstream.total_out, entry->central.size); 1.474 + 1.475 + /* Close out the deflation operation */ 1.476 + err = deflateEnd(&zstream); 1.477 + if (err != Z_OK) { 1.478 + handle_zerror(err, zstream.msg); 1.479 + exit(ERRX); 1.480 + } 1.481 + 1.482 + PR_Close(readfp); 1.483 + 1.484 + if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) { 1.485 + deflate_percent = (int) 1.486 + ((zstream.total_in - zstream.total_out) *100 / zstream.total_in); 1.487 + } else { 1.488 + deflate_percent = 0; 1.489 + } 1.490 + if (verbosity >= 0) { 1.491 + PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent); 1.492 + } 1.493 + 1.494 + return 0; 1.495 +} 1.496 + 1.497 + 1.498 +/******************************************************************** 1.499 + * J z i p C l o s e 1.500 + * 1.501 + * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!! 1.502 + */ 1.503 +int 1.504 +JzipClose(ZIPfile *zipfile) 1.505 +{ 1.506 + ZIPentry * pe, *dead; 1.507 + PRFileDesc * zipfp; 1.508 + struct ZipEnd zipend; 1.509 + unsigned int entrycount = 0; 1.510 + 1.511 + if (!zipfile) { 1.512 + return - 1; 1.513 + } 1.514 + 1.515 + if (!zipfile->filename) { 1.516 + /* bogus */ 1.517 + return 0; 1.518 + } 1.519 + 1.520 + zipfp = zipfile->fp; 1.521 + zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR); 1.522 + 1.523 + /* Write out all the central directories */ 1.524 + pe = zipfile->list; 1.525 + while (pe) { 1.526 + entrycount++; 1.527 + 1.528 + /* Write central directory info */ 1.529 + if ( PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral )) 1.530 + < sizeof(struct ZipCentral )) { 1.531 + char *nsprErr; 1.532 + if (PR_GetErrorTextLength()) { 1.533 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.534 + PR_GetErrorText(nsprErr); 1.535 + } else { 1.536 + nsprErr = NULL; 1.537 + } 1.538 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.539 + nsprErr ? nsprErr : ""); 1.540 + if (nsprErr) 1.541 + PR_Free(nsprErr); 1.542 + errorCount++; 1.543 + exit(ERRX); 1.544 + } 1.545 + 1.546 + /* Write filename */ 1.547 + if ( PR_Write(zipfp, pe->filename, strlen(pe->filename)) 1.548 + < strlen(pe->filename)) { 1.549 + char *nsprErr; 1.550 + if (PR_GetErrorTextLength()) { 1.551 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.552 + PR_GetErrorText(nsprErr); 1.553 + } else { 1.554 + nsprErr = NULL; 1.555 + } 1.556 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.557 + nsprErr ? nsprErr : ""); 1.558 + if (nsprErr) 1.559 + PR_Free(nsprErr); 1.560 + errorCount++; 1.561 + exit(ERRX); 1.562 + } 1.563 + 1.564 + /* Write file comment */ 1.565 + if (pe->comment) { 1.566 + if ( PR_Write(zipfp, pe->comment, strlen(pe->comment)) 1.567 + < strlen(pe->comment)) { 1.568 + char *nsprErr; 1.569 + if (PR_GetErrorTextLength()) { 1.570 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.571 + PR_GetErrorText(nsprErr); 1.572 + } else { 1.573 + nsprErr = NULL; 1.574 + } 1.575 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.576 + nsprErr ? nsprErr : ""); 1.577 + if (nsprErr) 1.578 + PR_Free(nsprErr); 1.579 + errorCount++; 1.580 + exit(ERRX); 1.581 + } 1.582 + } 1.583 + 1.584 + /* Delete the structure */ 1.585 + dead = pe; 1.586 + pe = pe->next; 1.587 + if (dead->filename) { 1.588 + PORT_Free(dead->filename); 1.589 + } 1.590 + if (dead->comment) { 1.591 + PORT_Free(dead->comment); 1.592 + } 1.593 + PORT_Free(dead); 1.594 + } 1.595 + zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR); 1.596 + 1.597 + /* Create the ZipEnd structure */ 1.598 + PORT_Memset(&zipend, 0, sizeof(zipend)); 1.599 + longtox(ESIG, zipend.signature); 1.600 + inttox(entrycount, zipend.total_entries_disk); 1.601 + inttox(entrycount, zipend.total_entries_archive); 1.602 + longtox(zipfile->central_end - zipfile->central_start, 1.603 + zipend.central_dir_size); 1.604 + longtox(zipfile->central_start, zipend.offset_central_dir); 1.605 + if (zipfile->comment) { 1.606 + inttox(strlen(zipfile->comment), zipend.commentfield_len); 1.607 + } 1.608 + 1.609 + /* Write out ZipEnd xtructure */ 1.610 + if ( PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) { 1.611 + char *nsprErr; 1.612 + if (PR_GetErrorTextLength()) { 1.613 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.614 + PR_GetErrorText(nsprErr); 1.615 + } else { 1.616 + nsprErr = NULL; 1.617 + } 1.618 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.619 + nsprErr ? nsprErr : ""); 1.620 + if (nsprErr) 1.621 + PR_Free(nsprErr); 1.622 + errorCount++; 1.623 + exit(ERRX); 1.624 + } 1.625 + 1.626 + /* Write out Zipfile comment */ 1.627 + if (zipfile->comment) { 1.628 + if ( PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment)) 1.629 + < strlen(zipfile->comment)) { 1.630 + char *nsprErr; 1.631 + if (PR_GetErrorTextLength()) { 1.632 + nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1); 1.633 + PR_GetErrorText(nsprErr); 1.634 + } else { 1.635 + nsprErr = NULL; 1.636 + } 1.637 + PR_fprintf(errorFD, "Writing zip data: %s\n", 1.638 + nsprErr ? nsprErr : ""); 1.639 + if (nsprErr) 1.640 + PR_Free(nsprErr); 1.641 + errorCount++; 1.642 + exit(ERRX); 1.643 + } 1.644 + } 1.645 + 1.646 + PR_Close(zipfp); 1.647 + 1.648 + /* Free the memory of the zipfile structure */ 1.649 + if (zipfile->filename) { 1.650 + PORT_Free(zipfile->filename); 1.651 + } 1.652 + if (zipfile->comment) { 1.653 + PORT_Free(zipfile->comment); 1.654 + } 1.655 + PORT_Free(zipfile); 1.656 + 1.657 + return 0; 1.658 +} 1.659 + 1.660 + 1.661 +/********************************************** 1.662 + * i n t t o x 1.663 + * 1.664 + * Converts a two byte ugly endianed integer 1.665 + * to our platform's integer. 1.666 + * 1.667 + */ 1.668 + 1.669 +static void inttox (int in, char *out) 1.670 +{ 1.671 + out [0] = (in & 0xFF); 1.672 + out [1] = (in & 0xFF00) >> 8; 1.673 +} 1.674 + 1.675 + 1.676 +/********************************************* 1.677 + * l o n g t o x 1.678 + * 1.679 + * Converts a four byte ugly endianed integer 1.680 + * to our platform's integer. 1.681 + * 1.682 + */ 1.683 + 1.684 +static void longtox (long in, char *out) 1.685 +{ 1.686 + out [0] = (in & 0xFF); 1.687 + out [1] = (in & 0xFF00) >> 8; 1.688 + out [2] = (in & 0xFF0000) >> 16; 1.689 + out [3] = (in & 0xFF000000) >> 24; 1.690 +} 1.691 + 1.692 +