Bug 533038 - 2. Generalize nsZipArchive and nsZipHandle to read from different sources, r=taras a=blocking-beta6

This commit is contained in:
Michael Wu 2010-09-08 20:37:34 -07:00
Родитель ef808d0528
Коммит 530165f48e
4 изменённых файлов: 99 добавлений и 58 удалений

Просмотреть файл

@ -88,7 +88,7 @@ nsJARInputStream::InitFile(nsJAR *aJar, nsZipItem *item)
// Must keep handle to filepointer and mmap structure as long as we need access to the mmapped data
mFd = aJar->mZip.GetFD();
mZs.next_in = aJar->mZip.GetData(item);
mZs.next_in = (Bytef *)aJar->mZip.GetData(item);
if (!mZs.next_in)
return NS_ERROR_FILE_CORRUPTED;
mZs.avail_in = item->Size();

Просмотреть файл

@ -175,8 +175,13 @@ nsZipHandle::nsZipHandle()
NS_IMPL_THREADSAFE_ADDREF(nsZipHandle)
NS_IMPL_THREADSAFE_RELEASE(nsZipHandle)
nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
nsresult nsZipHandle::Init(nsILocalFile *file, nsZipHandle **ret)
{
mozilla::AutoFDClose fd;
nsresult rv = file->OpenNSPRFileDesc(PR_RDONLY, 0000, &fd);
if (NS_FAILED(rv))
return rv;
PRInt64 size = PR_Available64(fd);
if (size >= PR_INT32_MAX)
return NS_ERROR_FILE_TOO_BIG;
@ -192,7 +197,7 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
return NS_ERROR_FAILURE;
}
nsZipHandle *handle = new nsZipHandle();
nsRefPtr<nsZipHandle> handle = new nsZipHandle();
if (!handle) {
PR_MemUnmap(buf, size);
PR_CloseFileMap(map);
@ -200,21 +205,40 @@ nsresult nsZipHandle::Init(PRFileDesc *fd, nsZipHandle **ret)
}
handle->mMap = map;
handle->mFile = file;
handle->mLen = (PRUint32) size;
handle->mFileData = buf;
handle->AddRef();
*ret = handle;
*ret = handle.forget().get();
return NS_OK;
}
nsresult nsZipHandle::Init(nsZipArchive *zip, const char *entry,
nsZipHandle **ret)
{
nsRefPtr<nsZipHandle> handle = new nsZipHandle();
if (!handle)
return NS_ERROR_OUT_OF_MEMORY;
handle->mBuf = new nsZipItemPtr<PRUint8>(zip, entry);
if (!handle->mBuf)
return NS_ERROR_OUT_OF_MEMORY;
handle->mMap = nsnull;
handle->mLen = handle->mBuf->Length();
handle->mFileData = handle->mBuf->Buffer();
*ret = handle.forget().get();
return NS_OK;
}
nsZipHandle::~nsZipHandle()
{
if (mFileData) {
PR_MemUnmap(mFileData, mLen);
if (mMap) {
PR_MemUnmap((void *)mFileData, mLen);
PR_CloseFileMap(mMap);
mFileData = nsnull;
mMap = nsnull;
}
mFileData = nsnull;
mMap = nsnull;
mBuf = nsnull;
MOZ_COUNT_DTOR(nsZipHandle);
}
@ -225,28 +249,17 @@ nsZipHandle::~nsZipHandle()
//---------------------------------------------
// nsZipArchive::OpenArchive
//---------------------------------------------
nsresult nsZipArchive::OpenArchive(nsIFile *aZipFile)
nsresult nsZipArchive::OpenArchive(nsZipHandle *aZipHandle)
{
nsresult rv;
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aZipFile, &rv);
if (NS_FAILED(rv)) return rv;
PRFileDesc* fd;
rv = localFile->OpenNSPRFileDesc(PR_RDONLY, 0000, &fd);
if (NS_FAILED(rv)) return rv;
rv = nsZipHandle::Init(fd, getter_AddRefs(mFd));
PR_Close(fd);
if (NS_FAILED(rv))
return rv;
mFd = aZipHandle;
// Initialize our arena
PL_INIT_ARENA_POOL(&mArena, "ZipArena", ZIP_ARENABLOCKSIZE);
//-- get table of contents for archive
rv = BuildFileList();
nsresult rv = BuildFileList();
char *env = PR_GetEnv("MOZ_JAR_LOG_DIR");
if (env && NS_SUCCEEDED(rv)) {
if (env && NS_SUCCEEDED(rv) && aZipHandle->mFile) {
nsCOMPtr<nsILocalFile> logFile;
nsresult rv2 = NS_NewLocalFile(NS_ConvertUTF8toUTF16(env), PR_FALSE, getter_AddRefs(logFile));
@ -257,10 +270,11 @@ nsresult nsZipArchive::OpenArchive(nsIFile *aZipFile)
logFile->Create(nsIFile::DIRECTORY_TYPE, 0700);
nsAutoString name;
localFile->GetLeafName(name);
aZipHandle->mFile->GetLeafName(name);
name.Append(NS_LITERAL_STRING(".log"));
logFile->Append(name);
PRFileDesc* fd;
rv2 = logFile->OpenNSPRFileDesc(PR_WRONLY|PR_CREATE_FILE|PR_APPEND, 0644, &fd);
if (NS_SUCCEEDED(rv2))
mLog = fd;
@ -268,6 +282,20 @@ nsresult nsZipArchive::OpenArchive(nsIFile *aZipFile)
return rv;
}
nsresult nsZipArchive::OpenArchive(nsIFile *aFile)
{
nsresult rv;
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsZipHandle> handle;
rv = nsZipHandle::Init(localFile, getter_AddRefs(handle));
if (NS_FAILED(rv))
return rv;
return OpenArchive(handle);
}
//---------------------------------------------
// nsZipArchive::Test
//---------------------------------------------
@ -562,9 +590,9 @@ nsresult nsZipArchive::BuildFileList()
NS_TIME_FUNCTION;
// Get archive size using end pos
PRUint8* buf;
PRUint8* startp = mFd->mFileData;
PRUint8* endp = startp + mFd->mLen;
const PRUint8* buf;
const PRUint8* startp = mFd->mFileData;
const PRUint8* endp = startp + mFd->mLen;
PRUint32 centralOffset = 1;
if (mFd->mLen > ZIPCENTRAL_SIZE && *(PRUint32*)(startp + centralOffset) == CENTRALSIG) {
@ -706,13 +734,13 @@ nsZipHandle* nsZipArchive::GetFD()
//---------------------------------------------
// nsZipArchive::GetData
//---------------------------------------------
PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
const PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
{
PR_ASSERT (aItem);
//-- read local header to get variable length values and calculate
//-- the real data offset
PRUint32 len = mFd->mLen;
PRUint8* data = mFd->mFileData;
const PRUint8* data = mFd->mFileData;
PRUint32 offset = aItem->LocalOffset();
if (offset + ZIPLOCAL_SIZE > len)
return nsnull;
@ -737,7 +765,7 @@ PRUint8* nsZipArchive::GetData(nsZipItem* aItem)
}
PRBool
nsZipArchive::CheckCRC(nsZipItem* aItem, PRUint8* aItemData) {
nsZipArchive::CheckCRC(nsZipItem* aItem, const PRUint8* aItemData) {
PRUint32 crc = crc32(0, (const unsigned char*)aItemData, aItem->Size());
return crc == aItem->CRC32();
}

Просмотреть файл

@ -133,10 +133,20 @@ public:
* object. If we were allowed to use exceptions this would have been
* part of the constructor
*
* @param fd File descriptor of file to open
* @param aZipHandle The nsZipHandle used to access the zip
* @return status code
*/
nsresult OpenArchive(nsIFile *aZipFile);
nsresult OpenArchive(nsZipHandle *aZipHandle);
/**
* OpenArchive
*
* Convenience function that generates nsZipHandle
*
* @param aFile The file used to access the zip
* @return status code
*/
nsresult OpenArchive(nsIFile *aFile);
/**
* Test the integrity of items in this archive by running
@ -196,9 +206,9 @@ public:
* @param aItem Pointer to nsZipItem
* reutrns null when zip file is corrupt.
*/
PRUint8* GetData(nsZipItem* aItem);
const PRUint8* GetData(nsZipItem* aItem);
PRBool CheckCRC(nsZipItem* aItem, PRUint8* aData);
PRBool CheckCRC(nsZipItem* aItem, const PRUint8* aData);
private:
//--- private members ---
@ -225,27 +235,6 @@ private:
nsresult BuildSynthetics();
};
class nsZipHandle {
friend class nsZipArchive;
public:
static nsresult Init(PRFileDesc *fd, nsZipHandle **ret NS_OUTPARAM);
NS_METHOD_(nsrefcnt) AddRef(void);
NS_METHOD_(nsrefcnt) Release(void);
protected:
PRUint8 * mFileData; /* pointer to mmaped file */
PRUint32 mLen; /* length of file and memory mapped area */
private:
nsZipHandle();
~nsZipHandle();
PRFileMap * mMap; /* nspr datastructure for mmap */
nsrefcnt mRefCnt; /* ref count */
};
/**
* nsZipFind
*
@ -308,7 +297,7 @@ private:
bool mDoCRC;
};
/**
/**
* nsZipItemPtr - a RAII convenience class for reading the individual items in a zip.
* It reads whole files and does zero-copy IO for stored files. A buffer is allocated
* for decompression.
@ -353,6 +342,30 @@ public:
}
};
class nsZipHandle {
friend class nsZipArchive;
public:
static nsresult Init(nsILocalFile *file, nsZipHandle **ret NS_OUTPARAM);
static nsresult Init(nsZipArchive *zip, const char *entry,
nsZipHandle **ret NS_OUTPARAM);
NS_METHOD_(nsrefcnt) AddRef(void);
NS_METHOD_(nsrefcnt) Release(void);
protected:
const PRUint8 * mFileData; /* pointer to mmaped file */
PRUint32 mLen; /* length of file and memory mapped area */
nsCOMPtr<nsILocalFile> mFile; /* source file if any, for logging */
private:
nsZipHandle();
~nsZipHandle();
PRFileMap * mMap; /* nspr datastructure for mmap */
nsAutoPtr<nsZipItemPtr<PRUint8> > mBuf;
nsrefcnt mRefCnt; /* ref count */
};
nsresult gZlibInit(z_stream *zs);
#endif /* nsZipArchive_h_ */

Просмотреть файл

@ -224,7 +224,7 @@ StartupCache::GetBuffer(const char* id, char** outbuf, PRUint32* length)
if (!data && mArchive) {
nsZipItem* zipItem = mArchive->GetItem(id);
if (zipItem) {
PRUint8* itemData = mArchive->GetData(zipItem);
const PRUint8* itemData = mArchive->GetData(zipItem);
if (!itemData || !mArchive->CheckCRC(zipItem, itemData)) {
NS_WARNING("StartupCache file corrupted!");
InvalidateCache();