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,