Change assets to use 64-bit API

The asset system and supporting libraries were using off_t instead of
off64_t to access files larger than 2GB (32-bit signed). This change
replaces all off_t with off64_t and lseek64.

There is a new utils/Compat.h added for Mac OS compatibility.

Also fixed some size-related compiler warnings.

Bug: 3205336
Change-Id: I9097b3cb7a602e811fe52f245939d8975da55e9e
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 8bd833b..e8d40ba 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -70,11 +70,6 @@
 endif
 endif
 
-ifeq ($(HOST_OS),darwin)
-# MacOS doesn't have lseek64. However, off_t is 64-bit anyway.
-LOCAL_CFLAGS += -DOFF_T_IS_64_BIT
-endif
-
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp
index cef7db4..a18294b 100644
--- a/libs/utils/Asset.cpp
+++ b/libs/utils/Asset.cpp
@@ -35,6 +35,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 using namespace android;
 
@@ -62,7 +65,7 @@
         if (cur->isAllocated()) {
             res.append("    ");
             res.append(cur->getAssetSource());
-            off_t size = (cur->getLength()+512)/1024;
+            off64_t size = (cur->getLength()+512)/1024;
             char buf[64];
             sprintf(buf, ": %dK\n", (int)size);
             res.append(buf);
@@ -119,7 +122,7 @@
 {
     _FileAsset* pAsset;
     status_t result;
-    off_t length;
+    off64_t length;
     int fd;
 
     fd = open(fileName, O_RDONLY | O_BINARY);
@@ -132,12 +135,26 @@
      * always open things read-only it doesn't really matter, so there's
      * no value in incurring the extra overhead of an fstat() call.
      */
-    length = lseek(fd, 0, SEEK_END);
+    // TODO(kroot): replace this with fstat despite the plea above.
+#if 1
+    length = lseek64(fd, 0, SEEK_END);
     if (length < 0) {
         ::close(fd);
         return NULL;
     }
-    (void) lseek(fd, 0, SEEK_SET);
+    (void) lseek64(fd, 0, SEEK_SET);
+#else
+    struct stat st;
+    if (fstat(fd, &st) < 0) {
+        ::close(fd);
+        return NULL;
+    }
+
+    if (!S_ISREG(st.st_mode)) {
+        ::close(fd);
+        return NULL;
+    }
+#endif
 
     pAsset = new _FileAsset;
     result = pAsset->openChunk(fileName, fd, 0, length);
@@ -162,7 +179,7 @@
 {
     _CompressedAsset* pAsset;
     status_t result;
-    off_t fileLen;
+    off64_t fileLen;
     bool scanResult;
     long offset;
     int method;
@@ -215,7 +232,7 @@
 /*
  * Create a new Asset from part of an open file.
  */
-/*static*/ Asset* Asset::createFromFileSegment(int fd, off_t offset,
+/*static*/ Asset* Asset::createFromFileSegment(int fd, off64_t offset,
     size_t length, AccessMode mode)
 {
     _FileAsset* pAsset;
@@ -233,7 +250,7 @@
 /*
  * Create a new Asset from compressed data in an open file.
  */
-/*static*/ Asset* Asset::createFromCompressedData(int fd, off_t offset,
+/*static*/ Asset* Asset::createFromCompressedData(int fd, off64_t offset,
     int compressionMethod, size_t uncompressedLen, size_t compressedLen,
     AccessMode mode)
 {
@@ -295,9 +312,9 @@
  *
  * Returns the new chunk offset, or -1 if the seek is illegal.
  */
-off_t Asset::handleSeek(off_t offset, int whence, off_t curPosn, off_t maxPosn)
+off64_t Asset::handleSeek(off64_t offset, int whence, off64_t curPosn, off64_t maxPosn)
 {
-    off_t newOffset;
+    off64_t newOffset;
 
     switch (whence) {
     case SEEK_SET:
@@ -311,15 +328,15 @@
         break;
     default:
         LOGW("unexpected whence %d\n", whence);
-        // this was happening due to an off_t size mismatch
+        // this was happening due to an off64_t size mismatch
         assert(false);
-        return (off_t) -1;
+        return (off64_t) -1;
     }
 
     if (newOffset < 0 || newOffset > maxPosn) {
         LOGW("seek out of range: want %ld, end=%ld\n",
             (long) newOffset, (long) maxPosn);
-        return (off_t) -1;
+        return (off64_t) -1;
     }
 
     return newOffset;
@@ -353,7 +370,7 @@
  *
  * Zero-length chunks are allowed.
  */
-status_t _FileAsset::openChunk(const char* fileName, int fd, off_t offset, size_t length)
+status_t _FileAsset::openChunk(const char* fileName, int fd, off64_t offset, size_t length)
 {
     assert(mFp == NULL);    // no reopen
     assert(mMap == NULL);
@@ -363,15 +380,15 @@
     /*
      * Seek to end to get file length.
      */
-    off_t fileLength;
-    fileLength = lseek(fd, 0, SEEK_END);
-    if (fileLength == (off_t) -1) {
+    off64_t fileLength;
+    fileLength = lseek64(fd, 0, SEEK_END);
+    if (fileLength == (off64_t) -1) {
         // probably a bad file descriptor
         LOGD("failed lseek (errno=%d)\n", errno);
         return UNKNOWN_ERROR;
     }
 
-    if ((off_t) (offset + length) > fileLength) {
+    if ((off64_t) (offset + length) > fileLength) {
         LOGD("start (%ld) + len (%ld) > end (%ld)\n",
             (long) offset, (long) length, (long) fileLength);
         return BAD_INDEX;
@@ -482,21 +499,21 @@
 /*
  * Seek to a new position.
  */
-off_t _FileAsset::seek(off_t offset, int whence)
+off64_t _FileAsset::seek(off64_t offset, int whence)
 {
-    off_t newPosn;
-    long actualOffset;
+    off64_t newPosn;
+    off64_t actualOffset;
 
     // compute new position within chunk
     newPosn = handleSeek(offset, whence, mOffset, mLength);
-    if (newPosn == (off_t) -1)
+    if (newPosn == (off64_t) -1)
         return newPosn;
 
-    actualOffset = (long) (mStart + newPosn);
+    actualOffset = mStart + newPosn;
 
     if (mFp != NULL) {
         if (fseek(mFp, (long) actualOffset, SEEK_SET) != 0)
-            return (off_t) -1;
+            return (off64_t) -1;
     }
 
     mOffset = actualOffset - mStart;
@@ -603,7 +620,7 @@
     }
 }
 
-int _FileAsset::openFileDescriptor(off_t* outStart, off_t* outLength) const
+int _FileAsset::openFileDescriptor(off64_t* outStart, off64_t* outLength) const
 {
     if (mMap != NULL) {
         const char* fname = mMap->getFileName();
@@ -678,7 +695,7 @@
  * This currently just sets up some values and returns.  On the first
  * read, we expand the entire file into a buffer and return data from it.
  */
-status_t _CompressedAsset::openChunk(int fd, off_t offset,
+status_t _CompressedAsset::openChunk(int fd, off64_t offset,
     int compressionMethod, size_t uncompressedLen, size_t compressedLen)
 {
     assert(mFd < 0);        // no re-open
@@ -782,13 +799,13 @@
  * expensive, because it requires plowing through a bunch of compressed
  * data.
  */
-off_t _CompressedAsset::seek(off_t offset, int whence)
+off64_t _CompressedAsset::seek(off64_t offset, int whence)
 {
-    off_t newPosn;
+    off64_t newPosn;
 
     // compute new position within chunk
     newPosn = handleSeek(offset, whence, mOffset, mUncompressedLen);
-    if (newPosn == (off_t) -1)
+    if (newPosn == (off64_t) -1)
         return newPosn;
 
     if (mZipInflater) {
diff --git a/libs/utils/FileMap.cpp b/libs/utils/FileMap.cpp
index f1f8bda..c220a90 100644
--- a/libs/utils/FileMap.cpp
+++ b/libs/utils/FileMap.cpp
@@ -88,11 +88,12 @@
  *
  * Returns "false" on failure.
  */
-bool FileMap::create(const char* origFileName, int fd, off_t offset, size_t length, bool readOnly)
+bool FileMap::create(const char* origFileName, int fd, off64_t offset, size_t length,
+        bool readOnly)
 {
 #ifdef HAVE_WIN32_FILEMAP
     int     adjust;
-    off_t   adjOffset;
+    off64_t adjOffset;
     size_t  adjLength;
 
     if (mPageSize == -1) {
@@ -131,7 +132,7 @@
 #endif
 #ifdef HAVE_POSIX_FILEMAP
     int     prot, flags, adjust;
-    off_t   adjOffset;
+    off64_t adjOffset;
     size_t  adjLength;
 
     void* ptr;
diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp
index 2c3724c..2907b56 100644
--- a/libs/utils/ObbFile.cpp
+++ b/libs/utils/ObbFile.cpp
@@ -22,6 +22,8 @@
 #include <unistd.h>
 
 #define LOG_TAG "ObbFile"
+
+#include <utils/Compat.h>
 #include <utils/Log.h>
 #include <utils/ObbFile.h>
 
@@ -67,17 +69,6 @@
     _rc; })
 #endif
 
-/*
- * Work around situations where off_t is 64-bit and use off64_t in
- * situations where it's 32-bit.
- */
-#ifdef OFF_T_IS_64_BIT
-#define my_lseek64 lseek
-typedef off_t my_off64_t;
-#else
-#define my_lseek64 lseek64
-typedef off64_t my_off64_t;
-#endif
 
 namespace android {
 
@@ -125,7 +116,7 @@
 
 bool ObbFile::parseObbFile(int fd)
 {
-    my_off64_t fileLength = my_lseek64(fd, 0, SEEK_END);
+    off64_t fileLength = lseek64(fd, 0, SEEK_END);
 
     if (fileLength < kFooterMinSize) {
         if (fileLength < 0) {
@@ -140,7 +131,7 @@
     size_t footerSize;
 
     {
-        my_lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);
+        lseek64(fd, fileLength - kFooterTagSize, SEEK_SET);
 
         char *footer = new char[kFooterTagSize];
         actual = TEMP_FAILURE_RETRY(read(fd, footer, kFooterTagSize));
@@ -171,8 +162,8 @@
         }
     }
 
-    my_off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
-    if (my_lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
+    off64_t fileOffset = fileLength - footerSize - kFooterTagSize;
+    if (lseek64(fd, fileOffset, SEEK_SET) != fileOffset) {
         LOGW("seek %lld failed: %s\n", fileOffset, strerror(errno));
         return false;
     }
@@ -211,10 +202,10 @@
 
     memcpy(&mSalt, (unsigned char*)scanBuf + kSaltOffset, sizeof(mSalt));
 
-    uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
-    if (packageNameLen <= 0
+    size_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
+    if (packageNameLen == 0
             || packageNameLen > (footerSize - kPackageNameOffset)) {
-        LOGW("bad ObbFile package name length (0x%04x; 0x%04x possible)\n",
+        LOGW("bad ObbFile package name length (0x%04zx; 0x%04zx possible)\n",
                 packageNameLen, footerSize - kPackageNameOffset);
         free(scanBuf);
         return false;
@@ -257,7 +248,7 @@
         return false;
     }
 
-    my_lseek64(fd, 0, SEEK_END);
+    lseek64(fd, 0, SEEK_END);
 
     if (mPackageName.size() == 0 || mVersion == -1) {
         LOGW("tried to write uninitialized ObbFile data\n");
diff --git a/libs/utils/StreamingZipInflater.cpp b/libs/utils/StreamingZipInflater.cpp
index 1f62ac5..5a162cc 100644
--- a/libs/utils/StreamingZipInflater.cpp
+++ b/libs/utils/StreamingZipInflater.cpp
@@ -31,7 +31,7 @@
 /*
  * Streaming access to compressed asset data in an open fd
  */
-StreamingZipInflater::StreamingZipInflater(int fd, off_t compDataStart,
+StreamingZipInflater::StreamingZipInflater(int fd, off64_t compDataStart,
         size_t uncompSize, size_t compSize) {
     mFd = fd;
     mDataMap = NULL;
@@ -210,7 +210,7 @@
 // seeking backwards requires uncompressing fom the beginning, so is very
 // expensive.  seeking forwards only requires uncompressing from the current
 // position to the destination.
-off_t StreamingZipInflater::seekAbsolute(off_t absoluteInputPosition) {
+off64_t StreamingZipInflater::seekAbsolute(off64_t absoluteInputPosition) {
     if (absoluteInputPosition < mOutCurPosition) {
         // rewind and reprocess the data from the beginning
         if (!mStreamNeedsInit) {
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
index 16b219c..55dfd9f 100644
--- a/libs/utils/ZipFileCRO.cpp
+++ b/libs/utils/ZipFileCRO.cpp
@@ -40,7 +40,7 @@
 
 bool ZipFileCRO_getEntryInfo(ZipFileCRO zipToken, ZipEntryRO entryToken,
         int* pMethod, size_t* pUncompLen,
-        size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) {
+        size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) {
     ZipFileRO* zip = (ZipFileRO*)zipToken;
     ZipEntryRO entry = (ZipEntryRO)entryToken;
     return zip->getEntryInfo(entry, pMethod, pUncompLen, pCompLen, pOffset,
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index 4261196..b18c383 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -146,7 +146,7 @@
         return NAME_NOT_FOUND;
     }
 
-    mFileLength = lseek(fd, 0, SEEK_END);
+    mFileLength = lseek64(fd, 0, SEEK_END);
     if (mFileLength < kEOCDLen) {
         TEMP_FAILURE_RETRY(close(fd));
         return UNKNOWN_ERROR;
@@ -202,7 +202,7 @@
     /*
      * Make sure this is a Zip archive.
      */
-    if (lseek(mFd, 0, SEEK_SET) != 0) {
+    if (lseek64(mFd, 0, SEEK_SET) != 0) {
         LOGW("seek to start failed: %s", strerror(errno));
         free(scanBuf);
         return false;
@@ -240,9 +240,9 @@
      *
      * We start by pulling in the last part of the file.
      */
-    off_t searchStart = mFileLength - readAmount;
+    off64_t searchStart = mFileLength - readAmount;
 
-    if (lseek(mFd, searchStart, SEEK_SET) != searchStart) {
+    if (lseek64(mFd, searchStart, SEEK_SET) != searchStart) {
         LOGW("seek %ld failed: %s\n",  (long) searchStart, strerror(errno));
         free(scanBuf);
         return false;
@@ -274,7 +274,7 @@
         return false;
     }
 
-    off_t eocdOffset = searchStart + i;
+    off64_t eocdOffset = searchStart + i;
     const unsigned char* eocdPtr = scanBuf + i;
 
     assert(eocdOffset < mFileLength);
@@ -473,7 +473,7 @@
  * appear to be bogus.
  */
 bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
-    size_t* pCompLen, off_t* pOffset, long* pModWhen, long* pCrc32) const
+    size_t* pCompLen, off64_t* pOffset, long* pModWhen, long* pCrc32) const
 {
     bool ret = false;
 
@@ -489,7 +489,7 @@
      * so we can just subtract back from that.
      */
     const unsigned char* ptr = (const unsigned char*) hashEntry.name;
-    off_t cdOffset = mDirectoryOffset;
+    off64_t cdOffset = mDirectoryOffset;
 
     ptr -= kCDELen;
 
@@ -536,12 +536,12 @@
 #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
+         * so we need to do an pread64() instead of a lseek64() + read() to
          * guarantee atomicity across the processes with the shared file
          * descriptors.
          */
         ssize_t actual =
-                TEMP_FAILURE_RETRY(pread(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
+                TEMP_FAILURE_RETRY(pread64(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset));
 
         if (actual != sizeof(lfhBuf)) {
             LOGW("failed reading lfh from offset %ld\n", localHdrOffset);
@@ -556,17 +556,17 @@
         }
 #else /* HAVE_PREAD */
         /*
-         * For hosts don't have pread() we cannot guarantee atomic reads from
+         * For hosts don't have pread64() 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.
+         * calling lseek64() concurrently.
          */
 
         {
             AutoMutex _l(mFdLock);
 
-            if (lseek(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
+            if (lseek64(mFd, localHdrOffset, SEEK_SET) != localHdrOffset) {
                 LOGW("failed seeking to lfh at offset %ld\n", localHdrOffset);
                 return false;
             }
@@ -579,7 +579,7 @@
             }
 
             if (get4LE(lfhBuf) != kLFHSignature) {
-                off_t actualOffset = lseek(mFd, 0, SEEK_CUR);
+                off64_t actualOffset = lseek64(mFd, 0, SEEK_CUR);
                 LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; "
                         "got: offset=" ZD " data=0x%08lx\n",
                         localHdrOffset, kLFHSignature, (ZD_TYPE) actualOffset, get4LE(lfhBuf));
@@ -588,7 +588,7 @@
         }
 #endif /* HAVE_PREAD */
 
-        off_t dataOffset = localHdrOffset + kLFHLen
+        off64_t dataOffset = localHdrOffset + kLFHLen
             + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
         if (dataOffset >= cdOffset) {
             LOGW("bad data offset %ld in zip\n", (long) dataOffset);
@@ -596,14 +596,14 @@
         }
 
         /* check lengths */
-        if ((off_t)(dataOffset + compLen) > cdOffset) {
+        if ((off64_t)(dataOffset + compLen) > cdOffset) {
             LOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
                 (long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
             return false;
         }
 
         if (method == kCompressStored &&
-            (off_t)(dataOffset + uncompLen) > cdOffset)
+            (off64_t)(dataOffset + uncompLen) > cdOffset)
         {
             LOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
                 (long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
@@ -649,7 +649,7 @@
 
     FileMap* newMap;
     size_t compLen;
-    off_t offset;
+    off64_t offset;
 
     if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL))
         return NULL;
@@ -679,7 +679,7 @@
 
     int method;
     size_t uncompLen, compLen;
-    off_t offset;
+    off64_t offset;
     const unsigned char* ptr;
 
     getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
@@ -739,7 +739,7 @@
 
     int method;
     size_t uncompLen, compLen;
-    off_t offset;
+    off64_t offset;
     const unsigned char* ptr;
 
     getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);