libziparchive: ensure ReadAtOffset is atomic
am: b1911401e0
* commit 'b1911401e0008c2b12a3fe6c9dc34528bf7710a5':
libziparchive: ensure ReadAtOffset is atomic
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index 3591a6b..7dc60ae 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -152,6 +152,9 @@
* if this file entry contains a data descriptor footer. To verify crc32s
* and length, a call to VerifyCrcAndLengths must be made after entry data
* has been processed.
+ *
+ * On non-Windows platforms this method does not modify internal state and
+ * can be called concurrently.
*/
int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName,
ZipEntry* data);
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a2d6fcc..1f27500 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -495,14 +495,20 @@
}
// Attempts to read |len| bytes into |buf| at offset |off|.
-// Callers should not rely on the |fd| offset being incremented
-// as a side effect of this call.
+// On non-Windows platforms, callers are guaranteed that the |fd|
+// offset is unchanged and there is no side effect to this call.
+//
+// On Windows platforms this is not thread-safe.
static inline bool ReadAtOffset(int fd, uint8_t* buf, size_t len, off64_t off) {
+#if !defined(_WIN32)
+ return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
+#else
if (lseek64(fd, off, SEEK_SET) != off) {
ALOGW("Zip: failed seek to offset %" PRId64, off);
return false;
}
return android::base::ReadFully(fd, buf, len);
+#endif
}
static int32_t FindEntry(const ZipArchive* archive, const int ent,