Example #1
0
bool
GMPStorageParent::RecvRead(const nsCString& aRecordName)
{
  LOGD(("%s::%s: %p record=%s", __CLASS__, __FUNCTION__, this, aRecordName.get()));

  if (mShutdown) {
    return true;
  }

  PRFileDesc* fd = mFiles.Get(aRecordName);
  nsTArray<uint8_t> data;
  if (!fd) {
    unused << SendReadComplete(aRecordName, GMPClosedErr, data);
    return true;
  }

  int32_t len = PR_Seek(fd, 0, PR_SEEK_END);
  PR_Seek(fd, 0, PR_SEEK_SET);

  if (len > GMP_MAX_RECORD_SIZE) {
    // Refuse to read big records.
    unused << SendReadComplete(aRecordName, GMPQuotaExceededErr, data);
    return true;
  }
  data.SetLength(len);
  auto bytesRead = PR_Read(fd, data.Elements(), len);
  auto res = (bytesRead == len) ? GMPNoErr : GMPGenericErr;
  unused << SendReadComplete(aRecordName, res, data);

  return true;
}
Example #2
0
bool
ReadIntoArray(nsIFile* aFile,
              nsTArray<uint8_t>& aOutDst,
              size_t aMaxLength)
{
  if (!FileExists(aFile)) {
    return false;
  }

  PRFileDesc* fd = nullptr;
  nsresult rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
  if (NS_FAILED(rv)) {
    return false;
  }

  int32_t length = PR_Seek(fd, 0, PR_SEEK_END);
  PR_Seek(fd, 0, PR_SEEK_SET);

  if (length < 0 || (size_t)length > aMaxLength) {
    NS_WARNING("EME file is longer than maximum allowed length");
    PR_Close(fd);
    return false;
  }
  aOutDst.SetLength(length);
  int32_t bytesRead = PR_Read(fd, aOutDst.Elements(), length);
  PR_Close(fd);
  return (bytesRead == length);
}
Example #3
0
    nsresult ReadRecordMetadata(PRFileDesc* aFd,
                                int32_t& aOutRecordLength,
                                nsACString& aOutRecordName)
    {
        int32_t offset = PR_Seek(aFd, 0, PR_SEEK_END);
        PR_Seek(aFd, 0, PR_SEEK_SET);

        if (offset < 0 || offset > GMP_MAX_RECORD_SIZE) {
            // Refuse to read big records, or records where we can't get a length.
            return NS_ERROR_FAILURE;
        }
        const uint32_t fileLength = static_cast<uint32_t>(offset);

        // At the start of the file the length of the record name is stored in a
        // uint32_t (little endian byte order) followed by the record name at the
        // start of the file. The record name is not null terminated. The remainder
        // of the file is the record's data.

        if (fileLength < sizeof(uint32_t)) {
            // Record file doesn't have enough contents to store the record name
            // length. Fail.
            return NS_ERROR_FAILURE;
        }

        // Read length, and convert to host byte order.
        uint32_t recordNameLength = 0;
        char buf[sizeof(recordNameLength)] = { 0 };
        int32_t bytesRead = PR_Read(aFd, &buf, sizeof(recordNameLength));
        recordNameLength = LittleEndian::readUint32(buf);
        if (sizeof(recordNameLength) != bytesRead ||
                recordNameLength == 0 ||
                recordNameLength + sizeof(recordNameLength) > fileLength ||
                recordNameLength > GMP_MAX_RECORD_NAME_SIZE) {
            // Record file has invalid contents. Fail.
            return NS_ERROR_FAILURE;
        }

        nsCString recordName;
        recordName.SetLength(recordNameLength);
        bytesRead = PR_Read(aFd, recordName.BeginWriting(), recordNameLength);
        if ((uint32_t)bytesRead != recordNameLength) {
            // Read failed.
            return NS_ERROR_FAILURE;
        }

        MOZ_ASSERT(fileLength >= sizeof(recordNameLength) + recordNameLength);
        int32_t recordLength = fileLength - (sizeof(recordNameLength) + recordNameLength);

        aOutRecordLength = recordLength;
        aOutRecordName = recordName;

        // Read cursor should be positioned after the record name, before the record contents.
        if (PR_Seek(aFd, 0, PR_SEEK_CUR) != (int32_t)(sizeof(recordNameLength) + recordNameLength)) {
            NS_WARNING("Read cursor mismatch after ReadRecordMetadata()");
            return NS_ERROR_FAILURE;
        }

        return NS_OK;
    }
