diff options
author | Kenny Root <kroot@google.com> | 2010-10-04 14:20:14 -0700 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2010-10-04 15:17:19 -0700 |
commit | 61ef747e0e1b3980fbb10ce48de575caa69a6a74 (patch) | |
tree | f9e8441c3b0216ce0af144f3c9edbd0d7f43ca30 /libs | |
parent | 1da40fbd474e378235877738ee622bbf8093ce6c (diff) | |
download | frameworks_native-61ef747e0e1b3980fbb10ce48de575caa69a6a74.zip frameworks_native-61ef747e0e1b3980fbb10ce48de575caa69a6a74.tar.gz frameworks_native-61ef747e0e1b3980fbb10ce48de575caa69a6a74.tar.bz2 |
Use pread() in ZipFileRO for Linux
AssetManager instances are created by zygote and passed to all its
children so that they don't have to individually open
frameworks-res.apk. This creates a problem for determining the current
file offset when using lseek() on those files, because you can't
guarantee the cross-process locking of a mutex. Luckily, Linux
implements pread() to get around this suckiness.
The problem is that only Linux implements this, so we have to keep the
old locking for use on host builds with aapt and friends. aapt doesn't
have this same problem of sharing file descriptors across forked
processes, so we can keep the local AutoMutex to protect accesses of
those files.
Change-Id: Ibe9f11499a53fe345f50fbaea438815ec0fd363e
Diffstat (limited to 'libs')
-rw-r--r-- | libs/utils/ZipFileRO.cpp | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp index bee86b2..9b1f82f 100644 --- a/libs/utils/ZipFileRO.cpp +++ b/libs/utils/ZipFileRO.cpp @@ -508,6 +508,36 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, 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); @@ -517,7 +547,7 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, } ssize_t actual = - TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf))); + TEMP_FAILURE_RETRY(read(mFd, lfhBuf, sizeof(lfhBuf))); if (actual != sizeof(lfhBuf)) { LOGW("failed reading lfh from offset %ld\n", localHdrOffset); return false; @@ -531,6 +561,7 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, return false; } } +#endif /* HAVE_PREAD */ off_t dataOffset = localHdrOffset + kLFHLen + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); |