mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 510844 - "Remove memcpy()s for compressed jar reading" [r=tglek]
This commit is contained in:
parent
c61ee4488f
commit
f37c1ed9ed
@ -339,7 +339,7 @@ nsJAR::GetInputStreamWithSpec(const nsACString& aJarDirSpec,
|
|||||||
if (!item || item->isDirectory) {
|
if (!item || item->isDirectory) {
|
||||||
rv = jis->InitDirectory(this, aJarDirSpec, aEntryName);
|
rv = jis->InitDirectory(this, aJarDirSpec, aEntryName);
|
||||||
} else {
|
} else {
|
||||||
rv = jis->InitFile(mZip.GetFD(item), item);
|
rv = jis->InitFile(this, item);
|
||||||
}
|
}
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
NS_RELEASE(*result);
|
NS_RELEASE(*result);
|
||||||
|
@ -59,43 +59,42 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream)
|
|||||||
*--------------------------------------------------------*/
|
*--------------------------------------------------------*/
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsJARInputStream::InitFile(nsZipHandle *aFd, nsZipItem *item)
|
nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv = NS_OK;
|
||||||
NS_ABORT_IF_FALSE(aFd, "Argument may not be null");
|
NS_ABORT_IF_FALSE(aJar, "Argument may not be null");
|
||||||
NS_ABORT_IF_FALSE(item, "Argument may not be null");
|
NS_ABORT_IF_FALSE(item, "Argument may not be null");
|
||||||
|
|
||||||
// Mark it as closed, in case something fails in initialisation
|
// Mark it as closed, in case something fails in initialisation
|
||||||
mClosed = PR_TRUE;
|
mClosed = true;
|
||||||
// Keep the important bits of nsZipItem only
|
|
||||||
mInSize = item->size;
|
|
||||||
|
|
||||||
//-- prepare for the compression type
|
//-- prepare for the compression type
|
||||||
switch (item->compression) {
|
switch (item->compression) {
|
||||||
case STORED:
|
case STORED:
|
||||||
|
mCompressed = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEFLATED:
|
case DEFLATED:
|
||||||
mInflate = (InflateStruct *) PR_Malloc(sizeof(InflateStruct));
|
mCompressed = true;
|
||||||
NS_ENSURE_TRUE(mInflate, NS_ERROR_OUT_OF_MEMORY);
|
rv = gZlibInit(&mZs);
|
||||||
|
|
||||||
rv = gZlibInit(&(mInflate->mZs));
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_OUT_OF_MEMORY);
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
|
||||||
mInflate->mOutSize = item->realsize;
|
mOutSize = item->realsize;
|
||||||
mInflate->mInCrc = item->crc32;
|
mInCrc = item->crc32;
|
||||||
mInflate->mOutCrc = crc32(0L, Z_NULL, 0);
|
mOutCrc = crc32(0L, Z_NULL, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-- Set filepointer to start of item
|
// Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
|
||||||
mFd.Open(aFd, item->dataOffset, item->size);
|
mFd = aJar->mZip.GetFD();
|
||||||
|
mZs.next_in = aJar->mZip.GetData(item);
|
||||||
|
mZs.avail_in = item->size;
|
||||||
|
mOutSize = item->realsize;
|
||||||
|
mDirectory = false;
|
||||||
// Open for reading
|
// Open for reading
|
||||||
mClosed = PR_FALSE;
|
mClosed = false;
|
||||||
mCurPos = 0;
|
mCurPos = 0;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -109,8 +108,9 @@ nsJARInputStream::InitDirectory(nsJAR* aJar,
|
|||||||
NS_ABORT_IF_FALSE(aDir, "Argument may not be null");
|
NS_ABORT_IF_FALSE(aDir, "Argument may not be null");
|
||||||
|
|
||||||
// Mark it as closed, in case something fails in initialisation
|
// Mark it as closed, in case something fails in initialisation
|
||||||
mClosed = PR_TRUE;
|
mClosed = true;
|
||||||
mDirectory = PR_TRUE;
|
mDirectory = true;
|
||||||
|
mCompressed = false;
|
||||||
|
|
||||||
// Keep the zipReader for getting the actual zipItems
|
// Keep the zipReader for getting the actual zipItems
|
||||||
mJar = aJar;
|
mJar = aJar;
|
||||||
@ -173,7 +173,7 @@ nsJARInputStream::InitDirectory(nsJAR* aJar,
|
|||||||
mBuffer.AppendLiteral("\n200: filename content-length last-modified file-type\n");
|
mBuffer.AppendLiteral("\n200: filename content-length last-modified file-type\n");
|
||||||
|
|
||||||
// Open for reading
|
// Open for reading
|
||||||
mClosed = PR_FALSE;
|
mClosed = false;
|
||||||
mCurPos = 0;
|
mCurPos = 0;
|
||||||
mArrPos = 0;
|
mArrPos = 0;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -187,10 +187,10 @@ nsJARInputStream::Available(PRUint32 *_retval)
|
|||||||
|
|
||||||
if (mDirectory)
|
if (mDirectory)
|
||||||
*_retval = mBuffer.Length();
|
*_retval = mBuffer.Length();
|
||||||
else if (mInflate)
|
else if (mCompressed)
|
||||||
*_retval = mInflate->mOutSize - mInflate->mZs.total_out;
|
*_retval = mOutSize - mZs.total_out;
|
||||||
else
|
else
|
||||||
*_retval = mInSize - mCurPos;
|
*_retval = mOutSize - mCurPos;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,41 +202,30 @@ nsJARInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aBytesRead)
|
|||||||
|
|
||||||
*aBytesRead = 0;
|
*aBytesRead = 0;
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
|
||||||
if (mClosed)
|
if (mClosed)
|
||||||
return rv;
|
return NS_OK;
|
||||||
|
|
||||||
if (mDirectory) {
|
if (mDirectory) {
|
||||||
rv = ReadDirectory(aBuffer, aCount, aBytesRead);
|
return ReadDirectory(aBuffer, aCount, aBytesRead);
|
||||||
} else {
|
}
|
||||||
if (mInflate) {
|
if (mCompressed) {
|
||||||
rv = ContinueInflate(aBuffer, aCount, aBytesRead);
|
return ContinueInflate(aBuffer, aCount, aBytesRead);
|
||||||
} else {
|
}
|
||||||
PRInt32 bytesRead = 0;
|
if (mFd) {
|
||||||
aCount = PR_MIN(aCount, mInSize - mCurPos);
|
PRUint32 count = PR_MIN(aCount, mOutSize - mCurPos);
|
||||||
if (aCount) {
|
memcpy(aBuffer, mZs.next_in + mCurPos, count);
|
||||||
bytesRead = mFd.Read(aBuffer, aCount);
|
mCurPos += count;
|
||||||
if (bytesRead < 0)
|
*aBytesRead = count;
|
||||||
return NS_ERROR_FILE_CORRUPTED;
|
|
||||||
mCurPos += bytesRead;
|
|
||||||
if ((PRUint32)bytesRead != aCount) {
|
|
||||||
// file is truncated or was lying about size, we're done
|
|
||||||
Close();
|
|
||||||
return NS_ERROR_FILE_CORRUPTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*aBytesRead = bytesRead;
|
|
||||||
}
|
|
||||||
// be aggressive about closing!
|
// be aggressive about closing!
|
||||||
// note that sometimes, we will close mFd before we've finished
|
// note that sometimes, we will close mFd before we've finished
|
||||||
// deflating - this is because zlib buffers the input
|
// deflating - this is because zlib buffers the input
|
||||||
// So, don't free the ReadBuf/InflateStruct yet.
|
// So, don't free the ReadBuf/InflateStruct yet.
|
||||||
// It is ok to close the fd multiple times (also in nsJARInputStream::Close())
|
// It is ok to close the fd multiple times (also in nsJARInputStream::Close())
|
||||||
if (mCurPos >= mInSize) {
|
if (mCurPos >= mZs.avail_in) {
|
||||||
mFd.Close();
|
mFd = nsnull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
@ -257,9 +246,9 @@ nsJARInputStream::IsNonBlocking(PRBool *aNonBlocking)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsJARInputStream::Close()
|
nsJARInputStream::Close()
|
||||||
{
|
{
|
||||||
PR_FREEIF(mInflate);
|
mClosed = true;
|
||||||
mClosed = PR_TRUE;
|
mFd = nsnull;
|
||||||
mFd.Close();
|
mJar = nsnull;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,56 +257,33 @@ nsJARInputStream::ContinueInflate(char* aBuffer, PRUint32 aCount,
|
|||||||
PRUint32* aBytesRead)
|
PRUint32* aBytesRead)
|
||||||
{
|
{
|
||||||
// No need to check the args, ::Read did that, but assert them at least
|
// No need to check the args, ::Read did that, but assert them at least
|
||||||
NS_ASSERTION(mInflate,"inflate data structure missing");
|
|
||||||
NS_ASSERTION(aBuffer,"aBuffer parameter must not be null");
|
NS_ASSERTION(aBuffer,"aBuffer parameter must not be null");
|
||||||
NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null");
|
NS_ASSERTION(aBytesRead,"aBytesRead parameter must not be null");
|
||||||
|
|
||||||
// Keep old total_out count
|
// Keep old total_out count
|
||||||
const PRUint32 oldTotalOut = mInflate->mZs.total_out;
|
const PRUint32 oldTotalOut = mZs.total_out;
|
||||||
|
|
||||||
// make sure we aren't reading too much
|
// make sure we aren't reading too much
|
||||||
mInflate->mZs.avail_out = (mInflate->mOutSize-oldTotalOut > aCount) ? aCount : mInflate->mOutSize-oldTotalOut;
|
mZs.avail_out = PR_MIN(aCount, (mOutSize-oldTotalOut));
|
||||||
mInflate->mZs.next_out = (unsigned char*)aBuffer;
|
mZs.next_out = (unsigned char*)aBuffer;
|
||||||
|
|
||||||
int zerr = Z_OK;
|
|
||||||
//-- inflate loop
|
|
||||||
while (mInflate->mZs.avail_out > 0 && zerr == Z_OK) {
|
|
||||||
|
|
||||||
if (mInflate->mZs.avail_in == 0 && mCurPos < mInSize) {
|
|
||||||
// time to fill the buffer!
|
|
||||||
PRUint32 bytesToRead = PR_MIN(mInSize - mCurPos, ZIP_BUFLEN);
|
|
||||||
|
|
||||||
PRInt32 bytesRead = mFd.Read(mInflate->mReadBuf, bytesToRead);
|
|
||||||
if (bytesRead < 0) {
|
|
||||||
zerr = Z_ERRNO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mCurPos += bytesRead;
|
|
||||||
|
|
||||||
// now set the state for 'inflate'
|
|
||||||
mInflate->mZs.next_in = mInflate->mReadBuf;
|
|
||||||
mInflate->mZs.avail_in = bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now inflate
|
|
||||||
zerr = inflate(&(mInflate->mZs), Z_SYNC_FLUSH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// now inflate
|
||||||
|
int zerr = inflate(&mZs, Z_SYNC_FLUSH);
|
||||||
if ((zerr != Z_OK) && (zerr != Z_STREAM_END))
|
if ((zerr != Z_OK) && (zerr != Z_STREAM_END))
|
||||||
return NS_ERROR_FILE_CORRUPTED;
|
return NS_ERROR_FILE_CORRUPTED;
|
||||||
|
|
||||||
*aBytesRead = (mInflate->mZs.total_out - oldTotalOut);
|
*aBytesRead = (mZs.total_out - oldTotalOut);
|
||||||
|
|
||||||
// Calculate the CRC on the output
|
// Calculate the CRC on the output
|
||||||
mInflate->mOutCrc = crc32(mInflate->mOutCrc, (unsigned char*)aBuffer, *aBytesRead);
|
mOutCrc = crc32(mOutCrc, (unsigned char*)aBuffer, *aBytesRead);
|
||||||
|
|
||||||
// be aggressive about ending the inflation
|
// be aggressive about ending the inflation
|
||||||
// for some reason we don't always get Z_STREAM_END
|
// for some reason we don't always get Z_STREAM_END
|
||||||
if (zerr == Z_STREAM_END || mInflate->mZs.total_out == mInflate->mOutSize) {
|
if (zerr == Z_STREAM_END || mZs.total_out == mOutSize) {
|
||||||
inflateEnd(&(mInflate->mZs));
|
inflateEnd(&mZs);
|
||||||
|
|
||||||
// stop returning valid data as soon as we know we have a bad CRC
|
// stop returning valid data as soon as we know we have a bad CRC
|
||||||
if (mInflate->mOutCrc != mInflate->mInCrc) {
|
if (mOutCrc != mInCrc) {
|
||||||
// asserting because while this rarely happens, you definitely
|
// asserting because while this rarely happens, you definitely
|
||||||
// want to catch it in debug builds!
|
// want to catch it in debug builds!
|
||||||
NS_NOTREACHED(0);
|
NS_NOTREACHED(0);
|
||||||
|
@ -53,45 +53,39 @@ class nsJARInputStream : public nsIInputStream
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsJARInputStream() :
|
nsJARInputStream() :
|
||||||
mInSize(0), mCurPos(0), mInflate(nsnull), mDirectory(0), mClosed(PR_FALSE)
|
mCurPos(0), mCompressed(false), mDirectory(false), mClosed(true)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~nsJARInputStream() {
|
~nsJARInputStream() { Close(); }
|
||||||
Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIINPUTSTREAM
|
NS_DECL_NSIINPUTSTREAM
|
||||||
|
|
||||||
// takes ownership of |fd|, even on failure
|
// takes ownership of |fd|, even on failure
|
||||||
nsresult InitFile(nsZipHandle *aFd, nsZipItem *item);
|
nsresult InitFile(nsJAR *aJar, nsZipItem *item);
|
||||||
|
|
||||||
nsresult InitDirectory(nsJAR *aJar,
|
nsresult InitDirectory(nsJAR *aJar,
|
||||||
const nsACString& aJarDirSpec,
|
const nsACString& aJarDirSpec,
|
||||||
const char* aDir);
|
const char* aDir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PRUint32 mInSize; // Size in original file
|
nsRefPtr<nsZipHandle> mFd; // handle for reading
|
||||||
PRUint32 mCurPos; // Current position in input
|
PRUint32 mCurPos; // Current position in input
|
||||||
|
PRUint32 mOutSize; // inflated size
|
||||||
struct InflateStruct {
|
PRUint32 mInCrc; // CRC as provided by the zipentry
|
||||||
PRUint32 mOutSize; // inflated size
|
PRUint32 mOutCrc; // CRC as calculated by me
|
||||||
PRUint32 mInCrc; // CRC as provided by the zipentry
|
z_stream mZs; // zip data structure
|
||||||
PRUint32 mOutCrc; // CRC as calculated by me
|
|
||||||
z_stream mZs; // zip data structure
|
|
||||||
unsigned char mReadBuf[ZIP_BUFLEN]; // Readbuffer to inflate from
|
|
||||||
};
|
|
||||||
struct InflateStruct * mInflate;
|
|
||||||
|
|
||||||
/* For directory reading */
|
/* For directory reading */
|
||||||
nsRefPtr<nsJAR> mJar; // string reference to zipreader
|
nsRefPtr<nsJAR> mJar; // string reference to zipreader
|
||||||
PRUint32 mNameLen; // length of dirname
|
PRUint32 mNameLen; // length of dirname
|
||||||
nsCAutoString mBuffer; // storage for generated text of stream
|
nsCString mBuffer; // storage for generated text of stream
|
||||||
PRUint32 mArrPos; // current position within mArray
|
PRUint32 mArrPos; // current position within mArray
|
||||||
nsTArray<nsCString> mArray; // array of names in (zip) directory
|
nsTArray<nsCString> mArray; // array of names in (zip) directory
|
||||||
PRPackedBool mDirectory; // is this a directory?
|
|
||||||
PRPackedBool mClosed; // Whether the stream is closed
|
bool mCompressed; // is this compressed?
|
||||||
nsSeekableZipHandle mFd; // handle for reading
|
bool mDirectory; // is this a directory?
|
||||||
|
bool mClosed; // Whether the stream is closed
|
||||||
|
|
||||||
nsresult ContinueInflate(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
|
nsresult ContinueInflate(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
|
||||||
nsresult ReadDirectory(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
|
nsresult ReadDirectory(char* aBuf, PRUint32 aCount, PRUint32* aBytesRead);
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define ZFILE_CREATE PR_WRONLY | PR_CREATE_FILE
|
|
||||||
#define READTYPE PRInt32
|
#define READTYPE PRInt32
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#include "nsISupportsUtils.h"
|
#include "nsISupportsUtils.h"
|
||||||
@ -173,7 +172,7 @@ zlibAlloc(void *opaque, uInt items, uInt size)
|
|||||||
PRUint32 realitems = items;
|
PRUint32 realitems = items;
|
||||||
if (size == 4 && items < BY4ALLOC_ITEMS)
|
if (size == 4 && items < BY4ALLOC_ITEMS)
|
||||||
realitems = BY4ALLOC_ITEMS;
|
realitems = BY4ALLOC_ITEMS;
|
||||||
return zallocator->Calloc(realitems, size);
|
return zallocator->Calloc(realitems, size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return calloc(items, size);
|
return calloc(items, size);
|
||||||
@ -228,13 +227,14 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
|
|||||||
return NS_ERROR_FILE_TOO_BIG;
|
return NS_ERROR_FILE_TOO_BIG;
|
||||||
|
|
||||||
PRFileMap *map = PR_CreateFileMap(fd, size, PR_PROT_READONLY);
|
PRFileMap *map = PR_CreateFileMap(fd, size, PR_PROT_READONLY);
|
||||||
|
|
||||||
if (!map)
|
if (!map)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
nsZipHandle *handle = new nsZipHandle();
|
nsZipHandle *handle = new nsZipHandle();
|
||||||
if (!handle)
|
if (!handle) {
|
||||||
|
PR_CloseFileMap(map);
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
handle->mFd = fd;
|
handle->mFd = fd;
|
||||||
handle->mMap = map;
|
handle->mMap = map;
|
||||||
@ -245,22 +245,17 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 nsZipHandle::Read(PRUint32 aPosition, void *aBuffer, PRUint32 aCount)
|
|
||||||
{
|
|
||||||
if (mLen < 0 || aPosition+aCount > (PRUint32) mLen)
|
|
||||||
return -1;
|
|
||||||
PRInt32 count = PR_MIN(aCount, mLen - aPosition);
|
|
||||||
memcpy(aBuffer, mFileData + aPosition, count);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsZipHandle::~nsZipHandle()
|
nsZipHandle::~nsZipHandle()
|
||||||
{
|
{
|
||||||
if (mFd) {
|
if (mFileData) {
|
||||||
PR_MemUnmap(mFileData, mLen);
|
PR_MemUnmap(mFileData, mLen);
|
||||||
PR_CloseFileMap(mMap);
|
PR_CloseFileMap(mMap);
|
||||||
|
mFileData = nsnull;
|
||||||
|
mMap = nsnull;
|
||||||
|
}
|
||||||
|
if (mFd) {
|
||||||
PR_Close(mFd);
|
PR_Close(mFd);
|
||||||
mFd = 0;
|
mFd = nsnull;
|
||||||
}
|
}
|
||||||
MOZ_COUNT_DTOR(nsZipHandle);
|
MOZ_COUNT_DTOR(nsZipHandle);
|
||||||
}
|
}
|
||||||
@ -326,6 +321,7 @@ nsresult nsZipArchive::CloseArchive()
|
|||||||
{
|
{
|
||||||
if (mFd) {
|
if (mFd) {
|
||||||
PL_FinishArenaPool(&mArena);
|
PL_FinishArenaPool(&mArena);
|
||||||
|
mFd = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAUTION:
|
// CAUTION:
|
||||||
@ -335,11 +331,8 @@ nsresult nsZipArchive::CloseArchive()
|
|||||||
// for all the nsZipItem in one shot. But if the ~nsZipItem is doing
|
// for all the nsZipItem in one shot. But if the ~nsZipItem is doing
|
||||||
// anything more than cleaning up memory, we should start calling it.
|
// anything more than cleaning up memory, we should start calling it.
|
||||||
// Let us also cleanup the mFiles table for re-use on the next 'open' call
|
// Let us also cleanup the mFiles table for re-use on the next 'open' call
|
||||||
for (int i = 0; i < ZIP_TABSIZE; i++) {
|
memset(mFiles, 0, sizeof(mFiles));
|
||||||
mFiles[i] = 0;
|
mBuiltSynthetics = false;
|
||||||
}
|
|
||||||
mFd = NULL;
|
|
||||||
mBuiltSynthetics = PR_FALSE;
|
|
||||||
return ZIP_OK;
|
return ZIP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,25 +381,17 @@ nsresult nsZipArchive::ExtractFile(nsZipItem *item, const char *outname,
|
|||||||
// so the item to be extracted should never be a directory
|
// so the item to be extracted should never be a directory
|
||||||
PR_ASSERT(!item->isDirectory);
|
PR_ASSERT(!item->isDirectory);
|
||||||
|
|
||||||
//-- move to the start of file's data
|
|
||||||
if (!MaybeReadItem(item))
|
|
||||||
return ZIP_ERR_CORRUPT;
|
|
||||||
|
|
||||||
nsSeekableZipHandle fd;
|
|
||||||
if (!fd.Open(mFd.get(), item->dataOffset, item->size))
|
|
||||||
return ZIP_ERR_CORRUPT;
|
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
//-- extract the file using the appropriate method
|
//-- extract the file using the appropriate method
|
||||||
switch(item->compression)
|
switch(item->compression)
|
||||||
{
|
{
|
||||||
case STORED:
|
case STORED:
|
||||||
rv = CopyItemToDisk(item->size, item->crc32, fd, aFd);
|
rv = CopyItemToDisk(item, aFd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEFLATED:
|
case DEFLATED:
|
||||||
rv = InflateItem(item, fd, aFd);
|
rv = InflateItem(item, aFd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -607,14 +592,12 @@ nsresult nsZipArchive::BuildFileList()
|
|||||||
return ZIP_ERR_MEMORY;
|
return ZIP_ERR_MEMORY;
|
||||||
|
|
||||||
item->headerOffset = xtolong(central->localhdr_offset);
|
item->headerOffset = xtolong(central->localhdr_offset);
|
||||||
item->dataOffset = 0;
|
|
||||||
item->size = xtolong(central->size);
|
item->size = xtolong(central->size);
|
||||||
item->realsize = xtolong(central->orglen);
|
item->realsize = xtolong(central->orglen);
|
||||||
item->crc32 = xtolong(central->crc32);
|
item->crc32 = xtolong(central->crc32);
|
||||||
item->time = xtoint(central->time);
|
item->time = xtoint(central->time);
|
||||||
item->date = xtoint(central->date);
|
item->date = xtoint(central->date);
|
||||||
item->isSynthetic = PR_FALSE;
|
item->isSynthetic = PR_FALSE;
|
||||||
item->hasDataOffset = PR_FALSE;
|
|
||||||
item->compression = PR_MIN(xtoint(central->method), UNSUPPORTED);
|
item->compression = PR_MIN(xtoint(central->method), UNSUPPORTED);
|
||||||
item->mode = ExtractMode(central->external_attributes);
|
item->mode = ExtractMode(central->external_attributes);
|
||||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||||
@ -652,7 +635,7 @@ nsresult nsZipArchive::BuildSynthetics()
|
|||||||
{
|
{
|
||||||
if (mBuiltSynthetics)
|
if (mBuiltSynthetics)
|
||||||
return ZIP_OK;
|
return ZIP_OK;
|
||||||
mBuiltSynthetics = PR_TRUE;
|
mBuiltSynthetics = true;
|
||||||
|
|
||||||
// Create synthetic entries for any missing directories.
|
// Create synthetic entries for any missing directories.
|
||||||
// Do this when all ziptable has scanned to prevent double entries.
|
// Do this when all ziptable has scanned to prevent double entries.
|
||||||
@ -737,91 +720,68 @@ nsresult nsZipArchive::BuildSynthetics()
|
|||||||
return ZIP_OK;
|
return ZIP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsZipHandle* nsZipArchive::GetFD(nsZipItem* aItem)
|
nsZipHandle* nsZipArchive::GetFD()
|
||||||
{
|
{
|
||||||
if (!mFd || !MaybeReadItem(aItem))
|
if (!mFd)
|
||||||
return NULL;
|
return NULL;
|
||||||
return mFd.get();
|
return mFd.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// nsZipArchive::MaybeReadItem
|
// nsZipArchive::GetData
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
bool nsZipArchive::MaybeReadItem(nsZipItem* aItem)
|
PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
|
||||||
{
|
{
|
||||||
PR_ASSERT (aItem);
|
PR_ASSERT (aItem);
|
||||||
|
|
||||||
//-- the first time an item is used we need to calculate its offset
|
//-- read local header to get variable length values and calculate
|
||||||
if (!aItem->hasDataOffset)
|
//-- the real data offset
|
||||||
{
|
if (aItem->headerOffset + ZIPLOCAL_SIZE > mFd->mLen)
|
||||||
//-- read local header to get variable length values and calculate
|
return nsnull;
|
||||||
//-- the real data offset
|
|
||||||
//--
|
|
||||||
//-- NOTE: extralen is different in central header and local header
|
|
||||||
//-- for archives created using the Unix "zip" utility. To set
|
|
||||||
//-- the offset accurately we need the _local_ extralen.
|
|
||||||
if (!mFd || !mFd->mLen > aItem->headerOffset + ZIPLOCAL_SIZE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ZipLocal *Local = (ZipLocal*)(mFd->mFileData + aItem->headerOffset);
|
// -- check signature before using the structure, in case the zip file is corrupt
|
||||||
//check limits here
|
ZipLocal* Local = (ZipLocal*)(mFd->mFileData + aItem->headerOffset);
|
||||||
if ((xtolong(Local->signature) != LOCALSIG))
|
if ((xtolong(Local->signature) != LOCALSIG))
|
||||||
{
|
return nsnull;
|
||||||
//-- read error or local header not found
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aItem->dataOffset = aItem->headerOffset +
|
//-- NOTE: extralen is different in central header and local header
|
||||||
|
//-- for archives created using the Unix "zip" utility. To set
|
||||||
|
//-- the offset accurately we need the _local_ extralen.
|
||||||
|
PRUint32 dataOffset = aItem->headerOffset +
|
||||||
ZIPLOCAL_SIZE +
|
ZIPLOCAL_SIZE +
|
||||||
xtoint(Local->filename_len) +
|
xtoint(Local->filename_len) +
|
||||||
xtoint(Local->extrafield_len);
|
xtoint(Local->extrafield_len);
|
||||||
aItem->hasDataOffset = PR_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
// -- check if there is enough source data in the file
|
||||||
|
if (dataOffset + aItem->size > mFd->mLen)
|
||||||
|
return nsnull;
|
||||||
|
|
||||||
|
return mFd->mFileData + dataOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// nsZipArchive::CopyItemToDisk
|
// nsZipArchive::CopyItemToDisk
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
nsresult
|
nsresult
|
||||||
nsZipArchive::CopyItemToDisk(PRUint32 itemSize, PRUint32 itemCrc,
|
nsZipArchive::CopyItemToDisk(nsZipItem *item, PRFileDesc* outFD)
|
||||||
nsSeekableZipHandle &fd, PRFileDesc* outFD)
|
|
||||||
/*
|
|
||||||
* This function copies an archive item to disk, to the
|
|
||||||
* file specified by outFD. If outFD is zero, the extracted data is
|
|
||||||
* not written, only checked for CRC, so this is in effect same as 'Test'.
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
PRUint32 chunk, pos, crc;
|
PR_ASSERT(item);
|
||||||
char buf[ZIP_BUFLEN];
|
|
||||||
|
|
||||||
//-- initialize crc
|
//-- get to the start of file's data
|
||||||
crc = crc32(0L, Z_NULL, 0);
|
const PRUint8* itemData = GetData(item);
|
||||||
|
if (!itemData)
|
||||||
|
return ZIP_ERR_CORRUPT;
|
||||||
|
|
||||||
//-- copy chunks until file is done
|
if (outFD && PR_Write(outFD, itemData, item->size) < (READTYPE)item->size)
|
||||||
for (pos = 0; pos < itemSize; pos += chunk)
|
|
||||||
{
|
{
|
||||||
chunk = (itemSize - pos < ZIP_BUFLEN) ? (itemSize - pos) : ZIP_BUFLEN;
|
//-- Couldn't write all the data (disk full?)
|
||||||
|
return ZIP_ERR_DISK;
|
||||||
if (fd.Read(buf, chunk) != (READTYPE)chunk)
|
|
||||||
{
|
|
||||||
//-- unexpected end of data in archive
|
|
||||||
return ZIP_ERR_CORRUPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-- incrementally update crc32
|
|
||||||
crc = crc32(crc, (const unsigned char*)buf, chunk);
|
|
||||||
|
|
||||||
if (outFD && PR_Write(outFD, buf, chunk) < (READTYPE)chunk)
|
|
||||||
{
|
|
||||||
//-- Couldn't write all the data (disk full?)
|
|
||||||
return ZIP_ERR_DISK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-- Calculate crc
|
||||||
|
PRUint32 crc = crc32(0L, (const unsigned char*)itemData, item->size);
|
||||||
//-- verify crc32
|
//-- verify crc32
|
||||||
if (crc != itemCrc)
|
if (crc != item->crc32)
|
||||||
return ZIP_ERR_CORRUPT;
|
return ZIP_ERR_CORRUPT;
|
||||||
|
|
||||||
return ZIP_OK;
|
return ZIP_OK;
|
||||||
@ -831,17 +791,15 @@ nsZipArchive::CopyItemToDisk(PRUint32 itemSize, PRUint32 itemCrc,
|
|||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// nsZipArchive::InflateItem
|
// nsZipArchive::InflateItem
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
nsresult nsZipArchive::InflateItem(const nsZipItem* aItem, nsSeekableZipHandle &fd, PRFileDesc* outFD)
|
nsresult nsZipArchive::InflateItem(nsZipItem * item, PRFileDesc* outFD)
|
||||||
/*
|
/*
|
||||||
* This function inflates an archive item to disk, to the
|
* This function inflates an archive item to disk, to the
|
||||||
* file specified by outFD. If outFD is zero, the extracted data is
|
* file specified by outFD. If outFD is zero, the extracted data is
|
||||||
* not written, only checked for CRC, so this is in effect same as 'Test'.
|
* not written, only checked for CRC, so this is in effect same as 'Test'.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PR_ASSERT(aItem);
|
PR_ASSERT(item);
|
||||||
|
|
||||||
//-- allocate deflation buffers
|
//-- allocate deflation buffers
|
||||||
Bytef inbuf[ZIP_BUFLEN];
|
|
||||||
Bytef outbuf[ZIP_BUFLEN];
|
Bytef outbuf[ZIP_BUFLEN];
|
||||||
|
|
||||||
//-- set up the inflate
|
//-- set up the inflate
|
||||||
@ -851,95 +809,44 @@ nsresult nsZipArchive::InflateItem(const nsZipItem* aItem, nsSeekableZipHandle &
|
|||||||
return ZIP_ERR_GENERAL;
|
return ZIP_ERR_GENERAL;
|
||||||
|
|
||||||
//-- inflate loop
|
//-- inflate loop
|
||||||
zs.next_out = outbuf;
|
zs.avail_in = item->size;
|
||||||
zs.avail_out = ZIP_BUFLEN;
|
zs.next_in = (Bytef*)GetData(item);
|
||||||
|
if (!zs.next_in)
|
||||||
|
return ZIP_ERR_CORRUPT;
|
||||||
|
|
||||||
PRUint32 size = aItem->size;
|
|
||||||
PRUint32 outpos = 0;
|
|
||||||
PRUint32 crc = crc32(0L, Z_NULL, 0);
|
PRUint32 crc = crc32(0L, Z_NULL, 0);
|
||||||
int zerr = Z_OK;
|
int zerr = Z_OK;
|
||||||
while (zerr == Z_OK)
|
while (zerr == Z_OK)
|
||||||
{
|
{
|
||||||
PRBool bRead = PR_FALSE;
|
zs.next_out = outbuf;
|
||||||
PRBool bWrote= PR_FALSE;
|
zs.avail_out = ZIP_BUFLEN;
|
||||||
|
|
||||||
if (zs.avail_in == 0 && zs.total_in < size)
|
zerr = inflate(&zs, Z_PARTIAL_FLUSH);
|
||||||
|
if (zerr != Z_OK && zerr != Z_STREAM_END)
|
||||||
{
|
{
|
||||||
//-- no data to inflate yet still more in file:
|
status = (zerr == Z_MEM_ERROR) ? ZIP_ERR_MEMORY : ZIP_ERR_CORRUPT;
|
||||||
//-- read another chunk of compressed data
|
break;
|
||||||
PRUint32 chunk = (size-zs.total_in < ZIP_BUFLEN) ? size-zs.total_in : ZIP_BUFLEN;
|
|
||||||
|
|
||||||
if (fd.Read(inbuf, chunk) != (READTYPE)chunk)
|
|
||||||
{
|
|
||||||
//-- unexpected end of data
|
|
||||||
status = ZIP_ERR_CORRUPT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
zs.next_in = inbuf;
|
|
||||||
zs.avail_in = chunk;
|
|
||||||
bRead = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
|
PRUint32 count = zs.next_out - outbuf;
|
||||||
|
|
||||||
if (zs.avail_out == 0)
|
//-- incrementally update crc32
|
||||||
|
crc = crc32(crc, (const unsigned char*)outbuf, count);
|
||||||
|
|
||||||
|
if (outFD && PR_Write(outFD, outbuf, count) < (READTYPE)count)
|
||||||
{
|
{
|
||||||
//-- write inflated buffer to disk and make space
|
status = ZIP_ERR_DISK;
|
||||||
if (outFD && PR_Write(outFD, outbuf, ZIP_BUFLEN) < ZIP_BUFLEN)
|
break;
|
||||||
{
|
|
||||||
//-- Couldn't write all the data (disk full?)
|
|
||||||
status = ZIP_ERR_DISK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
outpos = zs.total_out;
|
|
||||||
zs.next_out = outbuf;
|
|
||||||
zs.avail_out = ZIP_BUFLEN;
|
|
||||||
bWrote = PR_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bRead || bWrote)
|
|
||||||
{
|
|
||||||
Bytef* old_next_out = zs.next_out;
|
|
||||||
|
|
||||||
zerr = inflate(&zs, Z_PARTIAL_FLUSH);
|
|
||||||
|
|
||||||
//-- incrementally update crc32
|
|
||||||
crc = crc32(crc, (const unsigned char*)old_next_out, zs.next_out - old_next_out);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
zerr = Z_STREAM_END;
|
|
||||||
|
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
//-- verify crc32
|
|
||||||
if ((status == ZIP_OK) && (crc != aItem->crc32))
|
|
||||||
{
|
|
||||||
status = ZIP_ERR_CORRUPT;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-- write last inflated bit to disk
|
|
||||||
if (zerr == Z_STREAM_END && outpos < zs.total_out)
|
|
||||||
{
|
|
||||||
PRUint32 chunk = zs.total_out - outpos;
|
|
||||||
if (outFD && PR_Write(outFD, outbuf, chunk) < (READTYPE)chunk)
|
|
||||||
status = ZIP_ERR_DISK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-- convert zlib error to return value
|
|
||||||
if (status == ZIP_OK && zerr != Z_OK && zerr != Z_STREAM_END)
|
|
||||||
{
|
|
||||||
status = (zerr == Z_MEM_ERROR) ? ZIP_ERR_MEMORY : ZIP_ERR_CORRUPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-- if found no errors make sure we've converted the whole thing
|
|
||||||
PR_ASSERT(status != ZIP_OK || zs.total_in == aItem->size);
|
|
||||||
PR_ASSERT(status != ZIP_OK || zs.total_out == aItem->realsize);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
//-- free zlib internal state
|
//-- free zlib internal state
|
||||||
inflateEnd(&zs);
|
inflateEnd(&zs);
|
||||||
|
|
||||||
|
//-- verify crc32
|
||||||
|
if ((status == ZIP_OK) && (crc != item->crc32))
|
||||||
|
{
|
||||||
|
status = ZIP_ERR_CORRUPT;
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,12 +855,12 @@ cleanup:
|
|||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
|
|
||||||
nsZipArchive::nsZipArchive() :
|
nsZipArchive::nsZipArchive() :
|
||||||
mBuiltSynthetics(PR_FALSE)
|
mBuiltSynthetics(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsZipArchive);
|
MOZ_COUNT_CTOR(nsZipArchive);
|
||||||
|
|
||||||
// initialize the table to NULL
|
// initialize the table to NULL
|
||||||
memset(mFiles, 0, sizeof mFiles);
|
memset(mFiles, 0, sizeof(mFiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
nsZipArchive::~nsZipArchive()
|
nsZipArchive::~nsZipArchive()
|
||||||
|
@ -46,19 +46,16 @@
|
|||||||
#define ZIP_MAGIC 0x5A49505FL /* "ZIP_" */
|
#define ZIP_MAGIC 0x5A49505FL /* "ZIP_" */
|
||||||
#define ZIPFIND_MAGIC 0x5A495046L /* "ZIPF" */
|
#define ZIPFIND_MAGIC 0x5A495046L /* "ZIPF" */
|
||||||
#define ZIP_TABSIZE 256
|
#define ZIP_TABSIZE 256
|
||||||
// Keep this odd. The -1 is significant.
|
/* We really want to be a (multiple of) 4K for optimal file IO */
|
||||||
#define ZIP_BUFLEN (4 * 1024 - 1)
|
#define ZIP_BUFLEN (4*1024) /* Used as output buffer when deflating items to a file */
|
||||||
|
|
||||||
#define PL_ARENA_CONST_ALIGN_MASK 7
|
#define PL_ARENA_CONST_ALIGN_MASK 7
|
||||||
#include "plarena.h"
|
#include "plarena.h"
|
||||||
#define ZIP_Seek(fd,p,m) (PR_Seek((fd),((PROffset32)p),(m))==((PROffset32)p))
|
|
||||||
|
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
|
|
||||||
class nsZipFind;
|
class nsZipFind;
|
||||||
class nsZipReadState;
|
|
||||||
class nsZipItemMetadata;
|
|
||||||
|
|
||||||
struct PRFileDesc;
|
struct PRFileDesc;
|
||||||
|
|
||||||
@ -88,7 +85,6 @@ struct nsZipItem
|
|||||||
nsZipItem* next;
|
nsZipItem* next;
|
||||||
|
|
||||||
PRUint32 headerOffset;
|
PRUint32 headerOffset;
|
||||||
PRUint32 dataOffset;
|
|
||||||
PRUint32 size; /* size in original file */
|
PRUint32 size; /* size in original file */
|
||||||
PRUint32 realsize; /* inflated size */
|
PRUint32 realsize; /* inflated size */
|
||||||
PRUint32 crc32;
|
PRUint32 crc32;
|
||||||
@ -100,21 +96,18 @@ struct nsZipItem
|
|||||||
PRUint16 date;
|
PRUint16 date;
|
||||||
PRUint16 mode;
|
PRUint16 mode;
|
||||||
PRUint8 compression;
|
PRUint8 compression;
|
||||||
PRPackedBool hasDataOffset : 1;
|
bool isDirectory;
|
||||||
PRPackedBool isDirectory : 1;
|
bool isSynthetic; /* whether item is an actual zip entry or was
|
||||||
PRPackedBool isSynthetic : 1; /* whether item is an actual zip entry or was
|
generated as part of a real entry's path */
|
||||||
generated as part of a real entry's path,
|
|
||||||
e.g. foo/ in a zip containing only foo/a.txt
|
|
||||||
and no foo/ entry is synthetic */
|
|
||||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||||
PRPackedBool isSymlink : 1;
|
bool isSymlink;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char name[1]; // actually, bigger than 1
|
char name[1]; /* actually, bigger than 1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsZipHandle;
|
class nsZipHandle;
|
||||||
class nsSeekableZipHandle;
|
|
||||||
/**
|
/**
|
||||||
* nsZipArchive -- a class for reading the PKZIP file format.
|
* nsZipArchive -- a class for reading the PKZIP file format.
|
||||||
*
|
*
|
||||||
@ -190,10 +183,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
PRInt32 FindInit(const char * aPattern, nsZipFind** aFind);
|
PRInt32 FindInit(const char * aPattern, nsZipFind** aFind);
|
||||||
|
|
||||||
/* Gets an undependent handle to the jar
|
/*
|
||||||
* Also ensures that aItem is fully filled
|
* Gets an undependent handle to the mapped file.
|
||||||
*/
|
*/
|
||||||
nsZipHandle* GetFD(nsZipItem* aItem);
|
nsZipHandle* GetFD();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pointer to the data of the item.
|
||||||
|
* @param aItem Pointer to nsZipItem
|
||||||
|
* reutrns null when zip file is corrupt.
|
||||||
|
*/
|
||||||
|
PRUint8* GetData(nsZipItem* aItem);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//--- private members ---
|
//--- private members ---
|
||||||
@ -201,15 +201,8 @@ private:
|
|||||||
nsZipItem* mFiles[ZIP_TABSIZE];
|
nsZipItem* mFiles[ZIP_TABSIZE];
|
||||||
PLArenaPool mArena;
|
PLArenaPool mArena;
|
||||||
|
|
||||||
/**
|
|
||||||
* Fills in nsZipItem fields that were not filled in by BuildFileList
|
|
||||||
* @param aItem Pointer to nsZipItem
|
|
||||||
* returns true if the item was filled in successfully
|
|
||||||
*/
|
|
||||||
bool MaybeReadItem(nsZipItem* aItem);
|
|
||||||
|
|
||||||
// Whether we synthesized the directory entries
|
// Whether we synthesized the directory entries
|
||||||
PRPackedBool mBuiltSynthetics;
|
bool mBuiltSynthetics;
|
||||||
|
|
||||||
// file handle
|
// file handle
|
||||||
nsRefPtr<nsZipHandle> mFd;
|
nsRefPtr<nsZipHandle> mFd;
|
||||||
@ -222,92 +215,29 @@ private:
|
|||||||
nsresult BuildFileList();
|
nsresult BuildFileList();
|
||||||
nsresult BuildSynthetics();
|
nsresult BuildSynthetics();
|
||||||
|
|
||||||
nsresult CopyItemToDisk(PRUint32 size, PRUint32 crc, nsSeekableZipHandle &fd, PRFileDesc* outFD);
|
nsresult CopyItemToDisk(nsZipItem* item, PRFileDesc* outFD);
|
||||||
nsresult InflateItem(const nsZipItem* aItem, nsSeekableZipHandle &fd, PRFileDesc* outFD);
|
nsresult InflateItem(nsZipItem* item, PRFileDesc* outFD);
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsZipHandle {
|
class nsZipHandle {
|
||||||
friend class nsZipArchive;
|
friend class nsZipArchive;
|
||||||
friend class nsSeekableZipHandle;
|
|
||||||
public:
|
public:
|
||||||
static nsresult Init(PRFileDesc *fd, nsZipHandle **ret NS_OUTPARAM);
|
static nsresult Init(PRFileDesc *fd, nsZipHandle **ret NS_OUTPARAM);
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads data at a certain point
|
|
||||||
* @param aPosition seek ofset
|
|
||||||
* @param aBuffer buffer
|
|
||||||
* @param aCount number of bytes to read */
|
|
||||||
PRInt32 Read(PRUint32 aPosition, void *aBuffer, PRUint32 aCount);
|
|
||||||
|
|
||||||
NS_METHOD_(nsrefcnt) AddRef(void);
|
NS_METHOD_(nsrefcnt) AddRef(void);
|
||||||
NS_METHOD_(nsrefcnt) Release(void);
|
NS_METHOD_(nsrefcnt) Release(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PRFileDesc *mFd; // OS file-descriptor
|
PRFileDesc * mFd; /* OS file-descriptor */
|
||||||
PRUint8 *mFileData; // pointer to mmaped file
|
PRUint8 * mFileData; /* pointer to mmaped file */
|
||||||
PRUint32 mLen; // length of file and memory mapped area
|
PRUint32 mLen; /* length of file and memory mapped area */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsZipHandle();
|
nsZipHandle();
|
||||||
~nsZipHandle();
|
~nsZipHandle();
|
||||||
|
|
||||||
PRFileMap *mMap; // nspr datastructure for mmap
|
PRFileMap * mMap; /* nspr datastructure for mmap */
|
||||||
nsrefcnt mRefCnt; // ref count
|
nsrefcnt mRefCnt; /* ref count */
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** nsSeekableZipHandle acts as a container for nsZipHandle,
|
|
||||||
emulates sequential file io */
|
|
||||||
class nsSeekableZipHandle {
|
|
||||||
// stick nsZipItem in here
|
|
||||||
public:
|
|
||||||
nsSeekableZipHandle()
|
|
||||||
: mOffset(0)
|
|
||||||
, mRemaining(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Initializes nsSeekableZipHandle with
|
|
||||||
* @param aOffset byte offset of the file to start reading at
|
|
||||||
* @param length of this descriptor
|
|
||||||
*/
|
|
||||||
bool Open(nsZipHandle *aHandle, PRUint32 aOffset, PRUint32 aLength) {
|
|
||||||
NS_ABORT_IF_FALSE (aHandle, "Argument must not be NULL");
|
|
||||||
if (aOffset > aHandle->mLen)
|
|
||||||
return false;
|
|
||||||
mFd = aHandle;
|
|
||||||
mOffset = aOffset;
|
|
||||||
mRemaining = aLength;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Releases the file handle. It is safe to call multiple times. */
|
|
||||||
void Close()
|
|
||||||
{
|
|
||||||
mFd = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads data at a certain point
|
|
||||||
* @param aBuffer input buffer
|
|
||||||
* @param aCount number of bytes to read */
|
|
||||||
PRInt32 Read(void *aBuffer, PRUint32 aCount)
|
|
||||||
{
|
|
||||||
if (!mFd.get())
|
|
||||||
return -1;
|
|
||||||
aCount = PR_MIN(mRemaining, aCount);
|
|
||||||
PRInt32 ret = mFd->Read(mOffset, aBuffer, aCount);
|
|
||||||
if (ret > 0) {
|
|
||||||
mOffset += ret;
|
|
||||||
mRemaining -= ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsRefPtr<nsZipHandle> mFd; // file handle
|
|
||||||
PRUint32 mOffset; // current reading offset
|
|
||||||
PRUint32 mRemaining; // bytes remaining
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -319,7 +249,6 @@ private:
|
|||||||
class nsZipFind
|
class nsZipFind
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
nsZipFind(nsZipArchive* aZip, char* aPattern, PRBool regExp);
|
nsZipFind(nsZipArchive* aZip, char* aPattern, PRBool regExp);
|
||||||
~nsZipFind();
|
~nsZipFind();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user