static void VerifyAndCleanup(void)
{
	PRUintn	i;
	PRInt32 nRead, rv;
	
	for (i=0; i<TBSIZE; i++)
		tbuf[i] = 0;
		
	rv = PR_Seek(t2,0,PR_SEEK_SET);
	PR_ASSERT(rv == 0);	

	nRead = PR_Read((PRFileDesc*)t2, tbuf, TBSIZE);
	PR_ASSERT(nRead == TBSIZE);	
   		
	for (i=0; i<TBSIZE; i++)
		if (tbuf[i] != (PRUint8)i) {
			if (debug_mode) printf("data mismatch for index= %d \n", i);
			else failed_already=1;
		}
   	PR_Close(t1);
   	PR_Close(t2);

   	PR_Delete("t1.tmp");
   	PR_Delete("t2.tmp");

    if (debug_mode) printf("fileio test passed\n");
}
Example #5
0
xptiAutoLog::xptiAutoLog(xptiInterfaceInfoManager* mgr, 
                         nsILocalFile* logfile, PRBool append)
    : mMgr(nsnull), mOldFileDesc(nsnull)
{
    MOZ_COUNT_CTOR(xptiAutoLog);

    if(mgr && logfile)
    {
        PRFileDesc* fd;
        if(NS_SUCCEEDED(logfile->
                    OpenNSPRFileDesc(PR_WRONLY | PR_CREATE_FILE | PR_APPEND |
                                             (append ? 0 : PR_TRUNCATE),
                                             0666, &fd)) && fd)
        {
#ifdef DEBUG
            m_DEBUG_FileDesc = fd;
#endif
            mMgr = mgr;
            mOldFileDesc = mMgr->SetOpenLogFile(fd);
            if(append)
                PR_Seek(fd, 0, PR_SEEK_END);
            WriteTimestamp(fd, "++++ start logging ");

        }
        else
        {
#ifdef DEBUG
        printf("xpti failed to open log file for writing\n");
#endif
        }
    }
}
Example #6
0
streampos	
PRfilebuf::seekoff(streamoff offset, ios::seek_dir dir, int /* mode */)
{
    if (PR_GetDescType(_fd) == PR_DESC_FILE){
        PRSeekWhence fdir;
        PRInt32 retpos;
        switch (dir) {
            case ios::beg :
                fdir = PR_SEEK_SET;
                break;
            case ios::cur :
                fdir = PR_SEEK_CUR;
                break;
            case ios::end :
                fdir = PR_SEEK_END;
                break;
            default:
            // error
                return(EOF);
            }

        if (PRfilebuf::sync()==EOF)
            return EOF;
        if ((retpos=PR_Seek(_fd, offset, fdir))==-1L)
            return (EOF);
        return((streampos)retpos);
    }else
        return (EOF);
}
static nsresult
ReadFromFile(nsIFile* aPath,
             const nsACString& aFileName,
             nsACString& aOutData,
             int32_t aMaxLength)
{
  nsCOMPtr<nsIFile> path;
  nsresult rv = aPath->Clone(getter_AddRefs(path));
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  rv = path->AppendNative(aFileName);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  PRFileDesc* f = nullptr;
  rv = path->OpenNSPRFileDesc(PR_RDONLY | PR_CREATE_FILE, PR_IRWXU, &f);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  auto size = PR_Seek(f, 0, PR_SEEK_END);
  PR_Seek(f, 0, PR_SEEK_SET);

  if (size > aMaxLength) {
    return NS_ERROR_FAILURE;
  }
  aOutData.SetLength(size);

  auto len = PR_Read(f, aOutData.BeginWriting(), size);
  PR_Close(f);
  if (NS_WARN_IF(len != size)) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
Example #8
0
/*
 * replacement for fgets
 * This isn't like the real fgets.  It fills in 's' but strips off any
 * trailing linefeed character(s).  The return value is 0 if it went
 * okay.
 */
int PR_GetLine(PRFileDesc *fd, char *s, unsigned int n)
{
    PRInt32 start, newstart;
    int x;
    char *p;

    /* grab current location in file */
    start = PR_Seek(fd, 0, PR_SEEK_CUR);
    x = PR_Read(fd, s, n-1);
    if (x <= 0) return 1;   /* EOF or other error */
    s[x] = 0;
    p = strchr(s, '\n');
    if (p == NULL) p = strchr(s, '\r');
    if (p == NULL) {
        /* assume there was one anyway */
        return 0;
    }
    *p = 0;
    newstart = start+strlen(s)+1;
    if ((p != s) && (*(p-1) == '\r')) *(p-1) = 0;
    PR_Seek(fd, newstart, PR_SEEK_SET);
    return 0;
}
static void InitialSetup(void)
{
	PRUintn	i;
	PRInt32 nWritten, rv;
	
	t1 = PR_Open("t1.tmp", PR_CREATE_FILE | PR_RDWR, 0);
	PR_ASSERT(t1 != NULL);	
	
	for (i=0; i<TBSIZE; i++)
		tbuf[i] = i;
		
	nWritten = PR_Write((PRFileDesc*)t1, tbuf, TBSIZE);
	PR_ASSERT(nWritten == TBSIZE);	
   		
	rv = PR_Seek(t1,0,PR_SEEK_SET);
	PR_ASSERT(rv == 0);	

   	t2 = PR_Open("t2.tmp", PR_CREATE_FILE | PR_RDWR, 0);
	PR_ASSERT(t2 != NULL);	
}
Example #10
0
int 
PRfilebuf::sync()
{
    PRInt32 count; 

    if (_fd==0)
        return(EOF);

    if (!unbuffered()){
        // Sync write area
        if ((count=out_waiting())!=0){
            PRInt32 nout;
            if ((nout =PR_Write(_fd,
                               (void *) pbase(),
                               (unsigned int)count)) != count){
                if (nout > 0) {
                    // should set _pptr -= nout
                    pbump(-(int)nout);
                    memmove(pbase(), pbase()+nout, (int)(count-nout));
                }
                return(EOF);
            }
        }
        setp(0,0); // empty put area

        if (PR_GetDescType(_fd) == PR_DESC_FILE){
            // Sockets can't seek; don't need this
            if ((count=in_avail()) > 0){
                if (PR_Seek(_fd, -count, PR_SEEK_CUR)!=-1L)
                {
                    return (EOF);
                }
            }
        }
        setg(0,0,0); // empty get area
    }
    return(0);
}
Example #11
0
//---------------------------------------------
//  nsZipArchive::BuildFileList
//---------------------------------------------
nsresult nsZipArchive::BuildFileList()
{
  PRUint8   buf[4*BR_BUF_SIZE];

  //-----------------------------------------------------------------------
  // locate the central directory via the End record
  //-----------------------------------------------------------------------

  //-- get archive size using end pos
  PRInt32  pos = PR_Seek(mFd, 0, PR_SEEK_END);
#ifndef STANDALONE
  if (pos <= 0)
#else
  if (pos || ((pos = ftell(mFd)) <= 0))
#endif
    return ZIP_ERR_CORRUPT;

  PRBool bEndsigFound = PR_FALSE;
  while (!bEndsigFound)
  {
    //-- read backwards in 1K-sized chunks (unless file is less than 1K)
    PRInt32  bufsize = pos > BR_BUF_SIZE ? BR_BUF_SIZE : pos;
    pos -= bufsize;

    if (!ZIP_Seek(mFd, pos, PR_SEEK_SET))
      return ZIP_ERR_CORRUPT;

    if (PR_Read(mFd, buf, bufsize) != (READTYPE)bufsize)
      return ZIP_ERR_CORRUPT;

    //-- scan for ENDSIG
    PRUint8 *endp = buf + bufsize;
    for (endp -= ZIPEND_SIZE; endp >= buf; endp--)
    {
      if (xtolong(endp) == ENDSIG)
      { 
        //-- Seek to start of central directory
        PRInt32 central = xtolong(((ZipEnd *) endp)->offset_central_dir);
        if (!ZIP_Seek(mFd, central, PR_SEEK_SET))
          return ZIP_ERR_CORRUPT;

        bEndsigFound = PR_TRUE;
        break;
      }
    }

    if (bEndsigFound)
      break;

    if (pos <= 0)
      //-- We're at the beginning of the file, and still no sign
      //-- of the end signature.  File must be corrupted!
      return ZIP_ERR_CORRUPT;

    //-- backward read must overlap ZipEnd length
    pos += ZIPEND_SIZE;

  } /* while looking for end signature */


  //-------------------------------------------------------
  // read the central directory headers
  //-------------------------------------------------------
  PRInt32 byteCount = PR_Read(mFd, &buf, sizeof(buf));
  pos = 0;
  PRUint32 sig = xtolong(buf);
  while (sig == CENTRALSIG) {
    //-- make sure we've read enough
    if (byteCount - pos < ZIPCENTRAL_SIZE)
      return ZIP_ERR_CORRUPT;

    //-------------------------------------------------------
    // read the fixed-size data
    //-------------------------------------------------------
    ZipCentral* central = (ZipCentral*)(buf+pos);

    PRUint16 namelen = xtoint(central->filename_len);
    PRUint16 extralen = xtoint(central->extrafield_len);
    PRUint16 commentlen = xtoint(central->commentfield_len);

    //-- sanity check variable sizes and refuse to deal with
    //-- anything too big: it's likely a corrupt archive
    if (namelen > BR_BUF_SIZE || extralen > BR_BUF_SIZE || commentlen > 2*BR_BUF_SIZE)
      return ZIP_ERR_CORRUPT;

    nsZipItem* item = CreateZipItem(namelen);
    if (!item)
      return ZIP_ERR_MEMORY;

    item->headerOffset  = xtolong(central->localhdr_offset);
    item->dataOffset    = 0;
    item->size          = xtolong(central->size);
    item->realsize      = xtolong(central->orglen);
    item->crc32         = xtolong(central->crc32);
    item->time          = xtoint(central->time);
    item->date          = xtoint(central->date);
    item->isSynthetic   = PR_FALSE;
    item->hasDataOffset = PR_FALSE;

    PRUint16 compression = xtoint(central->method);
    item->compression   = (compression < UNSUPPORTED) ? (PRUint8)compression
                                                      : UNSUPPORTED;

    item->mode = ExtractMode(central->external_attributes);
#if defined(XP_UNIX) || defined(XP_BEOS)
    // Check if item is a symlink
    item->isSymlink = IsSymlink(central->external_attributes);
#endif

    pos += ZIPCENTRAL_SIZE;

    //-------------------------------------------------------
    // Make sure that remainder of this record (name, comments, extra)
    // and the next ZipCentral is all in the buffer
    //-------------------------------------------------------
    PRInt32 leftover = byteCount - pos;
    if (leftover < (namelen + extralen + commentlen + ZIPCENTRAL_SIZE)) {
      //-- not enough data left to process at top of loop.
      //-- move leftover and read more
      memcpy(buf, buf+pos, leftover);
      byteCount = leftover + PR_Read(mFd, buf+leftover, sizeof(buf)-leftover);
      pos = 0;

      if (byteCount < (namelen + extralen + commentlen + sizeof(sig))) {
        // truncated file
        return ZIP_ERR_CORRUPT;
      }
    }

    //-------------------------------------------------------
    // get the item name
    //-------------------------------------------------------
    memcpy(item->name, buf+pos, namelen);
    item->name[namelen] = 0;

    //-- an item whose name ends with '/' is a directory
    item->isDirectory = ('/' == item->name[namelen - 1]);

    //-- add item to file table
    //-- note that an explicit entry for a directory will override
    //-- a fake entry created for that directory (as in the case
    //-- of processing foo/bar.txt and then foo/) -- this will
    //-- preserve an explicit directory's metadata at the cost of
    //-- an extra nsZipItem (and that only happens if we process a
    //-- file inside that directory before processing the directory
    //-- entry itself)
    PRUint32 hash = HashName(item->name);
    item->next = mFiles[hash];
    mFiles[hash] = item;

    //-------------------------------------------------------
    // set up to process the next item at the top of loop
    //-------------------------------------------------------
    pos += namelen + extralen + commentlen;
    sig = xtolong(buf+pos);
  } /* while reading central directory records */

  if (sig != ENDSIG)
    return ZIP_ERR_CORRUPT;

  return ZIP_OK;
}
Example #12
0
PRIntn main(PRIntn argc, char *argv[])
{
    PRStatus    rc;
    PRInt32     rv;
    PRFileDesc  *fd;
    PRIntn      i;
    PRInt32     sum = 0;

    {   /* Get command line options */
        PLOptStatus os;
        PLOptState *opt = PL_CreateOptState(argc, argv, "vd");

	    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
        {
		    if (PL_OPT_BAD == os) continue;
            switch (opt->option)
            {
            case 'd':  /* debug */
                debug = 1;
                break;
            case 'v':  /* verbose */
                verbose = 1;
                break;
             default:
                break;
            }
        }
	    PL_DestroyOptState(opt);
    } /* end block "Get command line options" */
/* ---------------------------------------------------------------------- */
    fd = PR_Open( "/tmp/nsprAppend", (PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY), 0666 );
    if ( NULL == fd )  {
        if (debug) printf("PR_Open() failed for writing: %d\n", PR_GetError());
        failedAlready = PR_TRUE;
        goto Finished;
    }

    for ( i = 0; i < addedBytes ; i++ ) {
        rv = PR_Write( fd, &buf, sizeof(buf));
        if ( sizeof(buf) != rv )  {
            if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
            failedAlready = PR_TRUE;
            goto Finished;
        }
        rv = PR_Seek( fd, 0 , PR_SEEK_SET );
        if ( -1 == rv )  {
            if (debug) printf("PR_Seek() failed: %d\n", PR_GetError());
            failedAlready = PR_TRUE;
            goto Finished;
        }
    }
    rc = PR_Close( fd );
    if ( PR_FAILURE == rc ) {
        if (debug) printf("PR_Close() failed after writing: %d\n", PR_GetError());
        failedAlready = PR_TRUE;
        goto Finished;
    }
/* ---------------------------------------------------------------------- */
    fd = PR_Open( "/tmp/nsprAppend", PR_RDONLY, 0 );
    if ( NULL == fd )  {
        if (debug) printf("PR_Open() failed for reading: %d\n", PR_GetError());
        failedAlready = PR_TRUE;
        goto Finished;
    }

    for ( i = 0; i < addedBytes ; i++ ) {
        rv = PR_Read( fd, &inBuf, sizeof(inBuf));
        if ( sizeof(inBuf) != rv)  {
            if (debug) printf("PR_Write() failed: %d\n", PR_GetError());
            failedAlready = PR_TRUE;
            goto Finished;
        }
        sum += inBuf;
    }

    rc = PR_Close( fd );
    if ( PR_FAILURE == rc ) {
        if (debug) printf("PR_Close() failed after reading: %d\n", PR_GetError());
        failedAlready = PR_TRUE;
        goto Finished;
    }
    if ( sum != addedBytes )  {
        if (debug) printf("Uh Oh! addedBytes: %d. Sum: %d\n", addedBytes, sum);
        failedAlready = PR_TRUE;
        goto Finished;
    }

/* ---------------------------------------------------------------------- */
Finished:
    if (debug || verbose) printf("%s\n", (failedAlready)? "FAILED" : "PASSED" );
    return( (failedAlready)? 1 : 0 );
}  /* main() */
Example #13
0
/***********************************************************************
** PRIVATE FUNCTION:    Thread
** DESCRIPTION:
**   Hammer on the file I/O system
** INPUTS:      A pointer to the thread's private data
** OUTPUTS:     None
** RETURN:      None
** SIDE EFFECTS:
**      Creates, accesses and deletes a file
** RESTRICTIONS:
**      (Currently) must have file create permission in "/usr/tmp".
** MEMORY:      NA
** ALGORITHM:
**      This function is a root of a thread
**      1) Creates a (hopefully) unique file in /usr/tmp/
**      2) Writes a zero to a random number of sequential pages
**      3) Closes the file
**      4) Reopens the file
**      5) Seeks to a random page within the file
**      6) Writes a one byte on that page
**      7) Repeat steps [5..6] for each page in the file
**      8) Close and delete the file
**      9) Repeat steps [1..8] until told to stop
**     10) Notify complete and return
***********************************************************************/
static void PR_CALLBACK Thread(void *arg)
{
    PRUint32 index;
    char filename[30];
    const char zero = 0;
    PRFileDesc *file = NULL;
    PRStatus rv = PR_SUCCESS;
    Hammer_t *cd = (Hammer_t*)arg;

    (void)sprintf(filename, "%ssg%04ld.dat", baseName, cd->id);

    if (debug_mode) printf("Starting work on %s\n", filename);

    while (PR_TRUE)
    {
        PRUint32 bytes;
        PRUint32 minor = (Random() % cd->limit) + 1;
        PRUint32 random = (Random() % cd->limit) + 1;
        PRUint32 pages = (Random() % cd->limit) + 10;
        while (minor-- > 0)
        {
            cd->problem = sg_okay;
            if (cd->action != sg_go) goto finished;
            cd->problem = sg_open;
            file = PR_Open(filename, PR_RDWR|PR_CREATE_FILE, 0666);
            if (file == NULL) goto finished;
            for (index = 0; index < pages; index++)
            {
                cd->problem = sg_okay;
                if (cd->action != sg_go) goto close;
                cd->problem = sg_seek;
                bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
                if (bytes != pageSize * index) goto close;
                cd->problem = sg_write;
                bytes = PR_Write(file, &zero, sizeof(zero));
                if (bytes <= 0) goto close;
                cd->writes += 1;
            }
            cd->problem = sg_close;
            rv = PR_Close(file);
            if (rv != PR_SUCCESS) goto purge;

            cd->problem = sg_okay;
            if (cd->action != sg_go) goto purge;

            cd->problem = sg_open;
            file = PR_Open(filename, PR_RDWR, 0666);
            for (index = 0; index < pages; index++)
            {
                cd->problem = sg_okay;
                if (cd->action != sg_go) goto close;
                cd->problem = sg_seek;
                bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET);
                if (bytes != pageSize * index) goto close;
                cd->problem = sg_write;
                bytes = PR_Write(file, &zero, sizeof(zero));
                if (bytes <= 0) goto close;
                cd->writes += 1;
                random = (random + 511) % pages;
            }
            cd->problem = sg_close;
            rv = PR_Close(file);
            if (rv != PR_SUCCESS) goto purge;
            cd->problem = sg_delete;
            rv = PR_Delete(filename);
            if (rv != PR_SUCCESS) goto finished;
       }
    }

close:
    (void)PR_Close(file);
purge:
    (void)PR_Delete(filename);
finished:
    PR_Lock(cd->ml);
    cd->action = sg_done;
    PR_NotifyCondVar(cd->cv);
    PR_Unlock(cd->ml);

    if (debug_mode) printf("Ending work on %s\n", filename);

    return;
}  /* Thread */
Example #14
0
static PRBool
blapi_SHVerifyFile(const char *shName, PRBool self)
{
    char *checkName = NULL;
    PRFileDesc *checkFD = NULL;
    PRFileDesc *shFD = NULL;
    void  *hashcx = NULL;
    const SECHashObject *hashObj = NULL;
    SECItem signature = { 0, NULL, 0 };
    SECItem hash;
    int bytesRead, offset;
    SECStatus rv;
    DSAPublicKey key;
    int count;
#ifdef FREEBL_USE_PRELINK
    int pid = 0;
#endif

    PRBool result = PR_FALSE; /* if anything goes wrong,
			       * the signature does not verify */
    unsigned char buf[4096];
    unsigned char hashBuf[HASH_LENGTH_MAX];

    PORT_Memset(&key,0,sizeof(key));
    hash.data = hashBuf;
    hash.len = sizeof(hashBuf);

    /* If our integrity check was never ran or failed, fail any other 
     * integrity checks to prevent any token going into FIPS mode. */
    if (!self && (BL_FIPSEntryOK(PR_FALSE) != SECSuccess)) {
	return PR_FALSE;
    }

    if (!shName) {
	goto loser;
    }

    /* figure out the name of our check file */
    checkName = mkCheckFileName(shName);
    if (!checkName) {
	goto loser;
    }

    /* open the check File */
    checkFD = PR_Open(checkName, PR_RDONLY, 0);
    if (checkFD == NULL) {
#ifdef DEBUG_SHVERIFY
        fprintf(stderr, "Failed to open the check file %s: (%d, %d)\n",
                checkName, (int)PR_GetError(), (int)PR_GetOSError());
#endif /* DEBUG_SHVERIFY */
	goto loser;
    }

    /* read and Verify the headerthe header */
    bytesRead = PR_Read(checkFD, buf, 12);
    if (bytesRead != 12) {
	goto loser;
    }
    if ((buf[0] != NSS_SIGN_CHK_MAGIC1) || (buf[1] != NSS_SIGN_CHK_MAGIC2)) {
	goto loser;
    }
    if ((buf[2] != NSS_SIGN_CHK_MAJOR_VERSION) || 
				(buf[3] < NSS_SIGN_CHK_MINOR_VERSION)) {
	goto loser;
    }
#ifdef notdef
    if (decodeInt(&buf[8]) != CKK_DSA) {
	goto loser;
    }
#endif

    /* seek past any future header extensions */
    offset = decodeInt(&buf[4]);
    if (PR_Seek(checkFD, offset, PR_SEEK_SET) < 0) {
	goto loser;
    }

    /* read the key */
    rv = readItem(checkFD,&key.params.prime);
    if (rv != SECSuccess) {
	goto loser;
    }
    rv = readItem(checkFD,&key.params.subPrime);
    if (rv != SECSuccess) {
	goto loser;
    }
    rv = readItem(checkFD,&key.params.base);
    if (rv != SECSuccess) {
	goto loser;
    }
    rv = readItem(checkFD,&key.publicValue);
    if (rv != SECSuccess) {
	goto loser;
    }
    /* read the siganture */
    rv = readItem(checkFD,&signature);
    if (rv != SECSuccess) {
	goto loser;
    }

    /* done with the check file */
    PR_Close(checkFD);
    checkFD = NULL;

    hashObj = HASH_GetRawHashObject(PQG_GetHashType(&key.params));
    if (hashObj == NULL) {
	goto loser;
    }

    /* open our library file */
#ifdef FREEBL_USE_PRELINK
    shFD = bl_OpenUnPrelink(shName,&pid);
#else
    shFD = PR_Open(shName, PR_RDONLY, 0);
#endif
    if (shFD == NULL) {
#ifdef DEBUG_SHVERIFY
        fprintf(stderr, "Failed to open the library file %s: (%d, %d)\n",
                shName, (int)PR_GetError(), (int)PR_GetOSError());
#endif /* DEBUG_SHVERIFY */
	goto loser;
    }

    /* hash our library file with SHA1 */
    hashcx = hashObj->create();
    if (hashcx == NULL) {
	goto loser;
    }
    hashObj->begin(hashcx);

    count = 0;
    while ((bytesRead = PR_Read(shFD, buf, sizeof(buf))) > 0) {
	hashObj->update(hashcx, buf, bytesRead);
	count += bytesRead;
    }
#ifdef FREEBL_USE_PRELINK
    bl_CloseUnPrelink(shFD, pid);
#else
    PR_Close(shFD);
#endif
    shFD = NULL;

    hashObj->end(hashcx, hash.data, &hash.len, hash.len);


    /* verify the hash against the check file */
    if (DSA_VerifyDigest(&key, &signature, &hash) == SECSuccess) {
	result = PR_TRUE;
    }
#ifdef DEBUG_SHVERIFY
  {
        int i,j;
        fprintf(stderr,"File %s: %d bytes\n",shName, count);
        fprintf(stderr,"  hash: %d bytes\n", hash.len);
#define STEP 10
        for (i=0; i < hash.len; i += STEP) {
           fprintf(stderr,"   ");
           for (j=0; j < STEP && (i+j) < hash.len; j++) {
                fprintf(stderr," %02x", hash.data[i+j]);
           }
           fprintf(stderr,"\n");
        }
        fprintf(stderr,"  signature: %d bytes\n", signature.len);
        for (i=0; i < signature.len; i += STEP) {
           fprintf(stderr,"   ");
           for (j=0; j < STEP && (i+j) < signature.len; j++) {
                fprintf(stderr," %02x", signature.data[i+j]);
           }
           fprintf(stderr,"\n");
        }
	fprintf(stderr,"Verified : %s\n",result?"TRUE": "FALSE");
    }
#endif /* DEBUG_SHVERIFY */


loser:
    if (checkName != NULL) {
	PORT_Free(checkName);
    }
    if (checkFD != NULL) {
	PR_Close(checkFD);
    }
    if (shFD != NULL) {
	PR_Close(shFD);
    }
    if (hashcx != NULL) {
	if (hashObj) {
	    hashObj->destroy(hashcx,PR_TRUE);
	}
    }
    if (signature.data != NULL) {
	PORT_Free(signature.data);
    }
    if (key.params.prime.data != NULL) {
	PORT_Free(key.params.prime.data);
    }
    if (key.params.subPrime.data != NULL) {
	PORT_Free(key.params.subPrime.data);
    }
    if (key.params.base.data != NULL) {
	PORT_Free(key.params.base.data);
    }
    if (key.publicValue.data != NULL) {
	PORT_Free(key.publicValue.data);
    }

    return result;
}
Example #15
0
PR_IMPLEMENT(PRInt32) PR_EmulateSendFile(
    PRFileDesc *sd, PRSendFileData *sfd,
    PRTransmitFileFlags flags, PRIntervalTime timeout)
{
    PRInt32 rv, count = 0;
    PRInt32 rlen;
    const void * buffer;
    PRInt32 buflen;
    PRInt32 sendbytes, readbytes;
    char *buf;

#define _SENDFILE_BUFSIZE   (16 * 1024)

    buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE);
    if (buf == NULL) {
        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
        return -1;
    }

    /*
     * send header first
     */
    buflen = sfd->hlen;
    buffer = sfd->header;
    while (buflen) {
        rv = PR_Send(sd, buffer, buflen, 0, timeout);
        if (rv < 0) {
            /* PR_Send() has invoked PR_SetError(). */
            rv = -1;
            goto done;
        } else {
            count += rv;
            buffer = (const void*) ((const char*)buffer + rv);
            buflen -= rv;
        }
    }

    /*
     * send file next
     */
    if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) {
        rv = -1;
        goto done;
    }
    sendbytes = sfd->file_nbytes;
    if (sendbytes == 0) {
        /* send entire file */
        while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) {
            while (rlen) {
                char *bufptr = buf;

                rv =  PR_Send(sd, bufptr, rlen, 0, timeout);
                if (rv < 0) {
                    /* PR_Send() has invoked PR_SetError(). */
                    rv = -1;
                    goto done;
                } else {
                    count += rv;
                    bufptr = ((char*)bufptr + rv);
                    rlen -= rv;
                }
            }
        }
        if (rlen < 0) {
            /* PR_Read() has invoked PR_SetError(). */
            rv = -1;
            goto done;
        }
    } else {
        readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
        while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) {
            while (rlen) {
                char *bufptr = buf;

                rv =  PR_Send(sd, bufptr, rlen, 0, timeout);
                if (rv < 0) {
                    /* PR_Send() has invoked PR_SetError(). */
                    rv = -1;
                    goto done;
                } else {
                    count += rv;
                    sendbytes -= rv;
                    bufptr = ((char*)bufptr + rv);
                    rlen -= rv;
                }
            }
            readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE);
        }
        if (rlen < 0) {
            /* PR_Read() has invoked PR_SetError(). */
            rv = -1;
            goto done;
        } else if (sendbytes != 0) {
            /*
             * there are fewer bytes in file to send than specified
             */
            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
            rv = -1;
            goto done;
        }
    }

    /*
     * send trailer last
     */
    buflen = sfd->tlen;
    buffer = sfd->trailer;
    while (buflen) {
        rv =  PR_Send(sd, buffer, buflen, 0, timeout);
        if (rv < 0) {
            /* PR_Send() has invoked PR_SetError(). */
            rv = -1;
            goto done;
        } else {
            count += rv;
            buffer = (const void*) ((const char*)buffer + rv);
            buflen -= rv;
        }
    }
    rv = count;

