diff options
Diffstat (limited to '')
-rw-r--r-- | minzip/Android.mk | 36 | ||||
-rw-r--r-- | minzip/SysUtil.c | 77 | ||||
-rw-r--r-- | minzip/Zip.c | 14 | ||||
-rw-r--r-- | minzip/Zip.h | 4 |
4 files changed, 107 insertions, 24 deletions
diff --git a/minzip/Android.mk b/minzip/Android.mk index 22eabfbb1..8b52f35dd 100644 --- a/minzip/Android.mk +++ b/minzip/Android.mk @@ -12,10 +12,44 @@ LOCAL_C_INCLUDES := \ external/zlib \ external/safe-iop/include -LOCAL_STATIC_LIBRARIES := libselinux +LOCAL_C_INCLUDES += external/libselinux/include +LOCAL_SHARED_LIBRARIES += libselinux + +LOCAL_CFLAGS += -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) LOCAL_MODULE := libminzip +LOCAL_SHARED_LIBRARIES += libz + +LOCAL_CLANG := true + +LOCAL_CFLAGS += -Werror -Wall + +include $(BUILD_SHARED_LIBRARY) + + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Hash.c \ + SysUtil.c \ + DirUtil.c \ + Inlines.c \ + Zip.c + +LOCAL_C_INCLUDES += \ + external/zlib \ + external/safe-iop/include + +LOCAL_C_INCLUDES += external/libselinux/include +LOCAL_STATIC_LIBRARIES += libselinux + +LOCAL_CFLAGS += -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) + +LOCAL_MODULE := libminzip + +LOCAL_STATIC_LIBRARIES += libz + LOCAL_CLANG := true LOCAL_CFLAGS += -Werror -Wall diff --git a/minzip/SysUtil.c b/minzip/SysUtil.c index e7dd17b51..9c3575b9c 100644 --- a/minzip/SysUtil.c +++ b/minzip/SysUtil.c @@ -20,32 +20,76 @@ #include "Log.h" #include "SysUtil.h" +static int getFileStartAndLength(int fd, loff_t *start_, size_t *length_) +{ + loff_t start, end; + size_t length; + + assert(start_ != NULL); + assert(length_ != NULL); + + // TODO: isn't start always 0 for the single call site? just use fstat instead? + + start = TEMP_FAILURE_RETRY(lseek64(fd, 0L, SEEK_CUR)); + end = TEMP_FAILURE_RETRY(lseek64(fd, 0L, SEEK_END)); + + if (TEMP_FAILURE_RETRY(lseek64(fd, start, SEEK_SET)) == -1 || + start == (loff_t) -1 || end == (loff_t) -1) { + LOGE("could not determine length of file\n"); + return -1; + } + + length = end - start; + if (length == 0) { + LOGE("file is empty\n"); + return -1; + } + + *start_ = start; + *length_ = length; + + return 0; +} + +/* + * Map a file (from fd's current offset) into a private, read-only memory + * segment. The file offset must be a multiple of the page size. + * + * On success, returns 0 and fills out "pMap". On failure, returns a nonzero + * value and does not disturb "pMap". + */ static bool sysMapFD(int fd, MemMapping* pMap) { + loff_t start; + size_t length; + void* memPtr; + assert(pMap != NULL); - struct stat sb; - if (fstat(fd, &sb) == -1) { - LOGE("fstat(%d) failed: %s\n", fd, strerror(errno)); - return false; - } + if (getFileStartAndLength(fd, &start, &length) < 0) + return -1; - void* memPtr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); +#if (PLATFORM_SDK_VERSION >= 21) + memPtr = mmap64(NULL, length, PROT_READ, MAP_PRIVATE, fd, start); +#else + // Older versions of Android do not have mmap64 so we will just use mmap instead + memPtr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, start); +#endif if (memPtr == MAP_FAILED) { - LOGE("mmap(%d, R, PRIVATE, %d, 0) failed: %s\n", (int) sb.st_size, fd, strerror(errno)); + LOGE("mmap(%d, R, PRIVATE, %d, 0) failed: %s\n", (int) length, fd, strerror(errno)); return false; } pMap->addr = memPtr; - pMap->length = sb.st_size; + pMap->length = length; pMap->range_count = 1; pMap->ranges = malloc(sizeof(MappedRange)); if (pMap->ranges == NULL) { LOGE("malloc failed: %s\n", strerror(errno)); - munmap(memPtr, sb.st_size); + munmap(memPtr, length); return false; } pMap->ranges[0].addr = memPtr; - pMap->ranges[0].length = sb.st_size; + pMap->ranges[0].length = length; return true; } @@ -92,7 +136,12 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) // Reserve enough contiguous address space for the whole file. unsigned char* reserve; +#if (PLATFORM_SDK_VERSION >= 21) reserve = mmap64(NULL, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); +#else + // Older versions of Android do not have mmap64 so we will just use mmap instead + reserve = mmap(NULL, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0); +#endif if (reserve == MAP_FAILED) { LOGE("failed to reserve address space: %s\n", strerror(errno)); free(pMap->ranges); @@ -123,8 +172,12 @@ static int sysMapBlockFile(FILE* mapf, MemMapping* pMap) success = false; break; } - - void* addr = mmap64(next, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize); +#if (PLATFORM_SDK_VERSION >= 21) + void* addr = mmap64(next, (end-start)*blksize, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize); +#else + // Older versions of Android do not have mmap64 so we will just use mmap instead + void* addr = mmap(next, (end-start)*blksize, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, ((off64_t)start)*blksize); +#endif if (addr == MAP_FAILED) { LOGE("failed to map block %d: %s\n", i, strerror(errno)); success = false; diff --git a/minzip/Zip.c b/minzip/Zip.c index bdb565c64..1c3239df4 100644 --- a/minzip/Zip.c +++ b/minzip/Zip.c @@ -366,7 +366,7 @@ static bool parseZipArchive(ZipArchive* pArchive) } pEntry->offset = localHdrOffset + LOCHDR + get2LE(localHdr + LOCNAM) + get2LE(localHdr + LOCEXT); - if (!safe_add(NULL, pEntry->offset, pEntry->compLen)) { + if (!safe_add(NULL, pEntry->offset, (typeof(pEntry->offset))pEntry->compLen)) { LOGW("Integer overflow adding in parseZipArchive\n"); goto bail; } @@ -427,6 +427,8 @@ int mzOpenZipArchive(unsigned char* addr, size_t length, ZipArchive* pArchive) { int err; + memset(pArchive, 0, sizeof(ZipArchive)); + if (length < ENDHDR) { err = -1; LOGW("Archive %p is too small to be zip (%zd)\n", pArchive, length); @@ -966,8 +968,7 @@ bool mzExtractRecursive(const ZipArchive *pArchive, setfscreatecon(secontext); } - int fd = open(targetFile, O_CREAT|O_WRONLY|O_TRUNC|O_SYNC, - UNZIP_FILEMODE); + int fd = creat(targetFile, UNZIP_FILEMODE); if (secontext) { freecon(secontext); @@ -982,12 +983,7 @@ bool mzExtractRecursive(const ZipArchive *pArchive, } bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd); - if (ok) { - ok = (fsync(fd) == 0); - } - if (close(fd) != 0) { - ok = false; - } + close(fd); if (!ok) { LOGE("Error extracting \"%s\"\n", targetFile); ok = false; diff --git a/minzip/Zip.h b/minzip/Zip.h index 86d8db597..0a0345159 100644 --- a/minzip/Zip.h +++ b/minzip/Zip.h @@ -32,7 +32,7 @@ extern "C" { typedef struct ZipEntry { unsigned int fileNameLen; const char* fileName; // not null-terminated - long offset; + loff_t offset; long compLen; long uncompLen; int compression; @@ -85,7 +85,7 @@ void mzCloseZipArchive(ZipArchive* pArchive); const ZipEntry* mzFindZipEntry(const ZipArchive* pArchive, const char* entryName); -INLINE long mzGetZipEntryOffset(const ZipEntry* pEntry) { +INLINE loff_t mzGetZipEntryOffset(const ZipEntry* pEntry) { return pEntry->offset; } INLINE long mzGetZipEntryUncompLen(const ZipEntry* pEntry) { |