Back to index

lightning-sunbird  0.9+nobinonly
zip.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "signtool.h"
00038 #include "zip.h"
00039 #include "zlib.h"
00040 #include "prmem.h"
00041 
00042 static void   inttox (int in, char *out);
00043 static void   longtox (long in, char *out);
00044 
00045 /****************************************************************
00046  *
00047  * J z i p O p e n
00048  *
00049  * Opens a new ZIP file and creates a new ZIPfile structure to 
00050  * control the process of installing files into a zip.
00051  */
00052 ZIPfile*
00053 JzipOpen(char *filename, char *comment)
00054 {
00055     ZIPfile * zipfile;
00056     PRExplodedTime prtime;
00057 
00058     zipfile = PORT_ZAlloc(sizeof(ZIPfile));
00059     if (!zipfile) 
00060        out_of_memory();
00061 
00062     /* Construct time and date */
00063     PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime);
00064     zipfile->date =  ((prtime.tm_year - 1980) << 9) | 
00065                      ((prtime.tm_month + 1) << 5)   | 
00066                      prtime.tm_mday;
00067     zipfile->time =  (prtime.tm_hour << 11)   | 
00068                      (prtime.tm_min << 5)     | 
00069                      (prtime.tm_sec & 0x3f);
00070 
00071     zipfile->fp = NULL;
00072     if (filename  && 
00073         (zipfile->fp = PR_Open(filename,
00074         PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) == NULL) {
00075        char   *nsprErr;
00076        if (PR_GetErrorTextLength()) {
00077            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00078            PR_GetErrorText(nsprErr);
00079        } else {
00080            nsprErr = NULL;
00081        }
00082        PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n",
00083             PROGRAM_NAME,
00084            filename, nsprErr ? nsprErr : "");
00085        if (nsprErr) 
00086            PR_Free(nsprErr);
00087        errorCount++;
00088        exit (ERRX);
00089     }
00090 
00091     zipfile->list = NULL;
00092     if (filename) {
00093        zipfile->filename = PORT_ZAlloc(strlen(filename) + 1);
00094        if (!zipfile->filename) 
00095            out_of_memory();
00096        PORT_Strcpy(zipfile->filename, filename);
00097     }
00098     if (comment) {
00099        zipfile->comment = PORT_ZAlloc(strlen(comment) + 1);
00100        if (!zipfile->comment) 
00101            out_of_memory();
00102        PORT_Strcpy(zipfile->comment, comment);
00103     }
00104 
00105     return zipfile;
00106 }
00107 
00108 
00109 static
00110 void*
00111 my_alloc_func(void*opaque, uInt items, uInt size)
00112 {
00113     return PORT_Alloc(items * size);
00114 }
00115 
00116 
00117 static
00118 void
00119 my_free_func(void*opaque, void*address)
00120 {
00121     PORT_Free(address);
00122 }
00123 
00124 
00125 static
00126 void
00127 handle_zerror(int err, char *msg)
00128 {
00129     if (!msg) {
00130        msg = "";
00131     }
00132 
00133     errorCount++; /* unless Z_OK...see below */
00134 
00135     switch (err) {
00136     case Z_OK:
00137        PR_fprintf(errorFD, "No error: %s\n", msg);
00138        errorCount--; /* this was incremented above */
00139        break;
00140     case Z_MEM_ERROR:
00141        PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg);
00142        break;
00143     case Z_STREAM_ERROR:
00144        PR_fprintf(errorFD, "Invalid compression level: %s\n", msg);
00145        break;
00146     case Z_VERSION_ERROR:
00147        PR_fprintf(errorFD, "Incompatible compression library version: %s\n",
00148             msg);
00149        break;
00150     case Z_DATA_ERROR:
00151        PR_fprintf(errorFD, "Compression data error: %s\n", msg);
00152        break;
00153     default:
00154        PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg);
00155        break;
00156     }
00157 }
00158 
00159 
00160 
00161 
00162 /****************************************************************
00163  *
00164  * J z i p A d d
00165  *
00166  * Adds a new file into a ZIP file.  The ZIP file must have already
00167  * been opened with JzipOpen.
00168  */
00169 int
00170 JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level)
00171 {
00172     ZIPentry * entry;
00173     PRFileDesc * readfp;
00174     PRFileDesc * zipfp;
00175     unsigned long crc;
00176     unsigned long local_size_pos;
00177     int                 num;
00178     int                 err;
00179     int                 deflate_percent;
00180     z_stream      zstream;
00181     Bytef         inbuf[BUFSIZ];
00182     Bytef         outbuf[BUFSIZ];
00183 
00184 
00185     if ( !fullname || !filename || !zipfile) {
00186        return - 1;
00187     }
00188 
00189     zipfp = zipfile->fp;
00190     if (!zipfp)
00191        return - 1;
00192 
00193 
00194     if ( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) {
00195        char   *nsprErr;
00196        if (PR_GetErrorTextLength()) {
00197            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00198            PR_GetErrorText(nsprErr);
00199        } else {
00200            nsprErr = NULL;
00201        }
00202        PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr :
00203            "");
00204        errorCount++;
00205        if (nsprErr) 
00206            PR_Free(nsprErr);
00207        exit(ERRX);
00208     }
00209 
00210     /*
00211      * Make sure the input file is not the output file.
00212      * Add a few bytes to the end of the JAR file and see if the input file
00213      * twitches
00214      */
00215      {
00216        PRInt32 endOfJar;
00217        PRInt32 inputSize;
00218        PRBool isSame;
00219 
00220        inputSize = PR_Available(readfp);
00221 
00222        endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
00223 
00224        if (PR_Write(zipfp, "abcde", 5) < 5) {
00225            char      *nsprErr;
00226 
00227            if (PR_GetErrorTextLength()) {
00228               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00229               PR_GetErrorText(nsprErr);
00230            } else {
00231               nsprErr = NULL;
00232            }
00233            PR_fprintf(errorFD, "Writing to zip file: %s\n",
00234                nsprErr ? nsprErr : "");
00235            if (nsprErr) 
00236               PR_Free(nsprErr);
00237            errorCount++;
00238            exit(ERRX);
00239        }
00240 
00241        isSame = (PR_Available(readfp) != inputSize);
00242 
00243        PR_Seek(zipfp, endOfJar, PR_SEEK_SET);
00244 
00245        if (isSame) {
00246            /* It's the same file! Forget it! */
00247            PR_Close(readfp);
00248            return 0;
00249        }
00250     }
00251 
00252     if (verbosity >= 0) {
00253        PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename);
00254     }
00255 
00256     entry = PORT_ZAlloc(sizeof(ZIPentry));
00257     if (!entry) 
00258        out_of_memory();
00259 
00260     entry->filename = PORT_Strdup(filename);
00261     entry->comment = NULL;
00262 
00263     /* Set up local file header */
00264     longtox(LSIG, entry->local.signature);
00265     inttox(strlen(filename), entry->local.filename_len);
00266     inttox(zipfile->time, entry->local.time);
00267     inttox(zipfile->date, entry->local.date);
00268     inttox(Z_DEFLATED, entry->local.method);
00269 
00270     /* Set up central directory entry */
00271     longtox(CSIG, entry->central.signature);
00272     inttox(strlen(filename), entry->central.filename_len);
00273     if (entry->comment) {
00274        inttox(strlen(entry->comment), entry->central.commentfield_len);
00275     }
00276     longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR),
00277         entry->central.localhdr_offset);
00278     inttox(zipfile->time, entry->central.time);
00279     inttox(zipfile->date, entry->central.date);
00280     inttox(Z_DEFLATED, entry->central.method);
00281 
00282     /* Compute crc.  Too bad we have to process the whole file to do this*/
00283     crc = crc32(0L, NULL, 0);
00284     while ( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
00285        crc = crc32(crc, inbuf, num);
00286     }
00287     PR_Seek(readfp, 0L, PR_SEEK_SET);
00288 
00289     /* Store CRC */
00290     longtox(crc, entry->local.crc32);
00291     longtox(crc, entry->central.crc32);
00292 
00293     /* Stick this entry onto the end of the list */
00294     entry->next = NULL;
00295     if ( zipfile->list == NULL ) {
00296        /* First entry */
00297        zipfile->list = entry;
00298     } else {
00299        ZIPentry * pe;
00300 
00301        pe = zipfile->list;
00302        while (pe->next != NULL) {
00303            pe = pe->next;
00304        }
00305        pe->next = entry;
00306     }
00307 
00308     /*
00309      * Start writing stuff out
00310      */
00311 
00312     local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18;
00313     /* File header */
00314     if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal ))
00315          < sizeof(struct ZipLocal )) {
00316        char   *nsprErr;
00317        if (PR_GetErrorTextLength()) {
00318            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00319            PR_GetErrorText(nsprErr);
00320        } else {
00321            nsprErr = NULL;
00322        }
00323        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr :
00324            "");
00325        if (nsprErr) 
00326            PR_Free(nsprErr);
00327        errorCount++;
00328        exit(ERRX);
00329     }
00330 
00331     /* File Name */
00332     if ( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) {
00333        char   *nsprErr;
00334        if (PR_GetErrorTextLength()) {
00335            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00336            PR_GetErrorText(nsprErr);
00337        } else {
00338            nsprErr = NULL;
00339        }
00340        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr :
00341            "");
00342        if (nsprErr) 
00343            PR_Free(nsprErr);
00344        errorCount++;
00345        exit(ERRX);
00346     }
00347 
00348     /*
00349      * File data
00350      */
00351     /* Initialize zstream */
00352     zstream.zalloc = my_alloc_func;
00353     zstream.zfree = my_free_func;
00354     zstream.opaque = NULL;
00355     zstream.next_in = inbuf;
00356     zstream.avail_in = BUFSIZ;
00357     zstream.next_out = outbuf;
00358     zstream.avail_out = BUFSIZ;
00359     /* Setting the windowBits to -MAX_WBITS is an undocumented feature of
00360      * zlib (see deflate.c in zlib).  It is the same thing that Java does
00361      * when you specify the nowrap option for deflation in java.util.zip.
00362      * It causes zlib to leave out its headers and footers, which don't
00363      * work in PKZIP files.
00364      */
00365     err = deflateInit2(&zstream, compression_level, Z_DEFLATED,
00366                      -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY);
00367     if (err != Z_OK) {
00368        handle_zerror(err, zstream.msg);
00369        exit(ERRX);
00370     }
00371 
00372     while ( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
00373        zstream.next_in = inbuf;
00374        /* Process this chunk of data */
00375        while (zstream.avail_in > 0) {
00376            err = deflate(&zstream, Z_NO_FLUSH);
00377            if (err != Z_OK) {
00378               handle_zerror(err, zstream.msg);
00379               exit(ERRX);
00380            }
00381            if (zstream.avail_out <= 0) {
00382               if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
00383                   char      *nsprErr;
00384                   if (PR_GetErrorTextLength()) {
00385                      nsprErr = PR_Malloc(PR_GetErrorTextLength());
00386                      PR_GetErrorText(nsprErr);
00387                   } else {
00388                      nsprErr = NULL;
00389                   }
00390                   PR_fprintf(errorFD, "Writing zip data: %s\n",
00391                                    nsprErr ? nsprErr : "");
00392                   if (nsprErr) 
00393                      PR_Free(nsprErr);
00394                   errorCount++;
00395                   exit(ERRX);
00396               }
00397               zstream.next_out = outbuf;
00398               zstream.avail_out = BUFSIZ;
00399            }
00400        }
00401     }
00402 
00403     /* Now flush everything */
00404     while (1) {
00405        err = deflate(&zstream, Z_FINISH);
00406        if (err == Z_STREAM_END) {
00407            break;
00408        } else if (err == Z_OK) {
00409            /* output buffer full, repeat */
00410        } else {
00411            handle_zerror(err, zstream.msg);
00412            exit(ERRX);
00413        }
00414        if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
00415            char      *nsprErr;
00416            if (PR_GetErrorTextLength()) {
00417               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00418               PR_GetErrorText(nsprErr);
00419            } else {
00420               nsprErr = NULL;
00421            }
00422            PR_fprintf(errorFD, "Writing zip data: %s\n",
00423                             nsprErr ? nsprErr : "");
00424            if (nsprErr) 
00425               PR_Free(nsprErr);
00426            errorCount++;
00427            exit(ERRX);
00428        }
00429        zstream.avail_out = BUFSIZ;
00430        zstream.next_out = outbuf;
00431     }
00432 
00433     /* If there's any output left, write it out. */
00434     if (zstream.next_out != outbuf) {
00435        if ( PR_Write(zipfp, outbuf, zstream.next_out - outbuf) <
00436            zstream.next_out - outbuf) {
00437            char      *nsprErr;
00438            if (PR_GetErrorTextLength()) {
00439               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00440               PR_GetErrorText(nsprErr);
00441            } else {
00442               nsprErr = NULL;
00443            }
00444            PR_fprintf(errorFD, "Writing zip data: %s\n",
00445                             nsprErr ? nsprErr : "");
00446            if (nsprErr) 
00447               PR_Free(nsprErr);
00448            errorCount++;
00449            exit(ERRX);
00450        }
00451        zstream.avail_out = BUFSIZ;
00452        zstream.next_out = outbuf;
00453     }
00454 
00455     /* Now that we know the compressed size, write this to the headers */
00456     longtox(zstream.total_in, entry->local.orglen);
00457     longtox(zstream.total_out, entry->local.size);
00458     if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) {
00459        char   *nsprErr;
00460        if (PR_GetErrorTextLength()) {
00461            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00462            PR_GetErrorText(nsprErr);
00463        } else {
00464            nsprErr = NULL;
00465        }
00466        PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
00467        if (nsprErr) 
00468            PR_Free(nsprErr);
00469        errorCount++;
00470        exit(ERRX);
00471     }
00472     if ( PR_Write(zipfp, entry->local.size, 8) != 8) {
00473        char   *nsprErr;
00474        if (PR_GetErrorTextLength()) {
00475            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00476            PR_GetErrorText(nsprErr);
00477        } else {
00478            nsprErr = NULL;
00479        }
00480        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
00481        if (nsprErr) 
00482            PR_Free(nsprErr);
00483        errorCount++;
00484        exit(ERRX);
00485     }
00486     if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) {
00487        char   *nsprErr;
00488        if (PR_GetErrorTextLength()) {
00489            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00490            PR_GetErrorText(nsprErr);
00491        } else {
00492            nsprErr = NULL;
00493        }
00494        PR_fprintf(errorFD, "Accessing zip file: %s\n", 
00495                          nsprErr ? nsprErr : "");
00496        if (nsprErr) 
00497            PR_Free(nsprErr);
00498        errorCount++;
00499        exit(ERRX);
00500     }
00501     longtox(zstream.total_in, entry->central.orglen);
00502     longtox(zstream.total_out, entry->central.size);
00503 
00504     /* Close out the deflation operation */
00505     err = deflateEnd(&zstream);
00506     if (err != Z_OK) {
00507        handle_zerror(err, zstream.msg);
00508        exit(ERRX);
00509     }
00510 
00511     PR_Close(readfp);
00512 
00513     if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) {
00514        deflate_percent = (int) 
00515            ((zstream.total_in - zstream.total_out) *100 / zstream.total_in);
00516     } else {
00517        deflate_percent = 0;
00518     }
00519     if (verbosity >= 0) {
00520        PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent);
00521     }
00522 
00523     return 0;
00524 }
00525 
00526 
00527 /********************************************************************
00528  * J z i p C l o s e
00529  *
00530  * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!!
00531  */
00532 int
00533 JzipClose(ZIPfile *zipfile)
00534 {
00535     ZIPentry * pe, *dead;
00536     PRFileDesc * zipfp;
00537     struct ZipEnd zipend;
00538     unsigned int     entrycount = 0;
00539 
00540     if (!zipfile) {
00541        return - 1;
00542     }
00543 
00544     if (!zipfile->filename) {
00545        /* bogus */
00546        return 0;
00547     }
00548 
00549     zipfp = zipfile->fp;
00550     zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
00551 
00552     /* Write out all the central directories */
00553     pe = zipfile->list;
00554     while (pe) {
00555        entrycount++;
00556 
00557        /* Write central directory info */
00558        if ( PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral ))
00559             < sizeof(struct ZipCentral )) {
00560            char      *nsprErr;
00561            if (PR_GetErrorTextLength()) {
00562               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00563               PR_GetErrorText(nsprErr);
00564            } else {
00565               nsprErr = NULL;
00566            }
00567            PR_fprintf(errorFD, "Writing zip data: %s\n",
00568                             nsprErr ? nsprErr : "");
00569            if (nsprErr) 
00570               PR_Free(nsprErr);
00571            errorCount++;
00572            exit(ERRX);
00573        }
00574 
00575        /* Write filename */
00576        if ( PR_Write(zipfp, pe->filename, strlen(pe->filename))
00577             < strlen(pe->filename)) {
00578            char      *nsprErr;
00579            if (PR_GetErrorTextLength()) {
00580               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00581               PR_GetErrorText(nsprErr);
00582            } else {
00583               nsprErr = NULL;
00584            }
00585            PR_fprintf(errorFD, "Writing zip data: %s\n",
00586                             nsprErr ? nsprErr : "");
00587            if (nsprErr) 
00588               PR_Free(nsprErr);
00589            errorCount++;
00590            exit(ERRX);
00591        }
00592 
00593        /* Write file comment */
00594        if (pe->comment) {
00595            if ( PR_Write(zipfp, pe->comment, strlen(pe->comment))
00596                 < strlen(pe->comment)) {
00597               char   *nsprErr;
00598               if (PR_GetErrorTextLength()) {
00599                   nsprErr = PR_Malloc(PR_GetErrorTextLength());
00600                   PR_GetErrorText(nsprErr);
00601               } else {
00602                   nsprErr = NULL;
00603               }
00604               PR_fprintf(errorFD, "Writing zip data: %s\n",
00605                                        nsprErr ? nsprErr : "");
00606               if (nsprErr) 
00607                   PR_Free(nsprErr);
00608               errorCount++;
00609               exit(ERRX);
00610            }
00611        }
00612 
00613        /* Delete the structure */
00614        dead = pe;
00615        pe = pe->next;
00616        if (dead->filename) {
00617            PORT_Free(dead->filename);
00618        }
00619        if (dead->comment) {
00620            PORT_Free(dead->comment);
00621        }
00622        PORT_Free(dead);
00623     }
00624     zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR);
00625 
00626     /* Create the ZipEnd structure */
00627     PORT_Memset(&zipend, 0, sizeof(zipend));
00628     longtox(ESIG, zipend.signature);
00629     inttox(entrycount, zipend.total_entries_disk);
00630     inttox(entrycount, zipend.total_entries_archive);
00631     longtox(zipfile->central_end - zipfile->central_start,
00632            zipend.central_dir_size);
00633     longtox(zipfile->central_start, zipend.offset_central_dir);
00634     if (zipfile->comment) {
00635        inttox(strlen(zipfile->comment), zipend.commentfield_len);
00636     }
00637 
00638     /* Write out ZipEnd xtructure */
00639     if ( PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) {
00640        char   *nsprErr;
00641        if (PR_GetErrorTextLength()) {
00642            nsprErr = PR_Malloc(PR_GetErrorTextLength());
00643            PR_GetErrorText(nsprErr);
00644        } else {
00645            nsprErr = NULL;
00646        }
00647        PR_fprintf(errorFD, "Writing zip data: %s\n", 
00648                          nsprErr ? nsprErr : "");
00649        if (nsprErr) 
00650            PR_Free(nsprErr);
00651        errorCount++;
00652        exit(ERRX);
00653     }
00654 
00655     /* Write out Zipfile comment */
00656     if (zipfile->comment) {
00657        if ( PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment))
00658             < strlen(zipfile->comment)) {
00659            char      *nsprErr;
00660            if (PR_GetErrorTextLength()) {
00661               nsprErr = PR_Malloc(PR_GetErrorTextLength());
00662               PR_GetErrorText(nsprErr);
00663            } else {
00664               nsprErr = NULL;
00665            }
00666            PR_fprintf(errorFD, "Writing zip data: %s\n",
00667                             nsprErr ? nsprErr : "");
00668            if (nsprErr) 
00669               PR_Free(nsprErr);
00670            errorCount++;
00671            exit(ERRX);
00672        }
00673     }
00674 
00675     PR_Close(zipfp);
00676 
00677     /* Free the memory of the zipfile structure */
00678     if (zipfile->filename) {
00679        PORT_Free(zipfile->filename);
00680     }
00681     if (zipfile->comment) {
00682        PORT_Free(zipfile->comment);
00683     }
00684     PORT_Free(zipfile);
00685 
00686     return 0;
00687 }
00688 
00689 
00690 /**********************************************
00691  *  i n t t o x
00692  *
00693  *  Converts a two byte ugly endianed integer
00694  *  to our platform's integer.
00695  *
00696  */
00697 
00698 static void   inttox (int in, char *out)
00699 {
00700     out [0] = (in & 0xFF);
00701     out [1] = (in & 0xFF00) >> 8;
00702 }
00703 
00704 
00705 /*********************************************
00706  *  l o n g t o x
00707  *
00708  *  Converts a four byte ugly endianed integer
00709  *  to our platform's integer.
00710  *
00711  */
00712 
00713 static void   longtox (long in, char *out)
00714 {
00715     out [0] = (in & 0xFF);
00716     out [1] = (in & 0xFF00) >> 8;
00717     out [2] = (in & 0xFF0000) >> 16;
00718     out [3] = (in & 0xFF000000) >> 24;
00719 }
00720 
00721