done:
    if (buf)
        PR_DELETE(buf);
    if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET))
        PR_Close(sd);
    return rv;
}
Example #16
0
/********************************************************************
 * J z i p C l o s e
 *
 * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!!
 */
int
JzipClose(ZIPfile *zipfile)
{
    ZIPentry *pe, *dead;
    PRFileDesc *zipfp;
    struct ZipEnd zipend;
    unsigned int entrycount = 0;

    if (!zipfile) {
        return -1;
    }

    if (!zipfile->filename) {
        /* bogus */
        return 0;
    }

    zipfp = zipfile->fp;
    zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR);

    /* Write out all the central directories */
    pe = zipfile->list;
    while (pe) {
        entrycount++;

        /* Write central directory info */
        if (PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral)) <
            sizeof(struct ZipCentral)) {
            char *nsprErr;
            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing zip data: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }

        /* Write filename */
        if (PR_Write(zipfp, pe->filename, strlen(pe->filename)) <
            strlen(pe->filename)) {
            char *nsprErr;
            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing zip data: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }

        /* Write file comment */
        if (pe->comment) {
            if (PR_Write(zipfp, pe->comment, strlen(pe->comment)) <
                strlen(pe->comment)) {
                char *nsprErr;
                if (PR_GetErrorTextLength()) {
                    nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                    PR_GetErrorText(nsprErr);
                } else {
                    nsprErr = NULL;
                }
                PR_fprintf(errorFD, "Writing zip data: %s\n",
                           nsprErr ? nsprErr : "");
                if (nsprErr)
                    PR_Free(nsprErr);
                errorCount++;
                exit(ERRX);
            }
        }

        /* Delete the structure */
        dead = pe;
        pe = pe->next;
        if (dead->filename) {
            PORT_Free(dead->filename);
        }
        if (dead->comment) {
            PORT_Free(dead->comment);
        }
        PORT_Free(dead);
    }
    zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR);

    /* Create the ZipEnd structure */
    PORT_Memset(&zipend, 0, sizeof(zipend));
    longtox(ESIG, zipend.signature);
    inttox(entrycount, zipend.total_entries_disk);
    inttox(entrycount, zipend.total_entries_archive);
    longtox(zipfile->central_end - zipfile->central_start,
            zipend.central_dir_size);
    longtox(zipfile->central_start, zipend.offset_central_dir);
    if (zipfile->comment) {
        inttox(strlen(zipfile->comment), zipend.commentfield_len);
    }

    /* Write out ZipEnd xtructure */
    if (PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Writing zip data: %s\n",
                   nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }

    /* Write out Zipfile comment */
    if (zipfile->comment) {
        if (PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment)) <
            strlen(zipfile->comment)) {
            char *nsprErr;
            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing zip data: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }
    }

    PR_Close(zipfp);

    /* Free the memory of the zipfile structure */
    if (zipfile->filename) {
        PORT_Free(zipfile->filename);
    }
    if (zipfile->comment) {
        PORT_Free(zipfile->comment);
    }
    PORT_Free(zipfile);

    return 0;
}
Example #17
0
/****************************************************************
 *
 * J z i p A d d
 *
 * Adds a new file into a ZIP file.  The ZIP file must have already
 * been opened with JzipOpen.
 */
