am f84a5918: Merge "Use pread() in ZipFileRO for Linux" into gingerbread
Merge commit 'f84a5918f5e0572c0280fa705970ef7459b45393' into gingerbread-plus-aosp * commit 'f84a5918f5e0572c0280fa705970ef7459b45393': Use pread() in ZipFileRO for Linux
This commit is contained in:
@@ -14,13 +14,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
/*
|
||||||
// Read-only access to Zip archives, with minimal heap allocation.
|
* Read-only access to Zip archives, with minimal heap allocation.
|
||||||
//
|
*
|
||||||
// This is similar to the more-complete ZipFile class, but no attempt
|
* This is similar to the more-complete ZipFile class, but no attempt
|
||||||
// has been made to make them interchangeable. This class operates under
|
* has been made to make them interchangeable. This class operates under
|
||||||
// a very different set of assumptions and constraints.
|
* a very different set of assumptions and constraints.
|
||||||
//
|
*
|
||||||
|
* One such assumption is that if you're getting file descriptors for
|
||||||
|
* use with this class as a child of a fork() operation, you must be on
|
||||||
|
* a pread() to guarantee correct operation. This is because pread() can
|
||||||
|
* atomically read at a file offset without worrying about a lock around an
|
||||||
|
* lseek() + read() pair.
|
||||||
|
*/
|
||||||
#ifndef __LIBS_ZIPFILERO_H
|
#ifndef __LIBS_ZIPFILERO_H
|
||||||
#define __LIBS_ZIPFILERO_H
|
#define __LIBS_ZIPFILERO_H
|
||||||
|
|
||||||
@@ -55,6 +61,10 @@ typedef void* ZipEntryRO;
|
|||||||
* the record structure. However, this requires a private mapping of
|
* the record structure. However, this requires a private mapping of
|
||||||
* every page that the Central Directory touches. Easier to tuck a copy
|
* every page that the Central Directory touches. Easier to tuck a copy
|
||||||
* of the string length into the hash table entry.
|
* of the string length into the hash table entry.
|
||||||
|
*
|
||||||
|
* NOTE: If this is used on file descriptors inherited from a fork() operation,
|
||||||
|
* you must be on a platform that implements pread() to guarantee correctness
|
||||||
|
* on the shared file descriptors.
|
||||||
*/
|
*/
|
||||||
class ZipFileRO {
|
class ZipFileRO {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -508,6 +508,36 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
|
|||||||
|
|
||||||
unsigned char lfhBuf[kLFHLen];
|
unsigned char lfhBuf[kLFHLen];
|
||||||
|
|
||||||
|
#ifdef HAVE_PREAD
|
||||||
|
/*
|
||||||
|
* This file descriptor might be from zygote's preloaded assets,
|
||||||
|
* so we need to do an pread() instead of a lseek() + read() to
|
||||||
|
* guarantee atomicity across the processes with the shared file
|
||||||
|
* descriptors.
|
||||||
|
*/
|
||||||
|
ssize_t actual =
|
||||||
|
TEMP_FAILURE_RETRY(pread(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
|
||||||
|
|
||||||
|
if (actual != sizeof(lfhBuf)) {
|
||||||
|
LOGW("failed reading lfh from offset %ld\n", localHdrOffset);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get4LE(lfhBuf) != kLFHSignature) {
|
||||||
|
LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
|
||||||
|
"got: data=0x%08lx\n",
|
||||||
|
localHdrOffset, kLFHSignature, get4LE(lfhBuf));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else /* HAVE_PREAD */
|
||||||
|
/*
|
||||||
|
* For hosts don't have pread() we cannot guarantee atomic reads from
|
||||||
|
* an offset in a file. Android should never run on those platforms.
|
||||||
|
* File descriptors inherited from a fork() share file offsets and
|
||||||
|
* there would be nothing to protect from two different processes
|
||||||
|
* calling lseek() concurrently.
|
||||||
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
AutoMutex _l(mFdLock);
|
AutoMutex _l(mFdLock);
|
||||||
|
|
||||||
@@ -531,6 +561,7 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* HAVE_PREAD */
|
||||||
|
|
||||||
off_t dataOffset = localHdrOffset + kLFHLen
|
off_t dataOffset = localHdrOffset + kLFHLen
|
||||||
+ get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
|
+ get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
|
||||||
|
|||||||
Reference in New Issue
Block a user