зеркало из https://github.com/mozilla/gecko-dev.git
Bug 533038 - 2. Generalize nsZipArchive and nsZipHandle to read from different sources, r=taras a=blocking-beta6
This commit is contained in:
Родитель
ef808d0528
Коммит
530165f48e
|
@ -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();
|
||||
|
|
Загрузка…
Ссылка в новой задаче