int
JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level)
{
    ZIPentry *entry;
    PRFileDesc *readfp;
    PRFileDesc *zipfp;
    unsigned long crc;
    unsigned long local_size_pos;
    int num;
    int err;
    int deflate_percent;
    z_stream zstream;
    Bytef inbuf[BUFSIZ];
    Bytef outbuf[BUFSIZ];

    if (!fullname || !filename || !zipfile) {
        return -1;
    }

    zipfp = zipfile->fp;
    if (!zipfp)
        return -1;

    if ((readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr : "");
        errorCount++;
        if (nsprErr)
            PR_Free(nsprErr);
        exit(ERRX);
    }

    /*
     * Make sure the input file is not the output file.
     * Add a few bytes to the end of the JAR file and see if the input file
     * twitches
     */
    {
        PRInt32 endOfJar;
        PRInt32 inputSize;
        PRBool isSame;

        inputSize = PR_Available(readfp);

        endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR);

        if (PR_Write(zipfp, "abcde", 5) < 5) {
            char *nsprErr;

            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing to zip file: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }

        isSame = (PR_Available(readfp) != inputSize);

        PR_Seek(zipfp, endOfJar, PR_SEEK_SET);

        if (isSame) {
            /* It's the same file! Forget it! */
            PR_Close(readfp);
            return 0;
        }
    }

    if (verbosity >= 0) {
        PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename);
    }

    entry = PORT_ZAlloc(sizeof(ZIPentry));
    if (!entry)
        out_of_memory();

    entry->filename = PORT_Strdup(filename);
    entry->comment = NULL;

    /* Set up local file header */
    longtox(LSIG, entry->local.signature);
    inttox(strlen(filename), entry->local.filename_len);
    inttox(zipfile->time, entry->local.time);
    inttox(zipfile->date, entry->local.date);
    inttox(Z_DEFLATED, entry->local.method);

    /* Set up central directory entry */
    longtox(CSIG, entry->central.signature);
    inttox(strlen(filename), entry->central.filename_len);
    if (entry->comment) {
        inttox(strlen(entry->comment), entry->central.commentfield_len);
    }
    longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR),
            entry->central.localhdr_offset);
    inttox(zipfile->time, entry->central.time);
    inttox(zipfile->date, entry->central.date);
    inttox(Z_DEFLATED, entry->central.method);

    /* Compute crc.  Too bad we have to process the whole file to do this*/
    crc = crc32(0L, NULL, 0);
    while ((num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
        crc = crc32(crc, inbuf, num);
    }
    PR_Seek(readfp, 0L, PR_SEEK_SET);

    /* Store CRC */
    longtox(crc, entry->local.crc32);
    longtox(crc, entry->central.crc32);

    /* Stick this entry onto the end of the list */
    entry->next = NULL;
    if (zipfile->list == NULL) {
        /* First entry */
        zipfile->list = entry;
    } else {
        ZIPentry *pe;

        pe = zipfile->list;
        while (pe->next != NULL) {
            pe = pe->next;
        }
        pe->next = entry;
    }

    /*
     * Start writing stuff out
     */

    local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18;
    /* File header */
    if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal)) <
        sizeof(struct ZipLocal)) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }

    /* File Name */
    if (PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }

    /*
     * File data
     */
    /* Initialize zstream */
    zstream.zalloc = my_alloc_func;
    zstream.zfree = my_free_func;
    zstream.opaque = NULL;
    zstream.next_in = inbuf;
    zstream.avail_in = BUFSIZ;
    zstream.next_out = outbuf;
    zstream.avail_out = BUFSIZ;
    /* Setting the windowBits to -MAX_WBITS is an undocumented feature of
     * zlib (see deflate.c in zlib).  It is the same thing that Java does
     * when you specify the nowrap option for deflation in java.util.zip.
     * It causes zlib to leave out its headers and footers, which don't
     * work in PKZIP files.
     */
    err = deflateInit2(&zstream, compression_level, Z_DEFLATED,
                       -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY);
    if (err != Z_OK) {
        handle_zerror(err, zstream.msg);
        exit(ERRX);
    }

    while ((zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
        zstream.next_in = inbuf;
        /* Process this chunk of data */
        while (zstream.avail_in > 0) {
            err = deflate(&zstream, Z_NO_FLUSH);
            if (err != Z_OK) {
                handle_zerror(err, zstream.msg);
                exit(ERRX);
            }
            if (zstream.avail_out <= 0) {
                if (PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
                    char *nsprErr;
                    if (PR_GetErrorTextLength()) {
                        nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                        PR_GetErrorText(nsprErr);
                    } else {
                        nsprErr = NULL;
                    }
                    PR_fprintf(errorFD, "Writing zip data: %s\n",
                               nsprErr ? nsprErr : "");
                    if (nsprErr)
                        PR_Free(nsprErr);
                    errorCount++;
                    exit(ERRX);
                }
                zstream.next_out = outbuf;
                zstream.avail_out = BUFSIZ;
            }
        }
    }

    /* Now flush everything */
    while (1) {
        err = deflate(&zstream, Z_FINISH);
        if (err == Z_STREAM_END) {
            break;
        } else if (err == Z_OK) {
            /* output buffer full, repeat */
        } else {
            handle_zerror(err, zstream.msg);
            exit(ERRX);
        }
        if (PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
            char *nsprErr;
            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing zip data: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }
        zstream.avail_out = BUFSIZ;
        zstream.next_out = outbuf;
    }

    /* If there's any output left, write it out. */
    if (zstream.next_out != outbuf) {
        if (PR_Write(zipfp, outbuf, zstream.next_out - outbuf) <
            zstream.next_out - outbuf) {
            char *nsprErr;
            if (PR_GetErrorTextLength()) {
                nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
                PR_GetErrorText(nsprErr);
            } else {
                nsprErr = NULL;
            }
            PR_fprintf(errorFD, "Writing zip data: %s\n",
                       nsprErr ? nsprErr : "");
            if (nsprErr)
                PR_Free(nsprErr);
            errorCount++;
            exit(ERRX);
        }
        zstream.avail_out = BUFSIZ;
        zstream.next_out = outbuf;
    }

    /* Now that we know the compressed size, write this to the headers */
    longtox(zstream.total_in, entry->local.orglen);
    longtox(zstream.total_out, entry->local.size);
    if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }
    if (PR_Write(zipfp, entry->local.size, 8) != 8) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }
    if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) {
        char *nsprErr;
        if (PR_GetErrorTextLength()) {
            nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
            PR_GetErrorText(nsprErr);
        } else {
            nsprErr = NULL;
        }
        PR_fprintf(errorFD, "Accessing zip file: %s\n",
                   nsprErr ? nsprErr : "");
        if (nsprErr)
            PR_Free(nsprErr);
        errorCount++;
        exit(ERRX);
    }
    longtox(zstream.total_in, entry->central.orglen);
    longtox(zstream.total_out, entry->central.size);

    /* Close out the deflation operation */
    err = deflateEnd(&zstream);
    if (err != Z_OK) {
        handle_zerror(err, zstream.msg);
        exit(ERRX);
    }

    PR_Close(readfp);

    if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) {
        deflate_percent = (int)((zstream.total_in -
                                 zstream.total_out) *
                                100 / zstream.total_in);
    } else {
        deflate_percent = 0;
    }
    if (verbosity >= 0) {
        PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent);
    }

    return 0;
}
int main(int argc, char **argv)
{
    PRStatus rv;
    PLOptStatus os;
    PRUint8 *buffer;
    PRFileDesc *file = NULL;
    const char *filename = "sync.dat";
    PRUint32 index, loops, iterations = 10, filesize = 10;
    PRIntn flags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
    PLOptState *opt = PL_CreateOptState(argc, argv, "hSK:c:");
    PRIntervalTime time, total = 0, shortest = 0x7fffffff, longest = 0;

    err = PR_GetSpecialFD(PR_StandardError);

    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    {
        if (PL_OPT_BAD == os) continue;
        switch (opt->option)
        {
        case 0:       /* Name of file to create */
            filename = opt->value;
            break;
        case 'S':       /* Use sych option on file */
            flags |= PR_SYNC;
            break;
        case 'K':       /* Size of file to write */
            filesize = atoi(opt->value);
            break;
        case 'c':       /* Number of iterations */
            iterations = atoi(opt->value);
            break;
        case 'h':       /* user wants some guidance */
        default:        /* user needs some guidance */
            Help();     /* so give him an earful */
            return 2;   /* but not a lot else */
        }
    }
    PL_DestroyOptState(opt);

    file = PR_Open(filename, flags, 0666);
    if (NULL == file)
    {
        PL_FPrintError(err, "Failed to open file");
        return 1;
    }

    buffer = (PRUint8*)PR_CALLOC(1024);
    if (NULL == buffer)
    {
        PL_FPrintError(err, "Cannot allocate buffer");
        return 1;
    }

    for (index = 0; index < sizeof(buffer); ++index)
        buffer[index] = (PRUint8)index;

    for (loops = 0; loops < iterations; ++loops)
    {
        time = PR_IntervalNow();
        for (index = 0; index < filesize; ++index)
        {
            PR_Write(file, buffer, 1024);
        }
        time = (PR_IntervalNow() - time);

        total += time;
        if (time < shortest) shortest = time;
        else if (time > longest) longest = time;
        if (0 != PR_Seek(file, 0, PR_SEEK_SET))
        {
           PL_FPrintError(err, "Rewinding file");
           return 1;
        }
    }

    total = total / iterations;
    PR_fprintf(
        err, "%u iterations over a %u kbyte %sfile: %u [%u] %u\n",
        iterations, filesize, ((flags & PR_SYNC) ? "SYNCH'd " : ""),
        PR_IntervalToMicroseconds(shortest),
        PR_IntervalToMicroseconds(total),
        PR_IntervalToMicroseconds(longest));

    PR_DELETE(buffer);
    rv = PR_Close(file);
    if (PR_SUCCESS != rv)
    {
        PL_FPrintError(err, "Closing file failed");
        return 1;
    }
    rv = PR_Delete(filename);
    if (PR_SUCCESS != rv)
    {
        PL_FPrintError(err, "Deleting file failed");
        return 1;
    }
    return 0;
}