Update Zlib to version 1.2.8

merge the latest open source zlib into chromium external projects
Version 1.2.8 fixes a very rare bug in decompression. All users are encouraged to upgrade immediately. Version 1.2.8 also has these improvements:
- Add new inflateGetDictionary() function
- Fix bug where gzopen() immediately followed by gzclose() would write an empty file instead of an empty gzip stream.
- Fix bug in gzclose() when gzwrite() runs out of memory Version 1.2.7 has many portability improvements over 1.2.6, and has these enhancements:
- Fix bug in gzclose_w() when gzwrite() fails to allocate memory
- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen()
- Add gzopen_w() in Windows for wide character path names
- Fix type mismatch between get_crc_table() and crc_table Version 1.2.6 has many changes over 1.2.5, including these improvements:
- gzread() can now read a file that is being written concurrently
- gzgetc() is now a macro for increased speed
- Added a 'T' option to gzopen() for transparent writing (no compression)
- Added deflatePending() to return the amount of pending output
- Allow deflateSetDictionary() and inflateSetDictionary() at any time in raw mode
- deflatePrime() can now insert bits in the middle of the stream
- ./configure now creates a configure.log file with all of the results
- Added a ./configure --solo option to compile zlib with no dependency on any libraries
- Fixed a problem with large file support macros
- Fixed a bug in contrib/puff
- Many portability improvements

BUG=610615 R=gavinp@chromium.org

Review-Url: https://codereview.chromium.org/2084863002
Cr-Original-Commit-Position: refs/heads/master@{#401538}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: ca1c569cff20aa43a42816791744d847c7d788de
diff --git a/README.chromium b/README.chromium
index ddb63d7..df609b2 100644
--- a/README.chromium
+++ b/README.chromium
@@ -36,3 +36,11 @@
 - read_buf was moved from local to ZLIB_INTERNAL for fill_window_sse.c to use
 - INSERT_STRING macro was made a function, insert_string() and an implementation using CRC instruction added
 - some crc funcionality moved into crc32.c
+
+Update to zlib-1.2.8, generate a third patch which includes the jtkukunas optimisations. We may merge some more from jtkukunas branch later.
+Currently we upgrade to madler's version 1.2.8,merged SIMD optimisation and
+some other changes above.
+The step as follows:
+1.download a clean madler zlib from github.
+2.apply google.patch, mixed.patch, simd.patch sequencely.
+3.update these patches.
diff --git a/adler32.c b/adler32.c
index 65ad6a5..a868f07 100644
--- a/adler32.c
+++ b/adler32.c
@@ -1,5 +1,5 @@
 /* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2007 Mark Adler
+ * Copyright (C) 1995-2011 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,9 +9,9 @@
 
 #define local static
 
-local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
 
-#define BASE 65521UL    /* largest prime smaller than 65536 */
+#define BASE 65521      /* largest prime smaller than 65536 */
 #define NMAX 5552
 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
 
@@ -21,39 +21,44 @@
 #define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
 #define DO16(buf)   DO8(buf,0); DO8(buf,8);
 
-/* use NO_DIVIDE if your processor does not do division in hardware */
+/* use NO_DIVIDE if your processor does not do division in hardware --
+   try it both ways to see which is faster */
 #ifdef NO_DIVIDE
-#  define MOD(a) \
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+   (thank you to John Reiser for pointing this out) */
+#  define CHOP(a) \
     do { \
-        if (a >= (BASE << 16)) a -= (BASE << 16); \
-        if (a >= (BASE << 15)) a -= (BASE << 15); \
-        if (a >= (BASE << 14)) a -= (BASE << 14); \
-        if (a >= (BASE << 13)) a -= (BASE << 13); \
-        if (a >= (BASE << 12)) a -= (BASE << 12); \
-        if (a >= (BASE << 11)) a -= (BASE << 11); \
-        if (a >= (BASE << 10)) a -= (BASE << 10); \
-        if (a >= (BASE << 9)) a -= (BASE << 9); \
-        if (a >= (BASE << 8)) a -= (BASE << 8); \
-        if (a >= (BASE << 7)) a -= (BASE << 7); \
-        if (a >= (BASE << 6)) a -= (BASE << 6); \
-        if (a >= (BASE << 5)) a -= (BASE << 5); \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        unsigned long tmp = a >> 16; \
+        a &= 0xffffUL; \
+        a += (tmp << 4) - tmp; \
+    } while (0)
+#  define MOD28(a) \
+    do { \
+        CHOP(a); \
         if (a >= BASE) a -= BASE; \
     } while (0)
-#  define MOD4(a) \
+#  define MOD(a) \
     do { \
-        if (a >= (BASE << 4)) a -= (BASE << 4); \
-        if (a >= (BASE << 3)) a -= (BASE << 3); \
-        if (a >= (BASE << 2)) a -= (BASE << 2); \
-        if (a >= (BASE << 1)) a -= (BASE << 1); \
+        CHOP(a); \
+        MOD28(a); \
+    } while (0)
+#  define MOD63(a) \
+    do { /* this assumes a is not negative */ \
+        z_off64_t tmp = a >> 32; \
+        a &= 0xffffffffL; \
+        a += (tmp << 8) - (tmp << 5) + tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
+        tmp = a >> 16; \
+        a &= 0xffffL; \
+        a += (tmp << 4) - tmp; \
         if (a >= BASE) a -= BASE; \
     } while (0)
 #else
 #  define MOD(a) a %= BASE
-#  define MOD4(a) a %= BASE
+#  define MOD28(a) a %= BASE
+#  define MOD63(a) a %= BASE
 #endif
 
 /* ========================================================================= */
@@ -92,7 +97,7 @@
         }
         if (adler >= BASE)
             adler -= BASE;
-        MOD4(sum2);             /* only added so many BASE's */
+        MOD28(sum2);            /* only added so many BASE's */
         return adler | (sum2 << 16);
     }
 
@@ -137,8 +142,13 @@
     unsigned long sum2;
     unsigned rem;
 
+    /* for negative len, return invalid adler32 as a clue for debugging */
+    if (len2 < 0)
+        return 0xffffffffUL;
+
     /* the derivation of this formula is left as an exercise for the reader */
-    rem = (unsigned)(len2 % BASE);
+    MOD63(len2);                /* assumes len2 >= 0 */
+    rem = (unsigned)len2;
     sum1 = adler1 & 0xffff;
     sum2 = rem * sum1;
     MOD(sum2);
diff --git a/compress.c b/compress.c
index ea4dfbe..6e97626 100644
--- a/compress.c
+++ b/compress.c
@@ -29,7 +29,7 @@
     z_stream stream;
     int err;
 
-    stream.next_in = (Bytef*)source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
 #ifdef MAXSEG_64K
     /* Check for source > 64K on 16-bit machine: */
diff --git a/contrib/minizip/crypt.h b/contrib/minizip/crypt.h
index a01d08d..1e9e820 100644
--- a/contrib/minizip/crypt.h
+++ b/contrib/minizip/crypt.h
@@ -32,7 +32,7 @@
 /***********************************************************************
  * Return the next byte in the pseudo-random sequence
  */
-static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
+static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
 {
     unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
                      * unpredictable manner on 16-bit systems; not a problem
@@ -45,7 +45,7 @@
 /***********************************************************************
  * Update the encryption keys with the next byte of plain text
  */
-static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
+static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c)
 {
     (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
     (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
@@ -62,7 +62,7 @@
  * Initialize the encryption keys and the random header according to
  * the given password.
  */
-static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
+static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab)
 {
     *(pkeys+0) = 305419896L;
     *(pkeys+1) = 591751049L;
@@ -91,7 +91,7 @@
                      unsigned char* buf,      /* where to write header */
                      int bufSize,
                      unsigned long* pkeys,
-                     const unsigned long* pcrc_32_tab,
+                     const z_crc_t* pcrc_32_tab,
                      unsigned long crcForCrypting)
 {
     int n;                       /* index in random header */
diff --git a/contrib/minizip/ioapi.c b/contrib/minizip/ioapi.c
index 49958f6..7f5c191 100644
--- a/contrib/minizip/ioapi.c
+++ b/contrib/minizip/ioapi.c
@@ -10,10 +10,22 @@
 
 */
 
-#if (defined(_WIN32))
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
         #define _CRT_SECURE_NO_WARNINGS
 #endif
 
+#if defined(__APPLE__) || defined(IOAPI_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
 #include "ioapi.h"
 
 voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)
@@ -47,7 +59,7 @@
     else
     {
         uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
-        if ((tell_uLong) == ((uLong)-1))
+        if ((tell_uLong) == MAXU32)
             return (ZPOS64_T)-1;
         else
             return tell_uLong;
@@ -112,7 +124,7 @@
         mode_fopen = "wb";
 
     if ((filename!=NULL) && (mode_fopen != NULL))
-        file = fopen64((const char*)filename, mode_fopen);
+        file = FOPEN_FUNC((const char*)filename, mode_fopen);
     return file;
 }
 
@@ -142,7 +154,7 @@
 static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
 {
     ZPOS64_T ret;
-    ret = ftello64((FILE *)stream);
+    ret = FTELLO_FUNC((FILE *)stream);
     return ret;
 }
 
@@ -188,7 +200,7 @@
     }
     ret = 0;
 
-    if(fseeko64((FILE *)stream, offset, fseek_origin) != 0)
+    if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
                         ret = -1;
 
     return ret;
diff --git a/contrib/minizip/ioapi.h b/contrib/minizip/ioapi.h
index dfa3b6c..c1b7a54 100644
--- a/contrib/minizip/ioapi.h
+++ b/contrib/minizip/ioapi.h
@@ -21,7 +21,7 @@
 #ifndef _ZLIBIOAPI64_H
 #define _ZLIBIOAPI64_H
 
-#if (!defined(_WIN32)) && (!defined(WIN32))
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
 
   // Linux needs this to support file operation on files larger then 4+GB
   // But might need better if/def to select just the platforms that needs them.
@@ -38,6 +38,7 @@
         #ifndef _FILE_OFFSET_BIT
                 #define _FILE_OFFSET_BIT 64
         #endif
+
 #endif
 
 #include <stdio.h>
@@ -49,6 +50,11 @@
 #define ftello64 ftell
 #define fseeko64 fseek
 #else
+#ifdef __FreeBSD__
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
 #ifdef _MSC_VER
  #define fopen64 fopen
  #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
@@ -85,6 +91,8 @@
 typedef uint64_t ZPOS64_T;
 #else
 
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#define MAXU32 0xffffffff
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 typedef unsigned __int64 ZPOS64_T;
diff --git a/contrib/minizip/iowin32.c b/contrib/minizip/iowin32.c
index 6a2a883..0467c31 100644
--- a/contrib/minizip/iowin32.c
+++ b/contrib/minizip/iowin32.c
@@ -25,6 +25,20 @@
 #define INVALID_SET_FILE_POINTER ((DWORD)-1)
 #endif
 
+
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x601
+#endif
+
+#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
+#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API)))
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+#define IOWIN32_USING_WINRT_API 1
+#endif
+#endif
+#endif
+
 voidpf  ZCALLBACK win32_open_file_func  OF((voidpf opaque, const char* filename, int mode));
 uLong   ZCALLBACK win32_read_file_func  OF((voidpf opaque, voidpf stream, void* buf, uLong size));
 uLong   ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
@@ -93,8 +107,22 @@
 
     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
 
+#ifdef IOWIN32_USING_WINRT_API
+#ifdef UNICODE
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#endif
+#else
     if ((filename!=NULL) && (dwDesiredAccess != 0))
         hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
 
     return win32_build_iowin(hFile);
 }
@@ -108,8 +136,17 @@
 
     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
 
+#ifdef IOWIN32_USING_WINRT_API
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#else
     if ((filename!=NULL) && (dwDesiredAccess != 0))
         hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
 
     return win32_build_iowin(hFile);
 }
@@ -123,8 +160,13 @@
 
     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
 
+#ifdef IOWIN32_USING_WINRT_API
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL);
+#else
     if ((filename!=NULL) && (dwDesiredAccess != 0))
         hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
 
     return win32_build_iowin(hFile);
 }
@@ -138,8 +180,22 @@
 
     win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes);
 
+#ifdef IOWIN32_USING_WINRT_API
+#ifdef UNICODE
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+        hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+#else
+    if ((filename!=NULL) && (dwDesiredAccess != 0))
+    {
+        WCHAR filenameW[FILENAME_MAX + 0x200 + 1];
+        MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200);
+        hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL);
+    }
+#endif
+#else
     if ((filename!=NULL) && (dwDesiredAccess != 0))
         hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);
+#endif
 
     return win32_build_iowin(hFile);
 }
@@ -188,6 +244,26 @@
     return ret;
 }
 
+static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos,  DWORD dwMoveMethod)
+{
+#ifdef IOWIN32_USING_WINRT_API
+    return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod);
+#else
+    LONG lHigh = pos.HighPart;
+    DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod);
+    BOOL fOk = TRUE;
+    if (dwNewPos == 0xFFFFFFFF)
+        if (GetLastError() != NO_ERROR)
+            fOk = FALSE;
+    if ((newPos != NULL) && (fOk))
+    {
+        newPos->LowPart = dwNewPos;
+        newPos->HighPart = lHigh;
+    }
+    return fOk;
+#endif
+}
+
 long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream)
 {
     long ret=-1;
@@ -196,15 +272,17 @@
         hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
     if (hFile != NULL)
     {
-        DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
-        if (dwSet == INVALID_SET_FILE_POINTER)
+        LARGE_INTEGER pos;
+        pos.QuadPart = 0;
+
+        if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
             ret = -1;
         }
         else
-            ret=(long)dwSet;
+            ret=(long)pos.LowPart;
     }
     return ret;
 }
@@ -218,17 +296,17 @@
 
     if (hFile)
     {
-        LARGE_INTEGER li;
-        li.QuadPart = 0;
-        li.u.LowPart = SetFilePointer(hFile, li.u.LowPart, &li.u.HighPart, FILE_CURRENT);
-        if ( (li.LowPart == 0xFFFFFFFF) && (GetLastError() != NO_ERROR))
+        LARGE_INTEGER pos;
+        pos.QuadPart = 0;
+
+        if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
             ret = (ZPOS64_T)-1;
         }
         else
-            ret=li.QuadPart;
+            ret=pos.QuadPart;
     }
     return ret;
 }
@@ -258,8 +336,9 @@
 
     if (hFile != NULL)
     {
-        DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
-        if (dwSet == INVALID_SET_FILE_POINTER)
+        LARGE_INTEGER pos;
+        pos.QuadPart = offset;
+        if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
@@ -296,9 +375,9 @@
 
     if (hFile)
     {
-        LARGE_INTEGER* li = (LARGE_INTEGER*)&offset;
-        DWORD dwSet = SetFilePointer(hFile, li->u.LowPart, &li->u.HighPart, dwMoveMethod);
-        if (dwSet == INVALID_SET_FILE_POINTER)
+        LARGE_INTEGER pos;
+        pos.QuadPart = offset;
+        if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod))
         {
             DWORD dwErr = GetLastError();
             ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
diff --git a/contrib/minizip/miniunz.c b/contrib/minizip/miniunz.c
index 9ed009f..3d65401 100644
--- a/contrib/minizip/miniunz.c
+++ b/contrib/minizip/miniunz.c
@@ -12,7 +12,7 @@
          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
 */
 
-#ifndef _WIN32
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
         #ifndef __USE_FILE_OFFSET64
                 #define __USE_FILE_OFFSET64
         #endif
@@ -27,6 +27,18 @@
         #endif
 #endif
 
+#ifdef __APPLE__
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -34,14 +46,15 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#ifdef unix
-# include <unistd.h>
-# include <utime.h>
-#else
+#ifdef _WIN32
 # include <direct.h>
 # include <io.h>
+#else
+# include <unistd.h>
+# include <utime.h>
 #endif
 
+
 #include "unzip.h"
 
 #define CASESENSITIVITY (0)
@@ -84,7 +97,7 @@
   SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
   CloseHandle(hFile);
 #else
-#ifdef unix
+#ifdef unix || __APPLE__
   struct utimbuf ut;
   struct tm newdate;
   newdate.tm_sec = tmu_date.tm_sec;
@@ -114,10 +127,10 @@
     int ret=0;
 #ifdef _WIN32
     ret = _mkdir(dirname);
-#else
-#ifdef unix
+#elif unix
     ret = mkdir (dirname,0775);
-#endif
+#elif __APPLE__
+    ret = mkdir (dirname,0775);
 #endif
     return ret;
 }
@@ -364,7 +377,7 @@
         {
             char rep=0;
             FILE* ftestexist;
-            ftestexist = fopen64(write_filename,"rb");
+            ftestexist = FOPEN_FUNC(write_filename,"rb");
             if (ftestexist!=NULL)
             {
                 fclose(ftestexist);
@@ -395,8 +408,7 @@
 
         if ((skip==0) && (err==UNZ_OK))
         {
-            fout=fopen64(write_filename,"wb");
-
+            fout=FOPEN_FUNC(write_filename,"wb");
             /* some zipfile don't contain directory alone before file */
             if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
                                 (filename_withoutpath!=(char*)filename_inzip))
@@ -405,7 +417,7 @@
                 *(filename_withoutpath-1)='\0';
                 makedir(write_filename);
                 *(filename_withoutpath-1)=c;
-                fout=fopen64(write_filename,"wb");
+                fout=FOPEN_FUNC(write_filename,"wb");
             }
 
             if (fout==NULL)
diff --git a/contrib/minizip/minizip.c b/contrib/minizip/minizip.c
index 7a4fa5a..4288962 100644
--- a/contrib/minizip/minizip.c
+++ b/contrib/minizip/minizip.c
@@ -13,7 +13,7 @@
 */
 
 
-#ifndef _WIN32
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
         #ifndef __USE_FILE_OFFSET64
                 #define __USE_FILE_OFFSET64
         #endif
@@ -28,6 +28,19 @@
         #endif
 #endif
 
+#ifdef __APPLE__
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,14 +48,14 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#ifdef unix
+#ifdef _WIN32
+# include <direct.h>
+# include <io.h>
+#else
 # include <unistd.h>
 # include <utime.h>
 # include <sys/types.h>
 # include <sys/stat.h>
-#else
-# include <direct.h>
-# include <io.h>
 #endif
 
 #include "zip.h"
@@ -81,7 +94,7 @@
   return ret;
 }
 #else
-#ifdef unix
+#ifdef unix || __APPLE__
 uLong filetime(f, tmzip, dt)
     char *f;               /* name of file to get info on */
     tm_zip *tmzip;         /* return value: access, modific. and creation times */
@@ -142,7 +155,7 @@
 {
     FILE* ftestexist;
     int ret = 1;
-    ftestexist = fopen64(filename,"rb");
+    ftestexist = FOPEN_FUNC(filename,"rb");
     if (ftestexist==NULL)
         ret = 0;
     else
@@ -173,7 +186,8 @@
 {
    unsigned long calculate_crc=0;
    int err=ZIP_OK;
-   FILE * fin = fopen64(filenameinzip,"rb");
+   FILE * fin = FOPEN_FUNC(filenameinzip,"rb");
+
    unsigned long size_read = 0;
    unsigned long total_read = 0;
    if (fin==NULL)
@@ -211,13 +225,12 @@
 {
   int largeFile = 0;
   ZPOS64_T pos = 0;
-  FILE* pFile = fopen64(filename, "rb");
+  FILE* pFile = FOPEN_FUNC(filename, "rb");
 
   if(pFile != NULL)
   {
-    int n = fseeko64(pFile, 0, SEEK_END);
-
-    pos = ftello64(pFile);
+    int n = FSEEKO_FUNC(pFile, 0, SEEK_END);
+    pos = FTELLO_FUNC(pFile);
 
                 printf("File : %s is %lld bytes\n", filename, pos);
 
@@ -447,7 +460,7 @@
                     printf("error in opening %s in zipfile\n",filenameinzip);
                 else
                 {
-                    fin = fopen64(filenameinzip,"rb");
+                    fin = FOPEN_FUNC(filenameinzip,"rb");
                     if (fin==NULL)
                     {
                         err=ZIP_ERRNO;
diff --git a/contrib/minizip/mztools.c b/contrib/minizip/mztools.c
index 026bf28..8bf9cca 100644
--- a/contrib/minizip/mztools.c
+++ b/contrib/minizip/mztools.c
@@ -42,7 +42,7 @@
     int entries = 0;
     uLong totalBytes = 0;
     char header[30];
-    char filename[256];
+    char filename[1024];
     char extra[1024];
     int offset = 0;
     int offsetCD = 0;
@@ -73,9 +73,14 @@
 
         /* Filename */
         if (fnsize > 0) {
-          if (fread(filename, 1, fnsize, fpZip) == fnsize) {
-            if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
-              offset += fnsize;
+          if (fnsize < sizeof(filename)) {
+            if (fread(filename, 1, fnsize, fpZip) == fnsize) {
+                if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
+                offset += fnsize;
+              } else {
+                err = Z_ERRNO;
+                break;
+              }
             } else {
               err = Z_ERRNO;
               break;
@@ -91,9 +96,14 @@
 
         /* Extra field */
         if (extsize > 0) {
-          if (fread(extra, 1, extsize, fpZip) == extsize) {
-            if (fwrite(extra, 1, extsize, fpOut) == extsize) {
-              offset += extsize;
+          if (extsize < sizeof(extra)) {
+            if (fread(extra, 1, extsize, fpZip) == extsize) {
+              if (fwrite(extra, 1, extsize, fpOut) == extsize) {
+                offset += extsize;
+                } else {
+                err = Z_ERRNO;
+                break;
+              }
             } else {
               err = Z_ERRNO;
               break;
diff --git a/contrib/minizip/mztools.h b/contrib/minizip/mztools.h
index 90c834d..f295ffe 100644
--- a/contrib/minizip/mztools.h
+++ b/contrib/minizip/mztools.h
@@ -28,4 +28,10 @@
                              uLong* nRecovered,
                              uLong* bytesRecovered);
 
+
+#ifdef __cplusplus
+}
+#endif
+
+
 #endif
diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c
index af59b80..2d5f0b1 100644
--- a/contrib/minizip/unzip.c
+++ b/contrib/minizip/unzip.c
@@ -188,7 +188,7 @@
 
 #    ifndef NOUNCRYPT
     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
+    const z_crc_t* pcrc_32_tab;
 #    endif
 } unz64_s;
 
@@ -801,9 +801,9 @@
 }
 
 /*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  Close a ZipFile opened with unzOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
   return UNZ_OK if there is no problem. */
 extern int ZEXPORT unzClose (unzFile file)
 {
@@ -1040,26 +1040,26 @@
             {
                                                         uLong uL;
 
-                                                                if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1)
+                                                                if(file_info.uncompressed_size == MAXU32)
                                                                 {
                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
                                                                                         err=UNZ_ERRNO;
                                                                 }
 
-                                                                if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1)
+                                                                if(file_info.compressed_size == MAXU32)
                                                                 {
                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
                                                                                   err=UNZ_ERRNO;
                                                                 }
 
-                                                                if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1)
+                                                                if(file_info_internal.offset_curfile == MAXU32)
                                                                 {
                                                                         /* Relative Header offset */
                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
                                                                                 err=UNZ_ERRNO;
                                                                 }
 
-                                                                if(file_info.disk_num_start == (unsigned long)-1)
+                                                                if(file_info.disk_num_start == MAXU32)
                                                                 {
                                                                         /* Disk Start Number */
                                                                         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
@@ -1145,7 +1145,7 @@
                                                 szFileName,fileNameBufferSize,
                                                 extraField,extraFieldBufferSize,
                                                 szComment,commentBufferSize);
-    if (err==UNZ_OK)
+    if ((err==UNZ_OK) && (pfile_info != NULL))
     {
         pfile_info->version = file_info64.version;
         pfile_info->version_needed = file_info64.version_needed;
@@ -1223,7 +1223,7 @@
 
 /*
   Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzipStringFileNameCompare
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
 
   return value :
   UNZ_OK if the file is found. It becomes the current file.
@@ -1696,7 +1696,7 @@
         return UNZ_PARAMERROR;
 
 
-    if ((pfile_in_zip_read_info->read_buffer == NULL))
+    if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
         return 0;
@@ -1993,7 +1993,7 @@
 }
 
 /*
-  Close the file in zip opened with unzipOpenCurrentFile
+  Close the file in zip opened with unzOpenCurrentFile
   Return UNZ_CRCERROR if all the file was read but the CRC is not good
 */
 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
diff --git a/contrib/minizip/unzip.h b/contrib/minizip/unzip.h
index 80eb36e..3c01435 100644
--- a/contrib/minizip/unzip.h
+++ b/contrib/minizip/unzip.h
@@ -197,9 +197,9 @@
 
 extern int ZEXPORT unzClose OF((unzFile file));
 /*
-  Close a ZipFile opened with unzipOpen.
+  Close a ZipFile opened with unzOpen.
   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+    these files MUST be closed with unzCloseCurrentFile before call unzClose.
   return UNZ_OK if there is no problem. */
 
 extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
diff --git a/contrib/minizip/zip.c b/contrib/minizip/zip.c
index 5a82885..aaf6961 100644
--- a/contrib/minizip/zip.c
+++ b/contrib/minizip/zip.c
@@ -157,7 +157,7 @@
     ZPOS64_T totalUncompressedData;
 #ifndef NOCRYPT
     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
-    const unsigned long* pcrc_32_tab;
+    const z_crc_t* pcrc_32_tab;
     int crypt_header_size;
 #endif
 } curfile64_info;
@@ -1067,6 +1067,7 @@
     int err = ZIP_OK;
 
 #    ifdef NOCRYPT
+    (crcForCrypting);
     if (password != NULL)
         return ZIP_PARAMERROR;
 #    endif
@@ -1114,9 +1115,9 @@
     zi->ci.flag = flagBase;
     if ((level==8) || (level==9))
       zi->ci.flag |= 2;
-    if ((level==2))
+    if (level==2)
       zi->ci.flag |= 4;
-    if ((level==1))
+    if (level==1)
       zi->ci.flag |= 6;
     if (password != NULL)
       zi->ci.flag |= 1;
@@ -1710,7 +1711,7 @@
         if (err==ZIP_OK)
             err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
 
-        if(uncompressed_size >= 0xffffffff)
+        if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
         {
           if(zi->ci.pos_zip64extrainfo > 0)
           {
@@ -1724,6 +1725,8 @@
             if (err==ZIP_OK) /* uncompressed size, unknown */
               err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
           }
+          else
+              err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
         }
         else
         {
@@ -1852,7 +1855,7 @@
       err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
     }
     else
-                  err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
+      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
   }
 
    return err;
@@ -1919,7 +1922,7 @@
     free_linkedlist(&(zi->central_dir));
 
     pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
-    if(pos >= 0xffffffff)
+    if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
     {
       ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
       Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
diff --git a/crc32.c b/crc32.c
index 75f2290..09228ed 100644
--- a/crc32.c
+++ b/crc32.c
@@ -1,5 +1,5 @@
 /* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2006, 2010 Mark Adler
+ * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  *
  * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
@@ -17,6 +17,8 @@
   of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
   first call get_crc_table() to initialize the tables before allowing more than
   one thread to use crc32().
+
+  DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
  */
 
 #ifdef MAKECRCH
@@ -32,31 +34,11 @@
 
 #define local static
 
-/* Find a four-byte integer type for crc32_little() and crc32_big(). */
-#ifndef NOBYFOUR
-#  ifdef STDC           /* need ANSI C limits.h to determine sizes */
-#    include <limits.h>
-#    define BYFOUR
-#    if (UINT_MAX == 0xffffffffUL)
-       typedef unsigned int u4;
-#    else
-#      if (ULONG_MAX == 0xffffffffUL)
-         typedef unsigned long u4;
-#      else
-#        if (USHRT_MAX == 0xffffffffUL)
-           typedef unsigned short u4;
-#        else
-#          undef BYFOUR     /* can't find a four-byte integer type! */
-#        endif
-#      endif
-#    endif
-#  endif /* STDC */
-#endif /* !NOBYFOUR */
-
 /* Definitions for doing the crc four data bytes at a time. */
+#if !defined(NOBYFOUR) && defined(Z_U4)
+#  define BYFOUR
+#endif
 #ifdef BYFOUR
-#  define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
-                (((w)&0xff00)<<8)+(((w)&0xff)<<24))
    local unsigned long crc32_little OF((unsigned long,
                         const unsigned char FAR *, unsigned));
    local unsigned long crc32_big OF((unsigned long,
@@ -70,16 +52,16 @@
 local unsigned long gf2_matrix_times OF((unsigned long *mat,
                                          unsigned long vec));
 local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
-local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
+local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
 
 
 #ifdef DYNAMIC_CRC_TABLE
 
 local volatile int crc_table_empty = 1;
-local unsigned long FAR crc_table[TBLS][256];
+local z_crc_t FAR crc_table[TBLS][256];
 local void make_crc_table OF((void));
 #ifdef MAKECRCH
-   local void write_table OF((FILE *, const unsigned long FAR *));
+   local void write_table OF((FILE *, const z_crc_t FAR *));
 #endif /* MAKECRCH */
 /*
   Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
@@ -109,9 +91,9 @@
 */
 local void make_crc_table()
 {
-    unsigned long c;
+    z_crc_t c;
     int n, k;
-    unsigned long poly;                 /* polynomial exclusive-or pattern */
+    z_crc_t poly;                       /* polynomial exclusive-or pattern */
     /* terms of polynomial defining this crc (except x^32): */
     static volatile int first = 1;      /* flag to limit concurrent making */
     static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
@@ -123,13 +105,13 @@
         first = 0;
 
         /* make exclusive-or pattern from polynomial (0xedb88320UL) */
-        poly = 0UL;
-        for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
-            poly |= 1UL << (31 - p[n]);
+        poly = 0;
+        for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
+            poly |= (z_crc_t)1 << (31 - p[n]);
 
         /* generate a crc for every 8-bit value */
         for (n = 0; n < 256; n++) {
-            c = (unsigned long)n;
+            c = (z_crc_t)n;
             for (k = 0; k < 8; k++)
                 c = c & 1 ? poly ^ (c >> 1) : c >> 1;
             crc_table[0][n] = c;
@@ -140,11 +122,11 @@
            and then the byte reversal of those as well as the first table */
         for (n = 0; n < 256; n++) {
             c = crc_table[0][n];
-            crc_table[4][n] = REV(c);
+            crc_table[4][n] = ZSWAP32(c);
             for (k = 1; k < 4; k++) {
                 c = crc_table[0][c & 0xff] ^ (c >> 8);
                 crc_table[k][n] = c;
-                crc_table[k + 4][n] = REV(c);
+                crc_table[k + 4][n] = ZSWAP32(c);
             }
         }
 #endif /* BYFOUR */
@@ -166,7 +148,7 @@
         if (out == NULL) return;
         fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
         fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
-        fprintf(out, "local const unsigned long FAR ");
+        fprintf(out, "local const z_crc_t FAR ");
         fprintf(out, "crc_table[TBLS][256] =\n{\n  {\n");
         write_table(out, crc_table[0]);
 #  ifdef BYFOUR
@@ -186,12 +168,13 @@
 #ifdef MAKECRCH
 local void write_table(out, table)
     FILE *out;
-    const unsigned long FAR *table;
+    const z_crc_t FAR *table;
 {
     int n;
 
     for (n = 0; n < 256; n++)
-        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ", table[n],
+        fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : "    ",
+                (unsigned long)(table[n]),
                 n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
 }
 #endif /* MAKECRCH */
@@ -206,13 +189,13 @@
 /* =========================================================================
  * This function can be used by asm versions of crc32()
  */
-const unsigned long FAR * ZEXPORT get_crc_table()
+const z_crc_t FAR * ZEXPORT get_crc_table()
 {
 #ifdef DYNAMIC_CRC_TABLE
     if (crc_table_empty)
         make_crc_table();
 #endif /* DYNAMIC_CRC_TABLE */
-    return (const unsigned long FAR *)crc_table;
+    return (const z_crc_t FAR *)crc_table;
 }
 
 /* ========================================================================= */
@@ -234,7 +217,7 @@
 
 #ifdef BYFOUR
     if (sizeof(void *) == sizeof(ptrdiff_t)) {
-        u4 endian;
+        z_crc_t endian;
 
         endian = 1;
         if (*((unsigned char *)(&endian)))
@@ -268,17 +251,17 @@
     const unsigned char FAR *buf;
     unsigned len;
 {
-    register u4 c;
-    register const u4 FAR *buf4;
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
 
-    c = (u4)crc;
+    c = (z_crc_t)crc;
     c = ~c;
     while (len && ((ptrdiff_t)buf & 3)) {
         c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
         len--;
     }
 
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
     while (len >= 32) {
         DOLIT32;
         len -= 32;
@@ -308,17 +291,17 @@
     const unsigned char FAR *buf;
     unsigned len;
 {
-    register u4 c;
-    register const u4 FAR *buf4;
+    register z_crc_t c;
+    register const z_crc_t FAR *buf4;
 
-    c = REV((u4)crc);
+    c = ZSWAP32((z_crc_t)crc);
     c = ~c;
     while (len && ((ptrdiff_t)buf & 3)) {
         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
         len--;
     }
 
-    buf4 = (const u4 FAR *)(const void FAR *)buf;
+    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
     buf4--;
     while (len >= 32) {
         DOBIG32;
@@ -335,7 +318,7 @@
         c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
     } while (--len);
     c = ~c;
-    return (unsigned long)(REV(c));
+    return (unsigned long)(ZSWAP32(c));
 }
 
 #endif /* BYFOUR */
diff --git a/crc32.h b/crc32.h
index 8053b61..9e0c778 100644
--- a/crc32.h
+++ b/crc32.h
@@ -2,7 +2,7 @@
  * Generated automatically by crc32.c
  */
 
-local const unsigned long FAR crc_table[TBLS][256] =
+local const z_crc_t FAR crc_table[TBLS][256] =
 {
   {
     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
diff --git a/deflate.c b/deflate.c
index 55ec215..59645eb 100644
--- a/deflate.c
+++ b/deflate.c
@@ -1,5 +1,5 @@
 /* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -37,7 +37,7 @@
  *  REFERENCES
  *
  *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
- *      Available in http://www.ietf.org/rfc/rfc1951.txt
+ *      Available in http://tools.ietf.org/html/rfc1951
  *
  *      A description of the Rabin and Karp algorithm is given in the book
  *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
@@ -48,14 +48,12 @@
  */
 
 /* @(#) $Id$ */
-
 #include <assert.h>
-
 #include "deflate.h"
 #include "x86.h"
 
 const char deflate_copyright[] =
-   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
+   " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -176,6 +174,9 @@
 struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
 #endif
 
+/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */
+#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0))
+
 /* ===========================================================================
  * Update a hash value with the given input byte
  * IN  assertion: all calls to to UPDATE_HASH are made with consecutive
@@ -269,10 +270,19 @@
 
     strm->msg = Z_NULL;
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
 
 #ifdef FASTEST
     if (level != 0) level = 1;
@@ -335,7 +345,7 @@
     if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
         s->pending_buf == Z_NULL) {
         s->status = FINISH_STATE;
-        strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+        strm->msg = ERR_MSG(Z_MEM_ERROR);
         deflateEnd (strm);
         return Z_MEM_ERROR;
     }
@@ -356,43 +366,66 @@
     uInt  dictLength;
 {
     deflate_state *s;
-    uInt length = dictLength;
-    uInt n;
-    IPos hash_head = 0;
+    uInt str, n;
+    int wrap;
+    unsigned avail;
+    z_const unsigned char *next;
 
-    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
-        strm->state->wrap == 2 ||
-        (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
+        return Z_STREAM_ERROR;
+    s = strm->state;
+    wrap = s->wrap;
+    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
         return Z_STREAM_ERROR;
 
-    s = strm->state;
-    if (s->wrap)
+    /* when using zlib wrappers, compute Adler-32 for provided dictionary */
+    if (wrap == 1)
         strm->adler = adler32(strm->adler, dictionary, dictLength);
+    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
 
-    if (length < MIN_MATCH) return Z_OK;
-    if (length > s->w_size) {
-        length = s->w_size;
-        dictionary += dictLength - length; /* use the tail of the dictionary */
+    /* if dictionary would fill window, just replace the history */
+    if (dictLength >= s->w_size) {
+        if (wrap == 0) {            /* already empty otherwise */
+            CLEAR_HASH(s);
+            s->strstart = 0;
+            s->block_start = 0L;
+            s->insert = 0;
+        }
+        dictionary += dictLength - s->w_size;  /* use the tail */
+        dictLength = s->w_size;
     }
-    zmemcpy(s->window, dictionary, length);
-    s->strstart = length;
-    s->block_start = (long)length;
 
-    /* Insert all strings in the hash table (except for the last two bytes).
-     * s->lookahead stays null, so s->ins_h will be recomputed at the next
-     * call of fill_window.
-     */
-    s->ins_h = s->window[0];
-    UPDATE_HASH(s, s->ins_h, s->window[1]);
-    for (n = 0; n <= length - MIN_MATCH; n++) {
-        insert_string(s, n);
+    /* insert dictionary into window and hash */
+    avail = strm->avail_in;
+    next = strm->next_in;
+    strm->avail_in = dictLength;
+    strm->next_in = (z_const Bytef *)dictionary;
+    fill_window(s);
+    while (s->lookahead >= MIN_MATCH) {
+        str = s->strstart;
+        n = s->lookahead - (MIN_MATCH-1);
+        do {
+            insert_string(s, str);
+            str++;
+        } while (--n);
+        s->strstart = str;
+        s->lookahead = MIN_MATCH-1;
+        fill_window(s);
     }
-    if (hash_head) hash_head = 0;  /* to make compiler happy */
+    s->strstart += s->lookahead;
+    s->block_start = (long)s->strstart;
+    s->insert = s->lookahead;
+    s->lookahead = 0;
+    s->match_length = s->prev_length = MIN_MATCH-1;
+    s->match_available = 0;
+    strm->next_in = next;
+    strm->avail_in = avail;
+    s->wrap = wrap;
     return Z_OK;
 }
 
 /* ========================================================================= */
-int ZEXPORT deflateReset (strm)
+int ZEXPORT deflateResetKeep (strm)
     z_streamp strm;
 {
     deflate_state *s;
@@ -424,12 +457,23 @@
     s->last_flush = Z_NO_FLUSH;
 
     _tr_init(s);
-    lm_init(s);
 
     return Z_OK;
 }
 
 /* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+    z_streamp strm;
+{
+    int ret;
+
+    ret = deflateResetKeep(strm);
+    if (ret == Z_OK)
+        lm_init(strm->state);
+    return ret;
+}
+
+/* ========================================================================= */
 int ZEXPORT deflateSetHeader (strm, head)
     z_streamp strm;
     gz_headerp head;
@@ -441,14 +485,42 @@
 }
 
 /* ========================================================================= */
+int ZEXPORT deflatePending (strm, pending, bits)
+    unsigned *pending;
+    int *bits;
+    z_streamp strm;
+{
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    if (pending != Z_NULL)
+        *pending = strm->state->pending;
+    if (bits != Z_NULL)
+        *bits = strm->state->bi_valid;
+    return Z_OK;
+}
+
+/* ========================================================================= */
 int ZEXPORT deflatePrime (strm, bits, value)
     z_streamp strm;
     int bits;
     int value;
 {
+    deflate_state *s;
+    int put;
+
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
-    strm->state->bi_valid = bits;
-    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+    s = strm->state;
+    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+        return Z_BUF_ERROR;
+    do {
+        put = Buf_size - s->bi_valid;
+        if (put > bits)
+            put = bits;
+        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
+        s->bi_valid += put;
+        _tr_flush_bits(s);
+        value >>= put;
+        bits -= put;
+    } while (bits);
     return Z_OK;
 }
 
@@ -479,6 +551,8 @@
         strm->total_in != 0) {
         /* Flush the last buffer: */
         err = deflate(strm, Z_BLOCK);
+        if (err == Z_BUF_ERROR && s->pending == 0)
+            err = Z_OK;
     }
     if (s->level != level) {
         s->level = level;
@@ -606,19 +680,22 @@
 local void flush_pending(strm)
     z_streamp strm;
 {
-    unsigned len = strm->state->pending;
+    unsigned len;
+    deflate_state *s = strm->state;
 
+    _tr_flush_bits(s);
+    len = s->pending;
     if (len > strm->avail_out) len = strm->avail_out;
     if (len == 0) return;
 
-    zmemcpy(strm->next_out, strm->state->pending_out, len);
+    zmemcpy(strm->next_out, s->pending_out, len);
     strm->next_out  += len;
-    strm->state->pending_out  += len;
+    s->pending_out  += len;
     strm->total_out += len;
     strm->avail_out  -= len;
-    strm->state->pending -= len;
-    if (strm->state->pending == 0) {
-        strm->state->pending_out = strm->state->pending_buf;
+    s->pending -= len;
+    if (s->pending == 0) {
+        s->pending_out = s->pending_buf;
     }
 }
 
@@ -845,7 +922,7 @@
      * flushes. For repeated and useless calls with Z_FINISH, we keep
      * returning Z_STREAM_END instead of Z_BUF_ERROR.
      */
-    } else if (strm->avail_in == 0 && flush <= old_flush &&
+    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&
                flush != Z_FINISH) {
         ERR_RETURN(strm, Z_BUF_ERROR);
     }
@@ -911,6 +988,7 @@
                     if (s->lookahead == 0) {
                         s->strstart = 0;
                         s->block_start = 0L;
+                        s->insert = 0;
                     }
                 }
             }
@@ -1008,12 +1086,12 @@
 
     ss = source->state;
 
-    zmemcpy(dest, source, sizeof(z_stream));
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
 
     ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
     if (ds == Z_NULL) return Z_MEM_ERROR;
     dest->state = (struct internal_state FAR *) ds;
-    zmemcpy(ds, ss, sizeof(deflate_state));
+    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
     ds->strm = dest;
 
     ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@@ -1029,8 +1107,8 @@
     }
     /* following zmemcpy do not work for 16-bit MSDOS */
     zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
-    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
-    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos));
+    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));
     zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
 
     ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
@@ -1065,10 +1143,9 @@
     strm->avail_in  -= len;
 
 #ifdef GZIP
-    if (strm->state->wrap == 2) {
+    if (strm->state->wrap == 2)
         copy_with_crc(strm, buf, len);
-    }
-    else
+    else 
 #endif
     {
         zmemcpy(buf, strm->next_in, len);
@@ -1101,6 +1178,7 @@
     s->strstart = 0;
     s->block_start = 0L;
     s->lookahead = 0;
+    s->insert = 0;
     s->match_length = s->prev_length = MIN_MATCH-1;
     s->match_available = 0;
     s->ins_h = 0;
@@ -1372,7 +1450,7 @@
         }
         /* Check that we aren't matching a prefix of another cookie by ensuring
          * that the final byte is either a semicolon (which cannot appear in a
-         * cookie value), or the match is followed by non-cookie data. */
+         * cookie value), or non-cookie data. */
         if (s->window[cookie_location+len-1] != ';' &&
             class_at(s, cookie_location+len) != 0) {
           return 0;
@@ -1506,6 +1584,8 @@
     unsigned more;    /* Amount of free space at the end of the window. */
     uInt wsize = s->w_size;
 
+    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
+
     do {
         more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
 
@@ -1556,7 +1636,6 @@
                  */
             } while (--n);
 #endif
-
             for (n = 0; n < Z_COOKIE_HASH_SIZE; n++) {
                 if (s->cookie_locations[n] > wsize) {
                     s->cookie_locations[n] -= wsize;
@@ -1573,7 +1652,7 @@
 
             more += wsize;
         }
-        if (s->strm->avail_in == 0) return;
+        if (s->strm->avail_in == 0) break;
 
         /* If there was no sliding:
          *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
@@ -1595,12 +1674,24 @@
         s->lookahead += n;
 
         /* Initialize the hash value now that we have some input: */
-        if (s->lookahead >= MIN_MATCH) {
-            s->ins_h = s->window[s->strstart];
-            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+        if (s->lookahead + s->insert >= MIN_MATCH) {
+            uInt str = s->strstart - s->insert;
+            s->ins_h = s->window[str];
+            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);
 #if MIN_MATCH != 3
             Call UPDATE_HASH() MIN_MATCH-3 more times
 #endif
+            while (s->insert) {
+                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+#ifndef FASTEST
+                s->prev[str & s->w_mask] = s->head[s->ins_h];
+#endif
+                s->head[s->ins_h] = (Pos)str;
+                str++;
+                s->insert--;
+                if (s->lookahead + s->insert < MIN_MATCH)
+                    break;
+            }
         }
         /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
          * but this is not important since only literal bytes will be emitted.
@@ -1641,6 +1732,9 @@
             s->high_water += init;
         }
     }
+
+    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
+           "not enough room for search");
 }
 
 /* ===========================================================================
@@ -1721,8 +1815,14 @@
             FLUSH_BLOCK(s, 0);
         }
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if ((long)s->strstart > s->block_start)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 /* ===========================================================================
@@ -1824,8 +1924,14 @@
         }
         if (bflush) FLUSH_BLOCK(s, 0);
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 #ifndef FASTEST
@@ -1980,8 +2086,14 @@
         _tr_tally_lit(s, s->window[s->strstart-1], bflush);
         s->match_available = 0;
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 #endif /* FASTEST */
 
@@ -2001,11 +2113,11 @@
     for (;;) {
         /* Make sure that we always have enough lookahead, except
          * at the end of the input file. We need MAX_MATCH bytes
-         * for the longest encodable run.
+         * for the longest run, plus one for the unrolled loop.
          */
-        if (s->lookahead < MAX_MATCH) {
+        if (s->lookahead <= MAX_MATCH) {
             fill_window(s);
-            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {
                 return need_more;
             }
             if (s->lookahead == 0) break; /* flush the current block */
@@ -2028,6 +2140,7 @@
                 if (s->match_length > s->lookahead)
                     s->match_length = s->lookahead;
             }
+            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");
         }
 
         /* Emit match if have run of MIN_MATCH or longer, else emit literal */
@@ -2048,8 +2161,14 @@
         }
         if (bflush) FLUSH_BLOCK(s, 0);
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 /* ===========================================================================
@@ -2081,8 +2200,14 @@
         s->strstart++;
         if (bflush) FLUSH_BLOCK(s, 0);
     }
-    FLUSH_BLOCK(s, flush == Z_FINISH);
-    return flush == Z_FINISH ? finish_done : block_done;
+    s->insert = 0;
+    if (flush == Z_FINISH) {
+        FLUSH_BLOCK(s, 1);
+        return finish_done;
+    }
+    if (s->last_lit)
+        FLUSH_BLOCK(s, 0);
+    return block_done;
 }
 
 /* Safe to inline this as GCC/clang will use inline asm and Visual Studio will
diff --git a/deflate.h b/deflate.h
index d15f2b5..c61e4ab 100644
--- a/deflate.h
+++ b/deflate.h
@@ -1,5 +1,5 @@
 /* deflate.h -- internal compression state
- * Copyright (C) 1995-2010 Jean-loup Gailly
+ * Copyright (C) 1995-2012 Jean-loup Gailly
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -48,6 +48,9 @@
 #define MAX_BITS 15
 /* All codes must not exceed MAX_BITS bits */
 
+#define Buf_size 16
+/* size of bit buffer in bi_buf */
+
 #define INIT_STATE    42
 #define EXTRA_STATE   69
 #define NAME_STATE    73
@@ -104,11 +107,9 @@
     int   wrap;          /* bit 0 true for zlib, bit 1 true for gzip */
     gz_headerp  gzhead;  /* gzip header information to write */
     uInt   gzindex;      /* where in extra, name, or comment */
-    Byte  method;        /* STORED (for zip only) or DEFLATED */
+    Byte  method;        /* can only be DEFLATED */
     int   last_flush;    /* value of flush param for previous deflate call */
-
     unsigned zalign(16) crc0[4 * 5];
-
                 /* used by deflate.c: */
 
     uInt  w_size;        /* LZ77 window size (32K by default) */
@@ -195,7 +196,7 @@
     int nice_match; /* Stop searching when current match exceeds this */
 
                 /* used by trees.c: */
-    /* Didn't use ct_data typedef below to supress compiler warning */
+    /* Didn't use ct_data typedef below to suppress compiler warning */
     struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
     struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
     struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
@@ -251,7 +252,7 @@
     ulg opt_len;        /* bit length of current block with optimal trees */
     ulg static_len;     /* bit length of current block with static trees */
     uInt matches;       /* number of string matches in current block */
-    int last_eob_len;   /* bit length of EOB code for last block */
+    uInt insert;        /* bytes at end of window left to insert */
 
 #ifdef DEBUG
     ulg compressed_len; /* total bit length of compressed file mod 2^32 */
@@ -301,6 +302,7 @@
 int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
 void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
                         ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
 void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
 void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
                         ulg stored_len, int last));
diff --git a/google.patch b/google.patch
index 3818b11..362b44d 100644
--- a/google.patch
+++ b/google.patch
@@ -1,21 +1,128 @@
-diff -ru zlib-1.2.5/gzlib.c zlib/gzlib.c
---- zlib-1.2.5/gzlib.c
-+++ zlib/gzlib.c
-@@ -5,7 +5,9 @@
+diff --git a/third_party/zlib/contrib/minizip/ioapi.h b/third_party/zlib/contrib/minizip/ioapi.h
+index 8dcbdb0..c1b7a54 100644
+--- a/third_party/zlib/contrib/minizip/ioapi.h
++++ b/third_party/zlib/contrib/minizip/ioapi.h
+@@ -43,7 +43,7 @@
  
- #include "gzguts.h"
+ #include <stdio.h>
+ #include <stdlib.h>
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
  
--#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
-+#if defined(_WIN32)
-+#  define LSEEK (z_off64_t)_lseeki64
-+#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
- #  define LSEEK lseek64
+ #if defined(USE_FILE32API)
+ #define fopen64 fopen
+diff --git a/third_party/zlib/contrib/minizip/mztools.c b/third_party/zlib/contrib/minizip/mztools.c
+index 96891c2..8bf9cca 100644
+--- a/third_party/zlib/contrib/minizip/mztools.c
++++ b/third_party/zlib/contrib/minizip/mztools.c
+@@ -8,7 +8,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #include "unzip.h"
+ 
+ #define READ_8(adr)  ((unsigned char)*(adr))
+diff --git a/third_party/zlib/contrib/minizip/mztools.h b/third_party/zlib/contrib/minizip/mztools.h
+index a49a426..f295ffe 100644
+--- a/third_party/zlib/contrib/minizip/mztools.h
++++ b/third_party/zlib/contrib/minizip/mztools.h
+@@ -12,7 +12,7 @@ extern "C" {
+ #endif
+ 
+ #ifndef _ZLIB_H
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #endif
+ 
+ #include "unzip.h"
+diff --git a/third_party/zlib/contrib/minizip/unzip.c b/third_party/zlib/contrib/minizip/unzip.c
+index 9093504..2d5f0b1 100644
+--- a/third_party/zlib/contrib/minizip/unzip.c
++++ b/third_party/zlib/contrib/minizip/unzip.c
+@@ -72,7 +72,7 @@
+         #define NOUNCRYPT
+ #endif
+ 
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #include "unzip.h"
+ 
+ #ifdef STDC
+@@ -1705,11 +1705,6 @@ extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
+ 
+     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+ 
+-    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+-        (!(pfile_in_zip_read_info->raw)))
+-        pfile_in_zip_read_info->stream.avail_out =
+-            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+-
+     if ((len>pfile_in_zip_read_info->rest_read_compressed+
+            pfile_in_zip_read_info->stream.avail_in) &&
+          (pfile_in_zip_read_info->raw))
+diff --git a/third_party/zlib/contrib/minizip/unzip.h b/third_party/zlib/contrib/minizip/unzip.h
+index 2104e39..3c01435 100644
+--- a/third_party/zlib/contrib/minizip/unzip.h
++++ b/third_party/zlib/contrib/minizip/unzip.h
+@@ -48,7 +48,7 @@ extern "C" {
+ #endif
+ 
+ #ifndef _ZLIB_H
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #endif
+ 
+ #ifndef  _ZLIBIOAPI_H
+diff --git a/third_party/zlib/contrib/minizip/zip.c b/third_party/zlib/contrib/minizip/zip.c
+index ea54853..aaf6961 100644
+--- a/third_party/zlib/contrib/minizip/zip.c
++++ b/third_party/zlib/contrib/minizip/zip.c
+@@ -26,7 +26,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #include "zip.h"
+ 
+ #ifdef STDC
+diff --git a/third_party/zlib/contrib/minizip/zip.h b/third_party/zlib/contrib/minizip/zip.h
+index 8aaebb6..8c06c0a 100644
+--- a/third_party/zlib/contrib/minizip/zip.h
++++ b/third_party/zlib/contrib/minizip/zip.h
+@@ -47,7 +47,7 @@ extern "C" {
+ //#define HAVE_BZIP2
+ 
+ #ifndef _ZLIB_H
+-#include "zlib.h"
++#include "third_party/zlib/zlib.h"
+ #endif
+ 
+ #ifndef _ZLIBIOAPI_H
+diff --git a/third_party/zlib/gzread.c b/third_party/zlib/gzread.c
+index bf4538e..4e11246 100644
+--- a/third_party/zlib/gzread.c
++++ b/third_party/zlib/gzread.c
+@@ -383,7 +383,11 @@ int ZEXPORT gzread(file, buf, len)
+ #  undef z_gzgetc
  #else
- #  define LSEEK lseek
-diff -ru zlib-1.2.5/mozzconf.h zlib/mozzconf.h
---- zlib-1.2.5/mozzconf.h	2011-12-15 18:10:49.000000000 +0800
-+++ zlib/mozzconf.h	2011-12-16 16:08:00.000000000 +0800
-@@ -0,0 +1,168 @@
+ #  undef gzgetc
++#  ifdef MOZZCONF_H
++#    define gzgetc MOZ_Z_gzgetc
++#  endif
+ #endif
++
+ int ZEXPORT gzgetc(file)
+     gzFile file;
+ {
+diff --git a/third_party/zlib/mozzconf.h b/third_party/zlib/mozzconf.h
+new file mode 100644
+index 0000000..80994c9
+--- /dev/null
++++ b/third_party/zlib/mozzconf.h
+@@ -0,0 +1,177 @@
 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 +/* ***** BEGIN LICENSE BLOCK *****
 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
@@ -92,10 +199,12 @@
 +#define gzread MOZ_Z_gzread
 +#define gzwrite MOZ_Z_gzwrite
 +#define gzprintf MOZ_Z_gzprintf
++#define gzvprintf MOZ_Z_gzvprintf
 +#define gzputs MOZ_Z_gzputs
 +#define gzgets MOZ_Z_gzgets
 +#define gzputc MOZ_Z_gzputc
 +#define gzgetc MOZ_Z_gzgetc
++#define gzgetc_ MOZ_Z_gzgetc_
 +#define gzungetc MOZ_Z_gzungetc
 +#define gzflush MOZ_Z_gzflush
 +#define gzseek MOZ_Z_gzseek
@@ -177,6 +286,13 @@
 +#define gz_header_s MOZ_Z_gz_header_s
 +#define internal_state MOZ_Z_internal_state
 +
++/* New as of zlib 1.2.8 */
++#define deflateResetKeep MOZ_Z_deflateResetKeep
++#define deflatePending MOZ_Z_deflatePending
++#define inflateGetDictionary MOZ_Z_inflateGetDictionary
++#define inflateResetKeep MOZ_Z_inflateResetKeep
++#define gzopen_w MOZ_Z_gzopen_w
++
 +/* Mangle Byte types except on Mac. */
 +#if !defined(__MACTYPES__)
 +#define Byte MOZ_Z_Byte
@@ -184,9 +300,10 @@
 +#endif
 +
 +#endif
-diff -ru zlib-1.2.5/zconf.h zlib/zconf.h
---- zlib-1.2.5/zconf.h	2010-04-19 01:58:06.000000000 +0800
-+++ zlib/zconf.h	2011-12-14 08:06:37.000000000 +0800
+diff --git a/third_party/zlib/zconf.h b/third_party/zlib/zconf.h
+index 9987a77..1b1d88b 100644
+--- a/third_party/zlib/zconf.h
++++ b/third_party/zlib/zconf.h
 @@ -8,6 +8,9 @@
  #ifndef ZCONF_H
  #define ZCONF_H
@@ -197,8 +314,8 @@
  /*
   * If you *really* need a unique prefix for all types and library functions,
   * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
-@@ -359,7 +359,7 @@ typedef uLong FAR uLongf;
-    typedef Byte       *voidp;
+@@ -408,7 +411,7 @@ typedef uLong FAR uLongf;
+    typedef unsigned long z_crc_t;
  #endif
  
 -#ifdef HAVE_UNISTD_H    /* may be set to #if 1 by ./configure */
@@ -206,35 +323,95 @@
  #  define Z_HAVE_UNISTD_H
  #endif
  
---- zlib-1.2.5/zlib.h	2010-04-20 12:12:48.000000000 +0800
-+++ zlib/zlib.h	2013-04-06 16:08:48.000000000 +0800
-@@ -1572,11 +1572,29 @@
+diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h
+index 3e0c767..36c73af 100644
+--- a/third_party/zlib/zlib.h
++++ b/third_party/zlib/zlib.h
+@@ -1678,8 +1678,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+ #  define z_gzgetc(g) \
+           ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+ #else
+-#  define gzgetc(g) \
++#  ifdef MOZZCONF_H
++#    undef gzgetc
++#    define gzgetc(g) \
++          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : MOZ_Z_gzgetc(g))
++#  else
++#    define gzgetc(g) \
+           ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
++#  endif
  #endif
  
- #if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
-+#  ifdef gzopen
-+#    undef gzopen
+ /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+@@ -1706,11 +1712,29 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+ #    define z_adler32_combine z_adler32_combine64
+ #    define z_crc32_combine z_crc32_combine64
+ #  else
++#    ifdef gzopen
++#      undef gzopen
++#    endif
+ #    define gzopen gzopen64
++#    ifdef gzseek
++#      undef gzseek
++#    endif
+ #    define gzseek gzseek64
++#    ifdef gztell
++#      undef gztell
++#    endif
+ #    define gztell gztell64
++#    ifdef gzoffset
++#      undef gzoffset
++#    endif
+ #    define gzoffset gzoffset64
++#    ifdef adler32_combine
++#      undef adler32_combine
++#    endif
+ #    define adler32_combine adler32_combine64
++#    ifdef crc32_combine
++#      undef crc32_combine
++#    endif
+ #    define crc32_combine crc32_combine64
+ #  endif
+ #  ifndef Z_LARGE64
+diff --git a/third_party/zlib/zutil.h b/third_party/zlib/zutil.h
+index 24ab06b..fe9e53c 100644
+--- a/third_party/zlib/zutil.h
++++ b/third_party/zlib/zutil.h
+@@ -28,6 +28,21 @@
+ #  include <string.h>
+ #  include <stdlib.h>
+ #endif
++#ifdef NO_ERRNO_H
++#   ifdef _WIN32_WCE
++      /* The Microsoft C Run-Time Library for Windows CE doesn't have
++       * errno.  We define it as a global variable to simplify porting.
++       * Its value is always 0 and should not be used.  We rename it to
++       * avoid conflict with other libraries that use the same workaround.
++       */
++#     define errno z_errno
++#   endif
++    extern int errno;
++#else
++#  ifndef _WIN32_WCE
++#    include <errno.h>
 +#  endif
- #  define gzopen gzopen64
-+#  ifdef gzseek
-+#    undef gzseek
-+#  endif
- #  define gzseek gzseek64
-+#  ifdef gztell
-+#    undef gztell
-+#  endif
- #  define gztell gztell64
-+#  ifdef gzoffset
-+#    undef gzoffset
-+#  endif
- #  define gzoffset gzoffset64
-+#  ifdef adler32_combine
-+#    undef adler32_combine
-+#  endif
- #  define adler32_combine adler32_combine64
-+#  ifdef crc32_combine
-+#    undef crc32_combine
-+#  endif
- #  define crc32_combine crc32_combine64
- #  ifdef _LARGEFILE64_SOURCE
-      ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
++#endif
+ 
+ #ifdef Z_SOLO
+    typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
+@@ -135,6 +150,12 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+ #  define OS_CODE  0x0a
+ #endif
+ 
++#ifdef _MSC_VER
++#define zalign(x) __declspec(align(x))
++#else
++#define zalign(x) __attribute__((aligned((x))))
++#endif
++
+ #ifdef WIN32
+ #  ifndef __CYGWIN__  /* Cygwin is Unix, not Win32 */
+ #    define OS_CODE  0x0b
+-- 
+2.7.4
+
diff --git a/gzguts.h b/gzguts.h
index 0f8fb79..d87659d 100644
--- a/gzguts.h
+++ b/gzguts.h
@@ -1,5 +1,5 @@
 /* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -12,7 +12,7 @@
 #  endif
 #endif
 
-#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#ifdef HAVE_HIDDEN
 #  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
 #else
 #  define ZLIB_INTERNAL
@@ -27,13 +27,80 @@
 #endif
 #include <fcntl.h>
 
+#ifdef _WIN32
+#  include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+#  include <io.h>
+#endif
+
+#ifdef WINAPI_FAMILY
+#  define open _open
+#  define read _read
+#  define write _write
+#  define close _close
+#endif
+
 #ifdef NO_DEFLATE       /* for compatibility with old definition */
 #  define NO_GZCOMPRESS
 #endif
 
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#if defined(__CYGWIN__)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+#  ifndef HAVE_VSNPRINTF
+#    define HAVE_VSNPRINTF
+#  endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+#  ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+   but for now we just assume it doesn't. */
+#    define NO_vsnprintf
+#  endif
+#  ifdef __TURBOC__
+#    define NO_vsnprintf
+#  endif
+#  ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
+#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+#         define vsnprintf _vsnprintf
+#      endif
+#    endif
+#  endif
+#  ifdef __SASC
+#    define NO_vsnprintf
+#  endif
+#  ifdef VMS
+#    define NO_vsnprintf
+#  endif
+#  ifdef __OS400__
+#    define NO_vsnprintf
+#  endif
+#  ifdef __MVS__
+#    define NO_vsnprintf
+#  endif
+#endif
+
+/* unlike snprintf (which is required in C99, yet still not supported by
+   Microsoft more than a decade later!), _snprintf does not guarantee null
+   termination of the result -- however this is only used in gzlib.c where
+   the result is assured to fit in the space provided */
 #ifdef _MSC_VER
-#  include <io.h>
-#  define vsnprintf _vsnprintf
+#  define snprintf _snprintf
 #endif
 
 #ifndef local
@@ -52,7 +119,7 @@
 #  include <windows.h>
 #  define zstrerror() gz_strwinerror((DWORD)GetLastError())
 #else
-#  ifdef STDC
+#  ifndef NO_STRERROR
 #    include <errno.h>
 #    define zstrerror() strerror(errno)
 #  else
@@ -68,7 +135,15 @@
     ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
 #endif
 
-/* default i/o buffer size -- double this for output when reading */
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+   twice this must be able to fit in an unsigned type) */
 #define GZBUFSIZE 8192
 
 /* gzip modes, also provide a little integrity check on the passed structure */
@@ -84,23 +159,25 @@
 
 /* internal gzip file state data structure */
 typedef struct {
+        /* exposed contents for gzgetc() macro */
+    struct gzFile_s x;      /* "x" for exposed */
+                            /* x.have: number of bytes available at x.next */
+                            /* x.next: next output data to deliver or write */
+                            /* x.pos: current position in uncompressed data */
         /* used for both reading and writing */
     int mode;               /* see gzip modes above */
     int fd;                 /* file descriptor */
     char *path;             /* path or fd for error messages */
-    z_off64_t pos;          /* current position in uncompressed data */
     unsigned size;          /* buffer size, zero if not allocated yet */
     unsigned want;          /* requested buffer size, default is GZBUFSIZE */
     unsigned char *in;      /* input buffer */
     unsigned char *out;     /* output buffer (double-sized when reading) */
-    unsigned char *next;    /* next output data to deliver or write */
+    int direct;             /* 0 if processing gzip, 1 if transparent */
         /* just for reading */
-    unsigned have;          /* amount of output data unused at next */
-    int eof;                /* true if end of input file reached */
-    z_off64_t start;        /* where the gzip data started, for rewinding */
-    z_off64_t raw;          /* where the raw data started, for seeking */
     int how;                /* 0: get header, 1: copy, 2: decompress */
-    int direct;             /* true if last read direct, false if gzip */
+    z_off64_t start;        /* where the gzip data started, for rewinding */
+    int eof;                /* true if end of input file reached */
+    int past;               /* true if read requested past end */
         /* just for writing */
     int level;              /* compression level */
     int strategy;           /* compression strategy */
diff --git a/gzlib.c b/gzlib.c
index 54e8344..fae202e 100644
--- a/gzlib.c
+++ b/gzlib.c
@@ -1,21 +1,23 @@
 /* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004, 2010 Mark Adler
+ * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #include "gzguts.h"
 
 #if defined(_WIN32) && !defined(__BORLANDC__)
-#  define LSEEK (z_off64_t)_lseeki64
-#elif defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#  define LSEEK _lseeki64
+#else
+#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
 #  define LSEEK lseek64
 #else
 #  define LSEEK lseek
 #endif
+#endif
 
 /* Local functions */
 local void gz_reset OF((gz_statep));
-local gzFile gz_open OF((const char *, int, const char *));
+local gzFile gz_open OF((const void *, int, const char *));
 
 #if defined UNDER_CE
 
@@ -73,28 +75,40 @@
 local void gz_reset(state)
     gz_statep state;
 {
+    state->x.have = 0;              /* no output data available */
     if (state->mode == GZ_READ) {   /* for reading ... */
-        state->have = 0;            /* no output data available */
         state->eof = 0;             /* not at end of file */
+        state->past = 0;            /* have not read past end yet */
         state->how = LOOK;          /* look for gzip header */
-        state->direct = 1;          /* default for empty file */
     }
     state->seek = 0;                /* no seek request pending */
     gz_error(state, Z_OK, NULL);    /* clear error */
-    state->pos = 0;                 /* no uncompressed data yet */
+    state->x.pos = 0;               /* no uncompressed data yet */
     state->strm.avail_in = 0;       /* no input data yet */
 }
 
 /* Open a gzip file either by name or file descriptor. */
 local gzFile gz_open(path, fd, mode)
-    const char *path;
+    const void *path;
     int fd;
     const char *mode;
 {
     gz_statep state;
+    size_t len;
+    int oflag;
+#ifdef O_CLOEXEC
+    int cloexec = 0;
+#endif
+#ifdef O_EXCL
+    int exclusive = 0;
+#endif
+
+    /* check input */
+    if (path == NULL)
+        return NULL;
 
     /* allocate gzFile structure to return */
-    state = malloc(sizeof(gz_state));
+    state = (gz_statep)malloc(sizeof(gz_state));
     if (state == NULL)
         return NULL;
     state->size = 0;            /* no buffers allocated yet */
@@ -105,6 +119,7 @@
     state->mode = GZ_NONE;
     state->level = Z_DEFAULT_COMPRESSION;
     state->strategy = Z_DEFAULT_STRATEGY;
+    state->direct = 0;
     while (*mode) {
         if (*mode >= '0' && *mode <= '9')
             state->level = *mode - '0';
@@ -126,6 +141,16 @@
                 return NULL;
             case 'b':       /* ignore -- will request binary anyway */
                 break;
+#ifdef O_CLOEXEC
+            case 'e':
+                cloexec = 1;
+                break;
+#endif
+#ifdef O_EXCL
+            case 'x':
+                exclusive = 1;
+                break;
+#endif
             case 'f':
                 state->strategy = Z_FILTERED;
                 break;
@@ -137,6 +162,10 @@
                 break;
             case 'F':
                 state->strategy = Z_FIXED;
+                break;
+            case 'T':
+                state->direct = 1;
+                break;
             default:        /* could consider as an error, but just ignore */
                 ;
             }
@@ -149,30 +178,71 @@
         return NULL;
     }
 
+    /* can't force transparent read */
+    if (state->mode == GZ_READ) {
+        if (state->direct) {
+            free(state);
+            return NULL;
+        }
+        state->direct = 1;      /* for empty file */
+    }
+
     /* save the path name for error messages */
-    state->path = malloc(strlen(path) + 1);
+#ifdef _WIN32
+    if (fd == -2) {
+        len = wcstombs(NULL, path, 0);
+        if (len == (size_t)-1)
+            len = 0;
+    }
+    else
+#endif
+        len = strlen((const char *)path);
+    state->path = (char *)malloc(len + 1);
     if (state->path == NULL) {
         free(state);
         return NULL;
     }
-    strcpy(state->path, path);
+#ifdef _WIN32
+    if (fd == -2)
+        if (len)
+            wcstombs(state->path, path, len + 1);
+        else
+            *(state->path) = 0;
+    else
+#endif
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+        snprintf(state->path, len + 1, "%s", (const char *)path);
+#else
+        strcpy(state->path, path);
+#endif
 
-    /* open the file with the appropriate mode (or just use fd) */
-    state->fd = fd != -1 ? fd :
-        open(path,
+    /* compute the flags for open() */
+    oflag =
 #ifdef O_LARGEFILE
-            O_LARGEFILE |
+        O_LARGEFILE |
 #endif
 #ifdef O_BINARY
-            O_BINARY |
+        O_BINARY |
 #endif
-            (state->mode == GZ_READ ?
-                O_RDONLY :
-                (O_WRONLY | O_CREAT | (
-                    state->mode == GZ_WRITE ?
-                        O_TRUNC :
-                        O_APPEND))),
-            0666);
+#ifdef O_CLOEXEC
+        (cloexec ? O_CLOEXEC : 0) |
+#endif
+        (state->mode == GZ_READ ?
+         O_RDONLY :
+         (O_WRONLY | O_CREAT |
+#ifdef O_EXCL
+          (exclusive ? O_EXCL : 0) |
+#endif
+          (state->mode == GZ_WRITE ?
+           O_TRUNC :
+           O_APPEND)));
+
+    /* open the file with the appropriate flags (or just use fd) */
+    state->fd = fd > -1 ? fd : (
+#ifdef _WIN32
+        fd == -2 ? _wopen(path, oflag, 0666) :
+#endif
+        open((const char *)path, oflag, 0666));
     if (state->fd == -1) {
         free(state->path);
         free(state);
@@ -218,15 +288,29 @@
     char *path;         /* identifier for error messages */
     gzFile gz;
 
-    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
+    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
         return NULL;
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
+#else
     sprintf(path, "<fd:%d>", fd);   /* for debugging */
+#endif
     gz = gz_open(path, fd, mode);
     free(path);
     return gz;
 }
 
 /* -- see zlib.h -- */
+#ifdef _WIN32
+gzFile ZEXPORT gzopen_w(path, mode)
+    const wchar_t *path;
+    const char *mode;
+{
+    return gz_open(path, -2, mode);
+}
+#endif
+
+/* -- see zlib.h -- */
 int ZEXPORT gzbuffer(file, size)
     gzFile file;
     unsigned size;
@@ -245,8 +329,8 @@
         return -1;
 
     /* check and set requested size */
-    if (size == 0)
-        return -1;
+    if (size < 2)
+        size = 2;               /* need two bytes to check magic header */
     state->want = size;
     return 0;
 }
@@ -263,7 +347,8 @@
     state = (gz_statep)file;
 
     /* check that we're reading and that there's no error */
-    if (state->mode != GZ_READ || state->err != Z_OK)
+    if (state->mode != GZ_READ ||
+            (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return -1;
 
     /* back up and start over */
@@ -291,7 +376,7 @@
         return -1;
 
     /* check that there's no error */
-    if (state->err != Z_OK)
+    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
         return -1;
 
     /* can only seek from start or relative to current position */
@@ -300,31 +385,32 @@
 
     /* normalize offset to a SEEK_CUR specification */
     if (whence == SEEK_SET)
-        offset -= state->pos;
+        offset -= state->x.pos;
     else if (state->seek)
         offset += state->skip;
     state->seek = 0;
 
     /* if within raw area while reading, just go there */
     if (state->mode == GZ_READ && state->how == COPY &&
-        state->pos + offset >= state->raw) {
-        ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
+            state->x.pos + offset >= 0) {
+        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
         if (ret == -1)
             return -1;
-        state->have = 0;
+        state->x.have = 0;
         state->eof = 0;
+        state->past = 0;
         state->seek = 0;
         gz_error(state, Z_OK, NULL);
         state->strm.avail_in = 0;
-        state->pos += offset;
-        return state->pos;
+        state->x.pos += offset;
+        return state->x.pos;
     }
 
     /* calculate skip amount, rewinding if needed for back seek when reading */
     if (offset < 0) {
         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
             return -1;
-        offset += state->pos;
+        offset += state->x.pos;
         if (offset < 0)                     /* before start of file! */
             return -1;
         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
@@ -333,11 +419,11 @@
 
     /* if reading, skip what's in output buffer (one less gzgetc() check) */
     if (state->mode == GZ_READ) {
-        n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
-            (unsigned)offset : state->have;
-        state->have -= n;
-        state->next += n;
-        state->pos += n;
+        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
+            (unsigned)offset : state->x.have;
+        state->x.have -= n;
+        state->x.next += n;
+        state->x.pos += n;
         offset -= n;
     }
 
@@ -346,7 +432,7 @@
         state->seek = 1;
         state->skip = offset;
     }
-    return state->pos + offset;
+    return state->x.pos + offset;
 }
 
 /* -- see zlib.h -- */
@@ -375,7 +461,7 @@
         return -1;
 
     /* return position */
-    return state->pos + (state->seek ? state->skip : 0);
+    return state->x.pos + (state->seek ? state->skip : 0);
 }
 
 /* -- see zlib.h -- */
@@ -435,8 +521,7 @@
         return 0;
 
     /* return end-of-file state */
-    return state->mode == GZ_READ ?
-        (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
+    return state->mode == GZ_READ ? state->past : 0;
 }
 
 /* -- see zlib.h -- */
@@ -456,7 +541,8 @@
     /* return error information */
     if (errnum != NULL)
         *errnum = state->err;
-    return state->msg == NULL ? "" : state->msg;
+    return state->err == Z_MEM_ERROR ? "out of memory" :
+                                       (state->msg == NULL ? "" : state->msg);
 }
 
 /* -- see zlib.h -- */
@@ -473,8 +559,10 @@
         return;
 
     /* clear error and end-of-file */
-    if (state->mode == GZ_READ)
+    if (state->mode == GZ_READ) {
         state->eof = 0;
+        state->past = 0;
+    }
     gz_error(state, Z_OK, NULL);
 }
 
@@ -496,26 +584,33 @@
         state->msg = NULL;
     }
 
+    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
+    if (err != Z_OK && err != Z_BUF_ERROR)
+        state->x.have = 0;
+
     /* set error code, and if no message, then done */
     state->err = err;
     if (msg == NULL)
         return;
 
-    /* for an out of memory error, save as static string */
-    if (err == Z_MEM_ERROR) {
-        state->msg = (char *)msg;
+    /* for an out of memory error, return literal string when requested */
+    if (err == Z_MEM_ERROR)
         return;
-    }
 
     /* construct error message with path */
-    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
+    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
+            NULL) {
         state->err = Z_MEM_ERROR;
-        state->msg = (char *)"out of memory";
         return;
     }
+#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
+    snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
+             "%s%s%s", state->path, ": ", msg);
+#else
     strcpy(state->msg, state->path);
     strcat(state->msg, ": ");
     strcat(state->msg, msg);
+#endif
     return;
 }
 
diff --git a/gzread.c b/gzread.c
index 548201a..4e11246 100644
--- a/gzread.c
+++ b/gzread.c
@@ -1,5 +1,5 @@
 /* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -8,10 +8,9 @@
 /* Local functions */
 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
 local int gz_avail OF((gz_statep));
-local int gz_next4 OF((gz_statep, unsigned long *));
-local int gz_head OF((gz_statep));
+local int gz_look OF((gz_statep));
 local int gz_decomp OF((gz_statep));
-local int gz_make OF((gz_statep));
+local int gz_fetch OF((gz_statep));
 local int gz_skip OF((gz_statep, z_off64_t));
 
 /* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
@@ -46,73 +45,54 @@
    error, 0 otherwise.  Note that the eof flag is set when the end of the input
    file is reached, even though there may be unused data in the buffer.  Once
    that data has been used, no more attempts will be made to read the file.
-   gz_avail() assumes that strm->avail_in == 0. */
+   If strm->avail_in != 0, then the current data is moved to the beginning of
+   the input buffer, and then the remainder of the buffer is loaded with the
+   available data from the input file. */
 local int gz_avail(state)
     gz_statep state;
 {
+    unsigned got;
     z_streamp strm = &(state->strm);
 
-    if (state->err != Z_OK)
+    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
         return -1;
     if (state->eof == 0) {
-        if (gz_load(state, state->in, state->size,
-                (unsigned *)&(strm->avail_in)) == -1)
+        if (strm->avail_in) {       /* copy what's there to the start */
+            unsigned char *p = state->in;
+            unsigned const char *q = strm->next_in;
+            unsigned n = strm->avail_in;
+            do {
+                *p++ = *q++;
+            } while (--n);
+        }
+        if (gz_load(state, state->in + strm->avail_in,
+                    state->size - strm->avail_in, &got) == -1)
             return -1;
+        strm->avail_in += got;
         strm->next_in = state->in;
     }
     return 0;
 }
 
-/* Get next byte from input, or -1 if end or error. */
-#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
-                (strm->avail_in == 0 ? -1 : \
-                 (strm->avail_in--, *(strm->next_in)++)))
-
-/* Get a four-byte little-endian integer and return 0 on success and the value
-   in *ret.  Otherwise -1 is returned and *ret is not modified. */
-local int gz_next4(state, ret)
-    gz_statep state;
-    unsigned long *ret;
-{
-    int ch;
-    unsigned long val;
-    z_streamp strm = &(state->strm);
-
-    val = NEXT();
-    val += (unsigned)NEXT() << 8;
-    val += (unsigned long)NEXT() << 16;
-    ch = NEXT();
-    if (ch == -1)
-        return -1;
-    val += (unsigned long)ch << 24;
-    *ret = val;
-    return 0;
-}
-
-/* Look for gzip header, set up for inflate or copy.  state->have must be zero.
+/* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
    If this is the first time in, allocate required memory.  state->how will be
    left unchanged if there is no more input data available, will be set to COPY
    if there is no gzip header and direct copying will be performed, or it will
-   be set to GZIP for decompression, and the gzip header will be skipped so
-   that the next available input data is the raw deflate stream.  If direct
-   copying, then leftover input data from the input buffer will be copied to
-   the output buffer.  In that case, all further file reads will be directly to
-   either the output buffer or a user buffer.  If decompressing, the inflate
-   state and the check value will be initialized.  gz_head() will return 0 on
-   success or -1 on failure.  Failures may include read errors or gzip header
-   errors.  */
-local int gz_head(state)
+   be set to GZIP for decompression.  If direct copying, then leftover input
+   data from the input buffer will be copied to the output buffer.  In that
+   case, all further file reads will be directly to either the output buffer or
+   a user buffer.  If decompressing, the inflate state will be initialized.
+   gz_look() will return 0 on success or -1 on failure. */
+local int gz_look(state)
     gz_statep state;
 {
     z_streamp strm = &(state->strm);
-    int flags;
-    unsigned len;
 
     /* allocate read buffers and inflate memory */
     if (state->size == 0) {
         /* allocate buffers */
-        state->in = malloc(state->want);
-        state->out = malloc(state->want << 1);
+        state->in = (unsigned char *)malloc(state->want);
+        state->out = (unsigned char *)malloc(state->want << 1);
         if (state->in == NULL || state->out == NULL) {
             if (state->out != NULL)
                 free(state->out);
@@ -129,7 +109,7 @@
         state->strm.opaque = Z_NULL;
         state->strm.avail_in = 0;
         state->strm.next_in = Z_NULL;
-        if (inflateInit2(&(state->strm), -15) != Z_OK) {    /* raw inflate */
+        if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
             free(state->out);
             free(state->in);
             state->size = 0;
@@ -138,83 +118,45 @@
         }
     }
 
-    /* get some data in the input buffer */
-    if (strm->avail_in == 0) {
+    /* get at least the magic bytes in the input buffer */
+    if (strm->avail_in < 2) {
         if (gz_avail(state) == -1)
             return -1;
         if (strm->avail_in == 0)
             return 0;
     }
 
-    /* look for the gzip magic header bytes 31 and 139 */
-    if (strm->next_in[0] == 31) {
-        strm->avail_in--;
-        strm->next_in++;
-        if (strm->avail_in == 0 && gz_avail(state) == -1)
-            return -1;
-        if (strm->avail_in && strm->next_in[0] == 139) {
-            /* we have a gzip header, woo hoo! */
-            strm->avail_in--;
-            strm->next_in++;
-
-            /* skip rest of header */
-            if (NEXT() != 8) {      /* compression method */
-                gz_error(state, Z_DATA_ERROR, "unknown compression method");
-                return -1;
-            }
-            flags = NEXT();
-            if (flags & 0xe0) {     /* reserved flag bits */
-                gz_error(state, Z_DATA_ERROR, "unknown header flags set");
-                return -1;
-            }
-            NEXT();                 /* modification time */
-            NEXT();
-            NEXT();
-            NEXT();
-            NEXT();                 /* extra flags */
-            NEXT();                 /* operating system */
-            if (flags & 4) {        /* extra field */
-                len = (unsigned)NEXT();
-                len += (unsigned)NEXT() << 8;
-                while (len--)
-                    if (NEXT() < 0)
-                        break;
-            }
-            if (flags & 8)          /* file name */
-                while (NEXT() > 0)
-                    ;
-            if (flags & 16)         /* comment */
-                while (NEXT() > 0)
-                    ;
-            if (flags & 2) {        /* header crc */
-                NEXT();
-                NEXT();
-            }
-            /* an unexpected end of file is not checked for here -- it will be
-               noticed on the first request for uncompressed data */
-
-            /* set up for decompression */
-            inflateReset(strm);
-            strm->adler = crc32(0L, Z_NULL, 0);
-            state->how = GZIP;
-            state->direct = 0;
-            return 0;
-        }
-        else {
-            /* not a gzip file -- save first byte (31) and fall to raw i/o */
-            state->out[0] = 31;
-            state->have = 1;
-        }
+    /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
+       a logical dilemma here when considering the case of a partially written
+       gzip file, to wit, if a single 31 byte is written, then we cannot tell
+       whether this is a single-byte file, or just a partially written gzip
+       file -- for here we assume that if a gzip file is being written, then
+       the header will be written in a single operation, so that reading a
+       single byte is sufficient indication that it is not a gzip file) */
+    if (strm->avail_in > 1 &&
+            strm->next_in[0] == 31 && strm->next_in[1] == 139) {
+        inflateReset(strm);
+        state->how = GZIP;
+        state->direct = 0;
+        return 0;
     }
 
-    /* doing raw i/o, save start of raw data for seeking, copy any leftover
-       input to output -- this assumes that the output buffer is larger than
-       the input buffer, which also assures space for gzungetc() */
-    state->raw = state->pos;
-    state->next = state->out;
+    /* no gzip header -- if we were decoding gzip before, then this is trailing
+       garbage.  Ignore the trailing garbage and finish. */
+    if (state->direct == 0) {
+        strm->avail_in = 0;
+        state->eof = 1;
+        state->x.have = 0;
+        return 0;
+    }
+
+    /* doing raw i/o, copy any leftover input to output -- this assumes that
+       the output buffer is larger than the input buffer, which also assures
+       space for gzungetc() */
+    state->x.next = state->out;
     if (strm->avail_in) {
-        memcpy(state->next + state->have, strm->next_in, strm->avail_in);
-        state->have += strm->avail_in;
+        memcpy(state->x.next, strm->next_in, strm->avail_in);
+        state->x.have = strm->avail_in;
         strm->avail_in = 0;
     }
     state->how = COPY;
@@ -223,19 +165,15 @@
 }
 
 /* Decompress from input to the provided next_out and avail_out in the state.
-   If the end of the compressed data is reached, then verify the gzip trailer
-   check value and length (modulo 2^32).  state->have and state->next are set
-   to point to the just decompressed data, and the crc is updated.  If the
-   trailer is verified, state->how is reset to LOOK to look for the next gzip
-   stream or raw data, once state->have is depleted.  Returns 0 on success, -1
-   on failure.  Failures may include invalid compressed data or a failed gzip
-   trailer verification. */
+   On return, state->x.have and state->x.next point to the just decompressed
+   data.  If the gzip stream completes, state->how is reset to LOOK to look for
+   the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
+   on success, -1 on failure. */
 local int gz_decomp(state)
     gz_statep state;
 {
-    int ret;
+    int ret = Z_OK;
     unsigned had;
-    unsigned long crc, len;
     z_streamp strm = &(state->strm);
 
     /* fill output buffer up to end of deflate stream */
@@ -245,15 +183,15 @@
         if (strm->avail_in == 0 && gz_avail(state) == -1)
             return -1;
         if (strm->avail_in == 0) {
-            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
-            return -1;
+            gz_error(state, Z_BUF_ERROR, "unexpected end of file");
+            break;
         }
 
         /* decompress and handle errors */
         ret = inflate(strm, Z_NO_FLUSH);
         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
             gz_error(state, Z_STREAM_ERROR,
-                      "internal error: inflate stream corrupt");
+                     "internal error: inflate stream corrupt");
             return -1;
         }
         if (ret == Z_MEM_ERROR) {
@@ -262,67 +200,55 @@
         }
         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
             gz_error(state, Z_DATA_ERROR,
-                      strm->msg == NULL ? "compressed data error" : strm->msg);
+                     strm->msg == NULL ? "compressed data error" : strm->msg);
             return -1;
         }
     } while (strm->avail_out && ret != Z_STREAM_END);
 
-    /* update available output and crc check value */
-    state->have = had - strm->avail_out;
-    state->next = strm->next_out - state->have;
-    strm->adler = crc32(strm->adler, state->next, state->have);
+    /* update available output */
+    state->x.have = had - strm->avail_out;
+    state->x.next = strm->next_out - state->x.have;
 
-    /* check gzip trailer if at end of deflate stream */
-    if (ret == Z_STREAM_END) {
-        if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
-            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
-            return -1;
-        }
-        if (crc != strm->adler) {
-            gz_error(state, Z_DATA_ERROR, "incorrect data check");
-            return -1;
-        }
-        if (len != (strm->total_out & 0xffffffffL)) {
-            gz_error(state, Z_DATA_ERROR, "incorrect length check");
-            return -1;
-        }
-        state->how = LOOK;      /* ready for next stream, once have is 0 (leave
-                                   state->direct unchanged to remember how) */
-    }
+    /* if the gzip stream completed successfully, look for another */
+    if (ret == Z_STREAM_END)
+        state->how = LOOK;
 
     /* good decompression */
     return 0;
 }
 
-/* Make data and put in the output buffer.  Assumes that state->have == 0.
+/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
    Data is either copied from the input file or decompressed from the input
    file depending on state->how.  If state->how is LOOK, then a gzip header is
-   looked for (and skipped if found) to determine wither to copy or decompress.
-   Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
-   or GZIP unless the end of the input file has been reached and all data has
-   been processed.  */
-local int gz_make(state)
+   looked for to determine whether to copy or decompress.  Returns -1 on error,
+   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
+   end of the input file has been reached and all data has been processed.  */
+local int gz_fetch(state)
     gz_statep state;
 {
     z_streamp strm = &(state->strm);
 
-    if (state->how == LOOK) {           /* look for gzip header */
-        if (gz_head(state) == -1)
-            return -1;
-        if (state->have)                /* got some data from gz_head() */
+    do {
+        switch(state->how) {
+        case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
+            if (gz_look(state) == -1)
+                return -1;
+            if (state->how == LOOK)
+                return 0;
+            break;
+        case COPY:      /* -> COPY */
+            if (gz_load(state, state->out, state->size << 1, &(state->x.have))
+                    == -1)
+                return -1;
+            state->x.next = state->out;
             return 0;
-    }
-    if (state->how == COPY) {           /* straight copy */
-        if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
-            return -1;
-        state->next = state->out;
-    }
-    else if (state->how == GZIP) {      /* decompress */
-        strm->avail_out = state->size << 1;
-        strm->next_out = state->out;
-        if (gz_decomp(state) == -1)
-            return -1;
-    }
+        case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
+            strm->avail_out = state->size << 1;
+            strm->next_out = state->out;
+            if (gz_decomp(state) == -1)
+                return -1;
+        }
+    } while (state->x.have == 0 && (!state->eof || strm->avail_in));
     return 0;
 }
 
@@ -336,12 +262,12 @@
     /* skip over len bytes or reach end-of-file, whichever comes first */
     while (len)
         /* skip over whatever is in output buffer */
-        if (state->have) {
-            n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
-                (unsigned)len : state->have;
-            state->have -= n;
-            state->next += n;
-            state->pos += n;
+        if (state->x.have) {
+            n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
+                (unsigned)len : state->x.have;
+            state->x.have -= n;
+            state->x.next += n;
+            state->x.pos += n;
             len -= n;
         }
 
@@ -352,7 +278,7 @@
         /* need more data to skip -- load up output buffer */
         else {
             /* get more output, looking for header if required */
-            if (gz_make(state) == -1)
+            if (gz_fetch(state) == -1)
                 return -1;
         }
     return 0;
@@ -374,14 +300,15 @@
     state = (gz_statep)file;
     strm = &(state->strm);
 
-    /* check that we're reading and that there's no error */
-    if (state->mode != GZ_READ || state->err != Z_OK)
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+            (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return -1;
 
     /* since an int is returned, make sure len fits in one, otherwise return
        with an error (this avoids the flaw in the interface) */
     if ((int)len < 0) {
-        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
+        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
         return -1;
     }
 
@@ -400,49 +327,51 @@
     got = 0;
     do {
         /* first just try copying data from the output buffer */
-        if (state->have) {
-            n = state->have > len ? len : state->have;
-            memcpy(buf, state->next, n);
-            state->next += n;
-            state->have -= n;
+        if (state->x.have) {
+            n = state->x.have > len ? len : state->x.have;
+            memcpy(buf, state->x.next, n);
+            state->x.next += n;
+            state->x.have -= n;
         }
 
         /* output buffer empty -- return if we're at the end of the input */
-        else if (state->eof && strm->avail_in == 0)
+        else if (state->eof && strm->avail_in == 0) {
+            state->past = 1;        /* tried to read past end */
             break;
+        }
 
         /* need output data -- for small len or new stream load up our output
            buffer */
         else if (state->how == LOOK || len < (state->size << 1)) {
             /* get more output, looking for header if required */
-            if (gz_make(state) == -1)
+            if (gz_fetch(state) == -1)
                 return -1;
-            continue;       /* no progress yet -- go back to memcpy() above */
+            continue;       /* no progress yet -- go back to copy above */
             /* the copy above assures that we will leave with space in the
                output buffer, allowing at least one gzungetc() to succeed */
         }
 
         /* large len -- read directly into user buffer */
         else if (state->how == COPY) {      /* read directly */
-            if (gz_load(state, buf, len, &n) == -1)
+            if (gz_load(state, (unsigned char *)buf, len, &n) == -1)
                 return -1;
         }
 
         /* large len -- decompress directly into user buffer */
         else {  /* state->how == GZIP */
             strm->avail_out = len;
-            strm->next_out = buf;
+            strm->next_out = (unsigned char *)buf;
             if (gz_decomp(state) == -1)
                 return -1;
-            n = state->have;
-            state->have = 0;
+            n = state->x.have;
+            state->x.have = 0;
         }
 
         /* update progress */
         len -= n;
         buf = (char *)buf + n;
         got += n;
-        state->pos += n;
+        state->x.pos += n;
     } while (len);
 
     /* return number of bytes read into user buffer (will fit in int) */
@@ -450,6 +379,15 @@
 }
 
 /* -- see zlib.h -- */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#else
+#  undef gzgetc
+#  ifdef MOZZCONF_H
+#    define gzgetc MOZ_Z_gzgetc
+#  endif
+#endif
+
 int ZEXPORT gzgetc(file)
     gzFile file;
 {
@@ -462,15 +400,16 @@
         return -1;
     state = (gz_statep)file;
 
-    /* check that we're reading and that there's no error */
-    if (state->mode != GZ_READ || state->err != Z_OK)
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return -1;
 
     /* try output buffer (no need to check for skip request) */
-    if (state->have) {
-        state->have--;
-        state->pos++;
-        return *(state->next)++;
+    if (state->x.have) {
+        state->x.have--;
+        state->x.pos++;
+        return *(state->x.next)++;
     }
 
     /* nothing there -- try gzread() */
@@ -478,6 +417,12 @@
     return ret < 1 ? -1 : buf[0];
 }
 
+int ZEXPORT gzgetc_(file)
+gzFile file;
+{
+    return gzgetc(file);
+}
+
 /* -- see zlib.h -- */
 int ZEXPORT gzungetc(c, file)
     int c;
@@ -490,8 +435,9 @@
         return -1;
     state = (gz_statep)file;
 
-    /* check that we're reading and that there's no error */
-    if (state->mode != GZ_READ || state->err != Z_OK)
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return -1;
 
     /* process a skip request */
@@ -506,32 +452,34 @@
         return -1;
 
     /* if output buffer empty, put byte at end (allows more pushing) */
-    if (state->have == 0) {
-        state->have = 1;
-        state->next = state->out + (state->size << 1) - 1;
-        state->next[0] = c;
-        state->pos--;
+    if (state->x.have == 0) {
+        state->x.have = 1;
+        state->x.next = state->out + (state->size << 1) - 1;
+        state->x.next[0] = c;
+        state->x.pos--;
+        state->past = 0;
         return c;
     }
 
     /* if no room, give up (must have already done a gzungetc()) */
-    if (state->have == (state->size << 1)) {
-        gz_error(state, Z_BUF_ERROR, "out of room to push characters");
+    if (state->x.have == (state->size << 1)) {
+        gz_error(state, Z_DATA_ERROR, "out of room to push characters");
         return -1;
     }
 
     /* slide output data if needed and insert byte before existing data */
-    if (state->next == state->out) {
-        unsigned char *src = state->out + state->have;
+    if (state->x.next == state->out) {
+        unsigned char *src = state->out + state->x.have;
         unsigned char *dest = state->out + (state->size << 1);
         while (src > state->out)
             *--dest = *--src;
-        state->next = dest;
+        state->x.next = dest;
     }
-    state->have++;
-    state->next--;
-    state->next[0] = c;
-    state->pos--;
+    state->x.have++;
+    state->x.next--;
+    state->x.next[0] = c;
+    state->x.pos--;
+    state->past = 0;
     return c;
 }
 
@@ -551,8 +499,9 @@
         return NULL;
     state = (gz_statep)file;
 
-    /* check that we're reading and that there's no error */
-    if (state->mode != GZ_READ || state->err != Z_OK)
+    /* check that we're reading and that there's no (serious) error */
+    if (state->mode != GZ_READ ||
+        (state->err != Z_OK && state->err != Z_BUF_ERROR))
         return NULL;
 
     /* process a skip request */
@@ -569,32 +518,31 @@
     left = (unsigned)len - 1;
     if (left) do {
         /* assure that something is in the output buffer */
-        if (state->have == 0) {
-            if (gz_make(state) == -1)
-                return NULL;            /* error */
-            if (state->have == 0) {     /* end of file */
-                if (buf == str)         /* got bupkus */
-                    return NULL;
-                break;                  /* got something -- return it */
-            }
+        if (state->x.have == 0 && gz_fetch(state) == -1)
+            return NULL;                /* error */
+        if (state->x.have == 0) {       /* end of file */
+            state->past = 1;            /* read past end */
+            break;                      /* return what we have */
         }
 
         /* look for end-of-line in current output buffer */
-        n = state->have > left ? left : state->have;
-        eol = memchr(state->next, '\n', n);
+        n = state->x.have > left ? left : state->x.have;
+        eol = (unsigned char *)memchr(state->x.next, '\n', n);
         if (eol != NULL)
-            n = (unsigned)(eol - state->next) + 1;
+            n = (unsigned)(eol - state->x.next) + 1;
 
         /* copy through end-of-line, or remainder if not found */
-        memcpy(buf, state->next, n);
-        state->have -= n;
-        state->next += n;
-        state->pos += n;
+        memcpy(buf, state->x.next, n);
+        state->x.have -= n;
+        state->x.next += n;
+        state->x.pos += n;
         left -= n;
         buf += n;
     } while (left && eol == NULL);
 
-    /* found end-of-line or out of space -- terminate string and return it */
+    /* return terminated string, or if nothing, end of file */
+    if (buf == str)
+        return NULL;
     buf[0] = 0;
     return str;
 }
@@ -610,16 +558,12 @@
         return 0;
     state = (gz_statep)file;
 
-    /* check that we're reading */
-    if (state->mode != GZ_READ)
-        return 0;
-
     /* if the state is not known, but we can find out, then do so (this is
        mainly for right after a gzopen() or gzdopen()) */
-    if (state->how == LOOK && state->have == 0)
-        (void)gz_head(state);
+    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
+        (void)gz_look(state);
 
-    /* return 1 if reading direct, 0 if decompressing a gzip stream */
+    /* return 1 if transparent, 0 if processing a gzip stream */
     return state->direct;
 }
 
@@ -627,7 +571,7 @@
 int ZEXPORT gzclose_r(file)
     gzFile file;
 {
-    int ret;
+    int ret, err;
     gz_statep state;
 
     /* get internal structure */
@@ -645,9 +589,10 @@
         free(state->out);
         free(state->in);
     }
+    err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
     gz_error(state, Z_OK, NULL);
     free(state->path);
     ret = close(state->fd);
     free(state);
-    return ret ? Z_ERRNO : Z_OK;
+    return ret ? Z_ERRNO : err;
 }
diff --git a/gzwrite.c b/gzwrite.c
index e8defc6..aa767fb 100644
--- a/gzwrite.c
+++ b/gzwrite.c
@@ -1,5 +1,5 @@
 /* gzwrite.c -- zlib functions for writing gzip files
- * Copyright (C) 2004, 2005, 2010 Mark Adler
+ * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -18,44 +18,55 @@
     int ret;
     z_streamp strm = &(state->strm);
 
-    /* allocate input and output buffers */
-    state->in = malloc(state->want);
-    state->out = malloc(state->want);
-    if (state->in == NULL || state->out == NULL) {
-        if (state->out != NULL)
-            free(state->out);
-        if (state->in != NULL)
-            free(state->in);
+    /* allocate input buffer */
+    state->in = (unsigned char *)malloc(state->want);
+    if (state->in == NULL) {
         gz_error(state, Z_MEM_ERROR, "out of memory");
         return -1;
     }
 
-    /* allocate deflate memory, set up for gzip compression */
-    strm->zalloc = Z_NULL;
-    strm->zfree = Z_NULL;
-    strm->opaque = Z_NULL;
-    ret = deflateInit2(strm, state->level, Z_DEFLATED,
-                       15 + 16, 8, state->strategy);
-    if (ret != Z_OK) {
-        free(state->in);
-        gz_error(state, Z_MEM_ERROR, "out of memory");
-        return -1;
+    /* only need output buffer and deflate state if compressing */
+    if (!state->direct) {
+        /* allocate output buffer */
+        state->out = (unsigned char *)malloc(state->want);
+        if (state->out == NULL) {
+            free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
+
+        /* allocate deflate memory, set up for gzip compression */
+        strm->zalloc = Z_NULL;
+        strm->zfree = Z_NULL;
+        strm->opaque = Z_NULL;
+        ret = deflateInit2(strm, state->level, Z_DEFLATED,
+                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
+        if (ret != Z_OK) {
+            free(state->out);
+            free(state->in);
+            gz_error(state, Z_MEM_ERROR, "out of memory");
+            return -1;
+        }
     }
 
     /* mark state as initialized */
     state->size = state->want;
 
-    /* initialize write buffer */
-    strm->avail_out = state->size;
-    strm->next_out = state->out;
-    state->next = strm->next_out;
+    /* initialize write buffer if compressing */
+    if (!state->direct) {
+        strm->avail_out = state->size;
+        strm->next_out = state->out;
+        state->x.next = strm->next_out;
+    }
     return 0;
 }
 
 /* Compress whatever is at avail_in and next_in and write to the output file.
    Return -1 if there is an error writing to the output file, otherwise 0.
    flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
-   then the deflate() state is reset to start a new gzip stream. */
+   then the deflate() state is reset to start a new gzip stream.  If gz->direct
+   is true, then simply write to the output file without compressing, and
+   ignore flush. */
 local int gz_comp(state, flush)
     gz_statep state;
     int flush;
@@ -68,6 +79,17 @@
     if (state->size == 0 && gz_init(state) == -1)
         return -1;
 
+    /* write directly if requested */
+    if (state->direct) {
+        got = write(state->fd, strm->next_in, strm->avail_in);
+        if (got < 0 || (unsigned)got != strm->avail_in) {
+            gz_error(state, Z_ERRNO, zstrerror());
+            return -1;
+        }
+        strm->avail_in = 0;
+        return 0;
+    }
+
     /* run deflate() on provided input until it produces no more output */
     ret = Z_OK;
     do {
@@ -75,8 +97,8 @@
            doing Z_FINISH then don't write until we get to Z_STREAM_END */
         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
             (flush != Z_FINISH || ret == Z_STREAM_END))) {
-            have = (unsigned)(strm->next_out - state->next);
-            if (have && ((got = write(state->fd, state->next, have)) < 0 ||
+            have = (unsigned)(strm->next_out - state->x.next);
+            if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
                          (unsigned)got != have)) {
                 gz_error(state, Z_ERRNO, zstrerror());
                 return -1;
@@ -85,7 +107,7 @@
                 strm->avail_out = state->size;
                 strm->next_out = state->out;
             }
-            state->next = strm->next_out;
+            state->x.next = strm->next_out;
         }
 
         /* compress */
@@ -131,7 +153,7 @@
         }
         strm->avail_in = n;
         strm->next_in = state->in;
-        state->pos += n;
+        state->x.pos += n;
         if (gz_comp(state, Z_NO_FLUSH) == -1)
             return -1;
         len -= n;
@@ -146,7 +168,6 @@
     unsigned len;
 {
     unsigned put = len;
-    unsigned n;
     gz_statep state;
     z_streamp strm;
 
@@ -163,7 +184,7 @@
     /* since an int is returned, make sure len fits in one, otherwise return
        with an error (this avoids the flaw in the interface) */
     if ((int)len < 0) {
-        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
+        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
         return 0;
     }
 
@@ -186,16 +207,19 @@
     if (len < state->size) {
         /* copy to input buffer, compress when full */
         do {
+            unsigned have, copy;
+
             if (strm->avail_in == 0)
                 strm->next_in = state->in;
-            n = state->size - strm->avail_in;
-            if (n > len)
-                n = len;
-            memcpy(strm->next_in + strm->avail_in, buf, n);
-            strm->avail_in += n;
-            state->pos += n;
-            buf = (char *)buf + n;
-            len -= n;
+            have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+            copy = state->size - have;
+            if (copy > len)
+                copy = len;
+            memcpy(state->in + have, buf, copy);
+            strm->avail_in += copy;
+            state->x.pos += copy;
+            buf = (const char *)buf + copy;
+            len -= copy;
             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
                 return 0;
         } while (len);
@@ -207,8 +231,8 @@
 
         /* directly compress user buffer to file */
         strm->avail_in = len;
-        strm->next_in = (voidp)buf;
-        state->pos += len;
+        strm->next_in = (z_const Bytef *)buf;
+        state->x.pos += len;
         if (gz_comp(state, Z_NO_FLUSH) == -1)
             return 0;
     }
@@ -222,6 +246,7 @@
     gzFile file;
     int c;
 {
+    unsigned have;
     unsigned char buf[1];
     gz_statep state;
     z_streamp strm;
@@ -245,19 +270,23 @@
 
     /* try writing to input buffer for speed (state->size == 0 if buffer not
        initialized) */
-    if (strm->avail_in < state->size) {
+    if (state->size) {
         if (strm->avail_in == 0)
             strm->next_in = state->in;
-        strm->next_in[strm->avail_in++] = c;
-        state->pos++;
-        return c;
+        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
+        if (have < state->size) {
+            state->in[have] = c;
+            strm->avail_in++;
+            state->x.pos++;
+            return c & 0xff;
+        }
     }
 
     /* no room in buffer or not initialized, use gz_write() */
     buf[0] = c;
     if (gzwrite(file, buf, 1) != 1)
         return -1;
-    return c;
+    return c & 0xff;
 }
 
 /* -- see zlib.h -- */
@@ -274,16 +303,15 @@
     return ret == 0 && len != 0 ? -1 : ret;
 }
 
-#ifdef STDC
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 #include <stdarg.h>
 
 /* -- see zlib.h -- */
-int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
+int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
 {
     int size, len;
     gz_statep state;
     z_streamp strm;
-    va_list va;
 
     /* get internal structure */
     if (file == NULL)
@@ -313,25 +341,20 @@
     /* do the printf() into the input buffer, put length in len */
     size = (int)(state->size);
     state->in[size - 1] = 0;
-    va_start(va, format);
 #ifdef NO_vsnprintf
 #  ifdef HAS_vsprintf_void
-    (void)vsprintf(state->in, format, va);
-    va_end(va);
+    (void)vsprintf((char *)(state->in), format, va);
     for (len = 0; len < size; len++)
         if (state->in[len] == 0) break;
 #  else
-    len = vsprintf(state->in, format, va);
-    va_end(va);
+    len = vsprintf((char *)(state->in), format, va);
 #  endif
 #else
 #  ifdef HAS_vsnprintf_void
-    (void)vsnprintf(state->in, size, format, va);
-    va_end(va);
-    len = strlen(state->in);
+    (void)vsnprintf((char *)(state->in), size, format, va);
+    len = strlen((char *)(state->in));
 #  else
     len = vsnprintf((char *)(state->in), size, format, va);
-    va_end(va);
 #  endif
 #endif
 
@@ -342,11 +365,22 @@
     /* update buffer and position, defer compression until needed */
     strm->avail_in = (unsigned)len;
     strm->next_in = state->in;
-    state->pos += len;
+    state->x.pos += len;
     return len;
 }
 
-#else /* !STDC */
+int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
+{
+    va_list va;
+    int ret;
+
+    va_start(va, format);
+    ret = gzvprintf(file, format, va);
+    va_end(va);
+    return ret;
+}
+
+#else /* !STDC && !Z_HAVE_STDARG_H */
 
 /* -- see zlib.h -- */
 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
@@ -366,6 +400,10 @@
     state = (gz_statep)file;
     strm = &(state->strm);
 
+    /* check that can really pass pointer in ints */
+    if (sizeof(int) != sizeof(void *))
+        return 0;
+
     /* check that we're writing and that there's no error */
     if (state->mode != GZ_WRITE || state->err != Z_OK)
         return 0;
@@ -390,22 +428,23 @@
     state->in[size - 1] = 0;
 #ifdef NO_snprintf
 #  ifdef HAS_sprintf_void
-    sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
+    sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     for (len = 0; len < size; len++)
         if (state->in[len] == 0) break;
 #  else
-    len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
-                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
+                  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
 #  endif
 #else
 #  ifdef HAS_snprintf_void
-    snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
+    snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
              a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
-    len = strlen(state->in);
+    len = strlen((char *)(state->in));
 #  else
-    len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
-                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+    len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
+                   a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
+                   a19, a20);
 #  endif
 #endif
 
@@ -416,7 +455,7 @@
     /* update buffer and position, defer compression until needed */
     strm->avail_in = (unsigned)len;
     strm->next_in = state->in;
-    state->pos += len;
+    state->x.pos += len;
     return len;
 }
 
@@ -500,7 +539,7 @@
 int ZEXPORT gzclose_w(file)
     gzFile file;
 {
-    int ret = 0;
+    int ret = Z_OK;
     gz_statep state;
 
     /* get internal structure */
@@ -515,17 +554,24 @@
     /* check for seek request */
     if (state->seek) {
         state->seek = 0;
-        ret += gz_zero(state, state->skip);
+        if (gz_zero(state, state->skip) == -1)
+            ret = state->err;
     }
 
     /* flush, free memory, and close file */
-    ret += gz_comp(state, Z_FINISH);
-    (void)deflateEnd(&(state->strm));
-    free(state->out);
-    free(state->in);
+    if (gz_comp(state, Z_FINISH) == -1)
+        ret = state->err;
+    if (state->size) {
+        if (!state->direct) {
+            (void)deflateEnd(&(state->strm));
+            free(state->out);
+        }
+        free(state->in);
+    }
     gz_error(state, Z_OK, NULL);
     free(state->path);
-    ret += close(state->fd);
+    if (close(state->fd) == -1)
+        ret = Z_ERRNO;
     free(state);
-    return ret ? Z_ERRNO : Z_OK;
+    return ret;
 }
diff --git a/infback.c b/infback.c
index af3a8c9..f3833c2 100644
--- a/infback.c
+++ b/infback.c
@@ -1,5 +1,5 @@
 /* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2009 Mark Adler
+ * Copyright (C) 1995-2011 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -42,10 +42,19 @@
         return Z_STREAM_ERROR;
     strm->msg = Z_NULL;                 /* in case we return an error */
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+    strm->zfree = zcfree;
+#endif
     state = (struct inflate_state FAR *)ZALLOC(strm, 1,
                                                sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
@@ -246,7 +255,7 @@
 void FAR *out_desc;
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */
@@ -394,7 +403,6 @@
                     PULLBYTE();
                 }
                 if (here.val < 16) {
-                    NEEDBITS(here.bits);
                     DROPBITS(here.bits);
                     state->lens[state->have++] = here.val;
                 }
diff --git a/inffast.c b/inffast.c
index 2f1d60b..bda59ce 100644
--- a/inffast.c
+++ b/inffast.c
@@ -1,5 +1,5 @@
 /* inffast.c -- fast decoding
- * Copyright (C) 1995-2008, 2010 Mark Adler
+ * Copyright (C) 1995-2008, 2010, 2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -69,8 +69,8 @@
 unsigned start;         /* inflate()'s starting value for strm->avail_out */
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *in;      /* local strm->next_in */
-    unsigned char FAR *last;    /* while in < last, enough input available */
+    z_const unsigned char FAR *in;      /* local strm->next_in */
+    z_const unsigned char FAR *last;    /* have enough input while in < last */
     unsigned char FAR *out;     /* local strm->next_out */
     unsigned char FAR *beg;     /* inflate()'s initial strm->next_out */
     unsigned char FAR *end;     /* while out < end, enough space available */
diff --git a/inffixed.h b/inffixed.h
index 75ed4b5..d628327 100644
--- a/inffixed.h
+++ b/inffixed.h
@@ -2,9 +2,9 @@
      * Generated automatically by makefixed().
      */
 
-    /* WARNING: this file should *not* be used by applications. It
-       is part of the implementation of the compression library and
-       is subject to change. Applications should only use zlib.h.
+    /* WARNING: this file should *not* be used by applications.
+       It is part of the implementation of this library and is
+       subject to change. Applications should only use zlib.h.
      */
 
     static const code lenfix[512] = {
diff --git a/inflate.c b/inflate.c
index a8431ab..870f89b 100644
--- a/inflate.c
+++ b/inflate.c
@@ -1,5 +1,5 @@
 /* inflate.c -- zlib decompression
- * Copyright (C) 1995-2010 Mark Adler
+ * Copyright (C) 1995-2012 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -93,14 +93,15 @@
 
 /* function prototypes */
 local void fixedtables OF((struct inflate_state FAR *state));
-local int updatewindow OF((z_streamp strm, unsigned out));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+                           unsigned copy));
 #ifdef BUILDFIXED
    void makefixed OF((void));
 #endif
-local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
                               unsigned len));
 
-int ZEXPORT inflateReset(strm)
+int ZEXPORT inflateResetKeep(strm)
 z_streamp strm;
 {
     struct inflate_state FAR *state;
@@ -109,15 +110,13 @@
     state = (struct inflate_state FAR *)strm->state;
     strm->total_in = strm->total_out = state->total = 0;
     strm->msg = Z_NULL;
-    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    if (state->wrap)        /* to support ill-conceived Java test suite */
+        strm->adler = state->wrap & 1;
     state->mode = HEAD;
     state->last = 0;
     state->havedict = 0;
     state->dmax = 32768U;
     state->head = Z_NULL;
-    state->wsize = 0;
-    state->whave = 0;
-    state->wnext = 0;
     state->hold = 0;
     state->bits = 0;
     state->lencode = state->distcode = state->next = state->codes;
@@ -127,6 +126,19 @@
     return Z_OK;
 }
 
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+    struct inflate_state FAR *state;
+
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+    state->wsize = 0;
+    state->whave = 0;
+    state->wnext = 0;
+    return inflateResetKeep(strm);
+}
+
 int ZEXPORT inflateReset2(strm, windowBits)
 z_streamp strm;
 int windowBits;
@@ -180,10 +192,19 @@
     if (strm == Z_NULL) return Z_STREAM_ERROR;
     strm->msg = Z_NULL;                 /* in case we return an error */
     if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
         strm->zalloc = zcalloc;
         strm->opaque = (voidpf)0;
+#endif
     }
-    if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+    if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+        return Z_STREAM_ERROR;
+#else
+        strm->zfree = zcfree;
+#endif
     state = (struct inflate_state FAR *)
             ZALLOC(strm, 1, sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
@@ -321,8 +342,8 @@
     low = 0;
     for (;;) {
         if ((low % 7) == 0) printf("\n        ");
-        printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
-               state.lencode[low].val);
+        printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+               state.lencode[low].bits, state.lencode[low].val);
         if (++low == size) break;
         putchar(',');
     }
@@ -355,12 +376,13 @@
    output will fall in the output data, making match copies simpler and faster.
    The advantage may be dependent on the size of the processor's data caches.
  */
-local int updatewindow(strm, out)
+local int updatewindow(strm, end, copy)
 z_streamp strm;
-unsigned out;
+const Bytef *end;
+unsigned copy;
 {
     struct inflate_state FAR *state;
-    unsigned copy, dist;
+    unsigned dist;
 
     state = (struct inflate_state FAR *)strm->state;
 
@@ -380,19 +402,18 @@
     }
 
     /* copy state->wsize or less output bytes into the circular window */
-    copy = out - strm->avail_out;
     if (copy >= state->wsize) {
-        zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        zmemcpy(state->window, end - state->wsize, state->wsize);
         state->wnext = 0;
         state->whave = state->wsize;
     }
     else {
         dist = state->wsize - state->wnext;
         if (dist > copy) dist = copy;
-        zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
+        zmemcpy(state->window + state->wnext, end - copy, dist);
         copy -= dist;
         if (copy) {
-            zmemcpy(state->window, strm->next_out - copy, copy);
+            zmemcpy(state->window, end - copy, copy);
             state->wnext = copy;
             state->whave = state->wsize;
         }
@@ -499,11 +520,6 @@
         bits -= bits & 7; \
     } while (0)
 
-/* Reverse the bytes in a 32-bit value */
-#define REVERSE(q) \
-    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
-     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
-
 /*
    inflate() uses a state machine to process as much input data and generate as
    much output data as possible before returning.  The state machine is
@@ -591,7 +607,7 @@
 int flush;
 {
     struct inflate_state FAR *state;
-    unsigned char FAR *next;    /* next input */
+    z_const unsigned char FAR *next;    /* next input */
     unsigned char FAR *put;     /* next output */
     unsigned have, left;        /* available input and output */
     unsigned long hold;         /* bit buffer */
@@ -797,7 +813,7 @@
 #endif
         case DICTID:
             NEEDBITS(32);
-            strm->adler = state->check = REVERSE(hold);
+            strm->adler = state->check = ZSWAP32(hold);
             INITBITS();
             state->mode = DICT;
         case DICT:
@@ -905,7 +921,7 @@
             while (state->have < 19)
                 state->lens[order[state->have++]] = 0;
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 7;
             ret = inflate_table(CODES, state->lens, 19, &(state->next),
                                 &(state->lenbits), state->work);
@@ -925,7 +941,6 @@
                     PULLBYTE();
                 }
                 if (here.val < 16) {
-                    NEEDBITS(here.bits);
                     DROPBITS(here.bits);
                     state->lens[state->have++] = here.val;
                 }
@@ -980,7 +995,7 @@
                values here (9 and 6) without reading the comments in inftrees.h
                concerning the ENOUGH constants, which depend on those values */
             state->next = state->codes;
-            state->lencode = (code const FAR *)(state->next);
+            state->lencode = (const code FAR *)(state->next);
             state->lenbits = 9;
             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
                                 &(state->lenbits), state->work);
@@ -989,7 +1004,7 @@
                 state->mode = BAD;
                 break;
             }
-            state->distcode = (code const FAR *)(state->next);
+            state->distcode = (const code FAR *)(state->next);
             state->distbits = 6;
             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
                             &(state->next), &(state->distbits), state->work);
@@ -1170,7 +1185,7 @@
 #ifdef GUNZIP
                      state->flags ? hold :
 #endif
-                     REVERSE(hold)) != state->check) {
+                     ZSWAP32(hold)) != state->check) {
                     strm->msg = (char *)"incorrect data check";
                     state->mode = BAD;
                     break;
@@ -1214,8 +1229,9 @@
      */
   inf_leave:
     RESTORE();
-    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
-        if (updatewindow(strm, out)) {
+    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+            (state->mode < CHECK || flush != Z_FINISH)))
+        if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
             state->mode = MEM;
             return Z_MEM_ERROR;
         }
@@ -1249,13 +1265,37 @@
     return Z_OK;
 }
 
+int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+Bytef *dictionary;
+uInt *dictLength;
+{
+    struct inflate_state FAR *state;
+
+    /* check state */
+    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state FAR *)strm->state;
+
+    /* copy dictionary */
+    if (state->whave && dictionary != Z_NULL) {
+        zmemcpy(dictionary, state->window + state->wnext,
+                state->whave - state->wnext);
+        zmemcpy(dictionary + state->whave - state->wnext,
+                state->window, state->wnext);
+    }
+    if (dictLength != Z_NULL)
+        *dictLength = state->whave;
+    return Z_OK;
+}
+
 int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
 z_streamp strm;
 const Bytef *dictionary;
 uInt dictLength;
 {
     struct inflate_state FAR *state;
-    unsigned long id;
+    unsigned long dictid;
+    int ret;
 
     /* check state */
     if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
@@ -1263,29 +1303,21 @@
     if (state->wrap != 0 && state->mode != DICT)
         return Z_STREAM_ERROR;
 
-    /* check for correct dictionary id */
+    /* check for correct dictionary identifier */
     if (state->mode == DICT) {
-        id = adler32(0L, Z_NULL, 0);
-        id = adler32(id, dictionary, dictLength);
-        if (id != state->check)
+        dictid = adler32(0L, Z_NULL, 0);
+        dictid = adler32(dictid, dictionary, dictLength);
+        if (dictid != state->check)
             return Z_DATA_ERROR;
     }
 
-    /* copy dictionary to window */
-    if (updatewindow(strm, strm->avail_out)) {
+    /* copy dictionary to window using updatewindow(), which will amend the
+       existing dictionary if appropriate */
+    ret = updatewindow(strm, dictionary + dictLength, dictLength);
+    if (ret) {
         state->mode = MEM;
         return Z_MEM_ERROR;
     }
-    if (dictLength > state->wsize) {
-        zmemcpy(state->window, dictionary + dictLength - state->wsize,
-                state->wsize);
-        state->whave = state->wsize;
-    }
-    else {
-        zmemcpy(state->window + state->wsize - dictLength, dictionary,
-                dictLength);
-        state->whave = dictLength;
-    }
     state->havedict = 1;
     Tracev((stderr, "inflate:   dictionary set\n"));
     return Z_OK;
@@ -1321,7 +1353,7 @@
  */
 local unsigned syncsearch(have, buf, len)
 unsigned FAR *have;
-unsigned char FAR *buf;
+const unsigned char FAR *buf;
 unsigned len;
 {
     unsigned got;
@@ -1433,8 +1465,8 @@
     }
 
     /* copy state */
-    zmemcpy(dest, source, sizeof(z_stream));
-    zmemcpy(copy, state, sizeof(struct inflate_state));
+    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
     if (state->lencode >= state->codes &&
         state->lencode <= state->codes + ENOUGH - 1) {
         copy->lencode = copy->codes + (state->lencode - state->codes);
diff --git a/inftrees.c b/inftrees.c
index 11e9c52..44d89cf 100644
--- a/inftrees.c
+++ b/inftrees.c
@@ -1,5 +1,5 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2010 Mark Adler
+ * Copyright (C) 1995-2013 Mark Adler
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -9,7 +9,7 @@
 #define MAXBITS 15
 
 const char inflate_copyright[] =
-   " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
+   " inflate 1.2.8 Copyright 1995-2013 Mark Adler ";
 /*
   If you use the zlib library in a product, an acknowledgment is welcome
   in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
     static const unsigned short lext[31] = { /* Length codes 257..285 extra */
         16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
-        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78};
     static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -208,8 +208,8 @@
     mask = used - 1;            /* mask for comparing low */
 
     /* check available table space */
-    if ((type == LENS && used >= ENOUGH_LENS) ||
-        (type == DISTS && used >= ENOUGH_DISTS))
+    if ((type == LENS && used > ENOUGH_LENS) ||
+        (type == DISTS && used > ENOUGH_DISTS))
         return 1;
 
     /* process all codes and make table entries */
@@ -277,8 +277,8 @@
 
             /* check for enough space */
             used += 1U << curr;
-            if ((type == LENS && used >= ENOUGH_LENS) ||
-                (type == DISTS && used >= ENOUGH_DISTS))
+            if ((type == LENS && used > ENOUGH_LENS) ||
+                (type == DISTS && used > ENOUGH_DISTS))
                 return 1;
 
             /* point entry in root table to sub-table */
@@ -289,38 +289,14 @@
         }
     }
 
-    /*
-       Fill in rest of table for incomplete codes.  This loop is similar to the
-       loop above in incrementing huff for table indices.  It is assumed that
-       len is equal to curr + drop, so there is no loop needed to increment
-       through high index bits.  When the current sub-table is filled, the loop
-       drops back to the root table to fill in any remaining entries there.
-     */
-    here.op = (unsigned char)64;                /* invalid code marker */
-    here.bits = (unsigned char)(len - drop);
-    here.val = (unsigned short)0;
-    while (huff != 0) {
-        /* when done with sub-table, drop back to root table */
-        if (drop != 0 && (huff & mask) != low) {
-            drop = 0;
-            len = root;
-            next = *table;
-            here.bits = (unsigned char)len;
-        }
-
-        /* put invalid code marker in table */
-        next[huff >> drop] = here;
-
-        /* backwards increment the len-bit code huff */
-        incr = 1U << (len - 1);
-        while (huff & incr)
-            incr >>= 1;
-        if (incr != 0) {
-            huff &= incr - 1;
-            huff += incr;
-        }
-        else
-            huff = 0;
+    /* fill in remaining table entry if code is incomplete (guaranteed to have
+       at most one remaining entry, since if the code is incomplete, the
+       maximum code length that was allowed to get this far is one bit) */
+    if (huff != 0) {
+        here.op = (unsigned char)64;            /* invalid code marker */
+        here.bits = (unsigned char)(len - drop);
+        here.val = (unsigned short)0;
+        next[huff] = here;
     }
 
     /* set return parameters */
diff --git a/mixed-source.patch b/mixed-source.patch
index ed54802..4ce1632 100644
--- a/mixed-source.patch
+++ b/mixed-source.patch
@@ -1,5 +1,5 @@
 diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c
-index 5c4022f..88b2ec0 100644
+index 6969577..7c95b30 100644
 --- a/third_party/zlib/deflate.c
 +++ b/third_party/zlib/deflate.c
 @@ -70,14 +70,15 @@ typedef enum {
@@ -34,7 +34,7 @@
  #endif
  
  #ifdef DEBUG
-@@ -281,6 +282,9 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+@@ -293,6 +294,9 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
      s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
      s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
      s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
@@ -44,7 +44,7 @@
  
      s->high_water = 0;      /* nothing written to s->window yet */
  
-@@ -367,6 +371,8 @@ int ZEXPORT deflateReset (strm)
+@@ -406,6 +410,8 @@ int ZEXPORT deflateResetKeep (strm)
      s = (deflate_state *)strm->state;
      s->pending = 0;
      s->pending_out = s->pending_buf;
@@ -53,7 +53,7 @@
  
      if (s->wrap < 0) {
          s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
-@@ -817,9 +823,26 @@ int ZEXPORT deflate (strm, flush)
+@@ -900,9 +906,26 @@ int ZEXPORT deflate (strm, flush)
          (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
          block_state bstate;
  
@@ -83,7 +83,7 @@
  
          if (bstate == finish_started || bstate == finish_done) {
              s->status = FINISH_STATE;
-@@ -915,6 +938,7 @@ int ZEXPORT deflateEnd (strm)
+@@ -999,6 +1022,7 @@ int ZEXPORT deflateEnd (strm)
      TRY_FREE(strm, strm->state->head);
      TRY_FREE(strm, strm->state->prev);
      TRY_FREE(strm, strm->state->window);
@@ -91,7 +91,7 @@
  
      ZFREE(strm, strm->state);
      strm->state = Z_NULL;
-@@ -1046,6 +1070,57 @@ local void lm_init (s)
+@@ -1131,6 +1155,57 @@ local void lm_init (s)
  #endif
  }
  
@@ -149,7 +149,7 @@
  #ifndef FASTEST
  /* ===========================================================================
   * Set match_start to the longest match starting at the given string and
-@@ -1060,9 +1135,10 @@ local void lm_init (s)
+@@ -1145,9 +1220,10 @@ local void lm_init (s)
  /* For 80x86 and 680x0, an optimized version will be provided in match.asm or
   * match.S. The code will be functionally equivalent.
   */
@@ -161,7 +161,7 @@
  {
      unsigned chain_length = s->max_chain_length;/* max hash chain length */
      register Bytef *scan = s->window + s->strstart; /* current string */
-@@ -1110,6 +1186,9 @@ local uInt longest_match(s, cur_match)
+@@ -1195,6 +1271,9 @@ local uInt longest_match(s, cur_match)
      do {
          Assert(cur_match < s->strstart, "no future");
          match = s->window + cur_match;
@@ -171,7 +171,7 @@
  
          /* Skip to next match if the match length cannot increase
           * or if the match length is less than 2.  Note that the checks below
-@@ -1152,6 +1231,8 @@ local uInt longest_match(s, cur_match)
+@@ -1237,6 +1316,8 @@ local uInt longest_match(s, cur_match)
          len = (MAX_MATCH - 1) - (int)(strend-scan);
          scan = strend - (MAX_MATCH-1);
  
@@ -180,7 +180,7 @@
  #else /* UNALIGNED_OK */
  
          if (match[best_len]   != scan_end  ||
-@@ -1168,15 +1249,23 @@ local uInt longest_match(s, cur_match)
+@@ -1253,15 +1334,23 @@ local uInt longest_match(s, cur_match)
          scan += 2, match++;
          Assert(*scan == *match, "match[2]?");
  
@@ -213,7 +213,7 @@
  
          Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
  
-@@ -1204,20 +1293,74 @@ local uInt longest_match(s, cur_match)
+@@ -1289,20 +1378,74 @@ local uInt longest_match(s, cur_match)
  }
  #endif /* ASMV */
  
@@ -289,11 +289,10 @@
      /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
       * It is easy to get rid of this optimization if necessary.
       */
-@@ -1360,6 +1503,21 @@ local void fill_window(s)
+@@ -1447,6 +1590,20 @@ local void fill_window(s)
                   */
              } while (--n);
  #endif
-+
 +            for (n = 0; n < Z_COOKIE_HASH_SIZE; n++) {
 +                if (s->cookie_locations[n] > wsize) {
 +                    s->cookie_locations[n] -= wsize;
@@ -310,8 +309,8 @@
 +
              more += wsize;
          }
-         if (s->strm->avail_in == 0) return;
-@@ -1378,6 +1536,9 @@ local void fill_window(s)
+         if (s->strm->avail_in == 0) break;
+@@ -1465,6 +1622,9 @@ local void fill_window(s)
          Assert(more >= 2, "more < 2");
  
          n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
@@ -321,7 +320,7 @@
          s->lookahead += n;
  
          /* Initialize the hash value now that we have some input: */
-@@ -1459,9 +1620,10 @@ local void fill_window(s)
+@@ -1561,9 +1721,10 @@ local void fill_window(s)
   * NOTE: this function should be optimized to avoid extra copying from
   * window to pending_buf.
   */
@@ -333,7 +332,7 @@
  {
      /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
       * to pending_buf_size, and each stored block has a 5 byte header:
-@@ -1517,13 +1679,19 @@ local block_state deflate_stored(s, flush)
+@@ -1625,13 +1786,19 @@ local block_state deflate_stored(s, flush)
   * new strings in the dictionary only for unmatched strings or for short
   * matches. It is used only for the fast compression options.
   */
@@ -354,7 +353,7 @@
      for (;;) {
          /* Make sure that we always have enough lookahead, except
           * at the end of the input file. We need MAX_MATCH bytes
-@@ -1554,7 +1722,7 @@ local block_state deflate_fast(s, flush)
+@@ -1662,7 +1829,7 @@ local block_state deflate_fast(s, flush)
               * of window index 0 (in particular we have to avoid a match
               * of the string with itself at the start of the input file).
               */
@@ -363,7 +362,7 @@
              /* longest_match() sets match_start */
          }
          if (s->match_length >= MIN_MATCH) {
-@@ -1613,12 +1781,25 @@ local block_state deflate_fast(s, flush)
+@@ -1727,12 +1894,25 @@ local block_state deflate_fast(s, flush)
   * evaluation for matches: a match is finally adopted only if there is
   * no better match at the next window position.
   */
@@ -390,7 +389,7 @@
  
      /* Process the input block. */
      for (;;) {
-@@ -1648,13 +1829,18 @@ local block_state deflate_slow(s, flush)
+@@ -1762,13 +1942,18 @@ local block_state deflate_slow(s, flush)
          s->prev_length = s->match_length, s->prev_match = s->match_start;
          s->match_length = MIN_MATCH-1;
  
@@ -412,7 +411,7 @@
              /* longest_match() sets match_start */
  
              if (s->match_length <= 5 && (s->strategy == Z_FILTERED
-@@ -1673,7 +1859,20 @@ local block_state deflate_slow(s, flush)
+@@ -1787,7 +1972,20 @@ local block_state deflate_slow(s, flush)
          /* If there was a match at the previous step and the current
           * match is not better, output the previous match:
           */
@@ -435,10 +434,10 @@
              /* Do not insert strings in hash table beyond this. */
  
 diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h
-index cbf0d1e..2fe6fd6 100644
+index ce0299e..c795034 100644
 --- a/third_party/zlib/deflate.h
 +++ b/third_party/zlib/deflate.h
-@@ -91,6 +91,9 @@ typedef unsigned IPos;
+@@ -94,6 +94,9 @@ typedef unsigned IPos;
   * save space in the various tables. IPos is used only for parameter passing.
   */
  
@@ -448,7 +447,7 @@
  typedef struct internal_state {
      z_streamp strm;      /* pointer back to this zlib stream */
      int   status;        /* as the name implies */
-@@ -139,6 +142,8 @@ typedef struct internal_state {
+@@ -142,6 +145,8 @@ typedef struct internal_state {
      uInt  hash_mask;      /* hash_size-1 */
  
      uInt  hash_shift;
@@ -458,7 +457,7 @@
       * step. It must be such that after MIN_MATCH steps, the oldest
       * byte no longer takes part in the hash key, that is:
 diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h
-index 4d54af9..da7e971 100644
+index 36c73af..5544c88 100644
 --- a/third_party/zlib/zlib.h
 +++ b/third_party/zlib/zlib.h
 @@ -101,6 +101,7 @@ typedef struct z_stream_s {
@@ -480,7 +479,7 @@
  #define zlib_version zlibVersion()
  /* for compatibility with versions < 1.0.2 */
  
-@@ -1587,6 +1592,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+@@ -1744,6 +1749,13 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
       ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
       ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
       ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
@@ -494,3 +493,6 @@
  #  endif
  #else
     ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+-- 
+2.7.4
+
diff --git a/mozzconf.h b/mozzconf.h
index 25c1d82..80994c9 100644
--- a/mozzconf.h
+++ b/mozzconf.h
@@ -74,10 +74,12 @@
 #define gzread MOZ_Z_gzread
 #define gzwrite MOZ_Z_gzwrite
 #define gzprintf MOZ_Z_gzprintf
+#define gzvprintf MOZ_Z_gzvprintf
 #define gzputs MOZ_Z_gzputs
 #define gzgets MOZ_Z_gzgets
 #define gzputc MOZ_Z_gzputc
 #define gzgetc MOZ_Z_gzgetc
+#define gzgetc_ MOZ_Z_gzgetc_
 #define gzungetc MOZ_Z_gzungetc
 #define gzflush MOZ_Z_gzflush
 #define gzseek MOZ_Z_gzseek
@@ -159,6 +161,13 @@
 #define gz_header_s MOZ_Z_gz_header_s
 #define internal_state MOZ_Z_internal_state
 
+/* New as of zlib 1.2.8 */
+#define deflateResetKeep MOZ_Z_deflateResetKeep
+#define deflatePending MOZ_Z_deflatePending
+#define inflateGetDictionary MOZ_Z_inflateGetDictionary
+#define inflateResetKeep MOZ_Z_inflateResetKeep
+#define gzopen_w MOZ_Z_gzopen_w
+
 /* Mangle Byte types except on Mac. */
 #if !defined(__MACTYPES__)
 #define Byte MOZ_Z_Byte
diff --git a/simd.patch b/simd.patch
new file mode 100644
index 0000000..5007b58
--- /dev/null
+++ b/simd.patch
@@ -0,0 +1,1198 @@
+diff --git a/third_party/zlib/crc32.c b/third_party/zlib/crc32.c
+index 979a719..09228ed 100644
+--- a/third_party/zlib/crc32.c
++++ b/third_party/zlib/crc32.c
+@@ -28,6 +28,8 @@
+ #  endif /* !DYNAMIC_CRC_TABLE */
+ #endif /* MAKECRCH */
+ 
++#include "deflate.h"
++#include "x86.h"
+ #include "zutil.h"      /* for STDC and FAR definitions */
+ 
+ #define local static
+@@ -423,3 +425,28 @@ uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+ {
+     return crc32_combine_(crc1, crc2, len2);
+ }
++
++ZLIB_INTERNAL void crc_reset(deflate_state *const s)
++{
++    if (x86_cpu_enable_simd) {
++        crc_fold_init(s);
++        return;
++    }
++    s->strm->adler = crc32(0L, Z_NULL, 0);
++}
++
++ZLIB_INTERNAL void crc_finalize(deflate_state *const s)
++{
++    if (x86_cpu_enable_simd)
++        s->strm->adler = crc_fold_512to32(s);
++}
++
++ZLIB_INTERNAL void copy_with_crc(z_streamp strm, Bytef *dst, long size)
++{
++    if (x86_cpu_enable_simd) {
++        crc_fold_copy(strm->state, dst, strm->next_in, size);
++        return;
++    }
++    zmemcpy(dst, strm->next_in, size);
++    strm->adler = crc32(strm->adler, dst, size);
++}
+diff --git a/third_party/zlib/crc_folding.c b/third_party/zlib/crc_folding.c
+new file mode 100644
+index 0000000..48d7774
+--- /dev/null
++++ b/third_party/zlib/crc_folding.c
+@@ -0,0 +1,493 @@
++/*
++ * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ
++ * instruction.
++ *
++ * A white paper describing this algorithm can be found at:
++ * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
++ *
++ * Copyright (C) 2013 Intel Corporation. All rights reserved.
++ * Authors:
++ * 	Wajdi Feghali   <wajdi.k.feghali@intel.com>
++ * 	Jim Guilford    <james.guilford@intel.com>
++ * 	Vinodh Gopal    <vinodh.gopal@intel.com>
++ * 	Erdinc Ozturk   <erdinc.ozturk@intel.com>
++ * 	Jim Kukunas     <james.t.kukunas@linux.intel.com>
++ *
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++#include "deflate.h"
++
++#include <inttypes.h>
++#include <emmintrin.h>
++#include <immintrin.h>
++#include <wmmintrin.h>
++
++#define CRC_LOAD(s) \
++    do { \
++        __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0);\
++        __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1);\
++        __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2);\
++        __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3);\
++        __m128i xmm_crc_part = _mm_loadu_si128((__m128i *)s->crc0 + 4);
++
++#define CRC_SAVE(s) \
++        _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0);\
++        _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1);\
++        _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2);\
++        _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3);\
++        _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part);\
++    } while (0);
++
++ZLIB_INTERNAL void crc_fold_init(deflate_state *const s)
++{
++    CRC_LOAD(s)
++
++    xmm_crc0 = _mm_cvtsi32_si128(0x9db42487);
++    xmm_crc1 = _mm_setzero_si128();
++    xmm_crc2 = _mm_setzero_si128();
++    xmm_crc3 = _mm_setzero_si128();
++
++    CRC_SAVE(s)
++
++    s->strm->adler = 0;
++}
++
++local void fold_1(deflate_state *const s,
++        __m128i *xmm_crc0, __m128i *xmm_crc1,
++        __m128i *xmm_crc2, __m128i *xmm_crc3)
++{
++    const __m128i xmm_fold4 = _mm_set_epi32(
++            0x00000001, 0x54442bd4,
++            0x00000001, 0xc6e41596);
++
++    __m128i x_tmp3;
++    __m128 ps_crc0, ps_crc3, ps_res;
++
++    x_tmp3 = *xmm_crc3;
++
++    *xmm_crc3 = *xmm_crc0;
++    *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
++    *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
++    ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
++    ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
++    ps_res = _mm_xor_ps(ps_crc0, ps_crc3);
++
++    *xmm_crc0 = *xmm_crc1;
++    *xmm_crc1 = *xmm_crc2;
++    *xmm_crc2 = x_tmp3;
++    *xmm_crc3 = _mm_castps_si128(ps_res);
++}
++
++local void fold_2(deflate_state *const s,
++        __m128i *xmm_crc0, __m128i *xmm_crc1,
++        __m128i *xmm_crc2, __m128i *xmm_crc3)
++{
++    const __m128i xmm_fold4 = _mm_set_epi32(
++            0x00000001, 0x54442bd4,
++            0x00000001, 0xc6e41596);
++
++    __m128i x_tmp3, x_tmp2;
++    __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20;
++
++    x_tmp3 = *xmm_crc3;
++    x_tmp2 = *xmm_crc2;
++
++    *xmm_crc3 = *xmm_crc1;
++    *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
++    *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
++    ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
++    ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
++    ps_res31= _mm_xor_ps(ps_crc3, ps_crc1);
++
++    *xmm_crc2 = *xmm_crc0;
++    *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
++    *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
++    ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
++    ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
++    ps_res20= _mm_xor_ps(ps_crc0, ps_crc2);
++
++    *xmm_crc0 = x_tmp2;
++    *xmm_crc1 = x_tmp3;
++    *xmm_crc2 = _mm_castps_si128(ps_res20);
++    *xmm_crc3 = _mm_castps_si128(ps_res31);
++}
++
++local void fold_3(deflate_state *const s,
++        __m128i *xmm_crc0, __m128i *xmm_crc1,
++        __m128i *xmm_crc2, __m128i *xmm_crc3)
++{
++    const __m128i xmm_fold4 = _mm_set_epi32(
++            0x00000001, 0x54442bd4,
++            0x00000001, 0xc6e41596);
++
++    __m128i x_tmp3;
++    __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10;
++
++    x_tmp3 = *xmm_crc3;
++
++    *xmm_crc3 = *xmm_crc2;
++    *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
++    *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
++    ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
++    ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
++    ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3);
++
++    *xmm_crc2 = *xmm_crc1;
++    *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
++    *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
++    ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
++    ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
++    ps_res21= _mm_xor_ps(ps_crc1, ps_crc2);
++
++    *xmm_crc1 = *xmm_crc0;
++    *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
++    *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10);
++    ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
++    ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
++    ps_res10= _mm_xor_ps(ps_crc0, ps_crc1);
++
++    *xmm_crc0 = x_tmp3;
++    *xmm_crc1 = _mm_castps_si128(ps_res10);
++    *xmm_crc2 = _mm_castps_si128(ps_res21);
++    *xmm_crc3 = _mm_castps_si128(ps_res32);
++}
++
++local void fold_4(deflate_state *const s,
++        __m128i *xmm_crc0, __m128i *xmm_crc1,
++        __m128i *xmm_crc2, __m128i *xmm_crc3)
++{
++    const __m128i xmm_fold4 = _mm_set_epi32(
++            0x00000001, 0x54442bd4,
++            0x00000001, 0xc6e41596);
++
++    __m128i x_tmp0, x_tmp1, x_tmp2, x_tmp3;
++    __m128 ps_crc0, ps_crc1, ps_crc2, ps_crc3;
++    __m128 ps_t0, ps_t1, ps_t2, ps_t3;
++    __m128 ps_res0, ps_res1, ps_res2, ps_res3;
++
++    x_tmp0 = *xmm_crc0;
++    x_tmp1 = *xmm_crc1;
++    x_tmp2 = *xmm_crc2;
++    x_tmp3 = *xmm_crc3;
++
++    *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
++    x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10);
++    ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
++    ps_t0 = _mm_castsi128_ps(x_tmp0);
++    ps_res0 = _mm_xor_ps(ps_crc0, ps_t0);
++
++    *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
++    x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10);
++    ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
++    ps_t1 = _mm_castsi128_ps(x_tmp1);
++    ps_res1 = _mm_xor_ps(ps_crc1, ps_t1);
++
++    *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
++    x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10);
++    ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
++    ps_t2 = _mm_castsi128_ps(x_tmp2);
++    ps_res2 = _mm_xor_ps(ps_crc2, ps_t2);
++
++    *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01);
++    x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10);
++    ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
++    ps_t3 = _mm_castsi128_ps(x_tmp3);
++    ps_res3 = _mm_xor_ps(ps_crc3, ps_t3);
++
++    *xmm_crc0 = _mm_castps_si128(ps_res0);
++    *xmm_crc1 = _mm_castps_si128(ps_res1);
++    *xmm_crc2 = _mm_castps_si128(ps_res2);
++    *xmm_crc3 = _mm_castps_si128(ps_res3);
++}
++
++local const unsigned zalign(32) pshufb_shf_table[60] = {
++	0x84838281,0x88878685,0x8c8b8a89,0x008f8e8d, /* shl 15 (16 - 1)/shr1 */
++	0x85848382,0x89888786,0x8d8c8b8a,0x01008f8e, /* shl 14 (16 - 3)/shr2 */
++	0x86858483,0x8a898887,0x8e8d8c8b,0x0201008f, /* shl 13 (16 - 4)/shr3 */
++	0x87868584,0x8b8a8988,0x8f8e8d8c,0x03020100, /* shl 12 (16 - 4)/shr4 */
++	0x88878685,0x8c8b8a89,0x008f8e8d,0x04030201, /* shl 11 (16 - 5)/shr5 */
++	0x89888786,0x8d8c8b8a,0x01008f8e,0x05040302, /* shl 10 (16 - 6)/shr6 */
++	0x8a898887,0x8e8d8c8b,0x0201008f,0x06050403, /* shl  9 (16 - 7)/shr7 */
++	0x8b8a8988,0x8f8e8d8c,0x03020100,0x07060504, /* shl  8 (16 - 8)/shr8 */
++	0x8c8b8a89,0x008f8e8d,0x04030201,0x08070605, /* shl  7 (16 - 9)/shr9 */
++	0x8d8c8b8a,0x01008f8e,0x05040302,0x09080706, /* shl  6 (16 -10)/shr10*/
++	0x8e8d8c8b,0x0201008f,0x06050403,0x0a090807, /* shl  5 (16 -11)/shr11*/
++	0x8f8e8d8c,0x03020100,0x07060504,0x0b0a0908, /* shl  4 (16 -12)/shr12*/
++	0x008f8e8d,0x04030201,0x08070605,0x0c0b0a09, /* shl  3 (16 -13)/shr13*/
++	0x01008f8e,0x05040302,0x09080706,0x0d0c0b0a, /* shl  2 (16 -14)/shr14*/
++	0x0201008f,0x06050403,0x0a090807,0x0e0d0c0b  /* shl  1 (16 -15)/shr15*/
++};
++
++local void partial_fold(deflate_state *const s, const size_t len,
++        __m128i *xmm_crc0, __m128i *xmm_crc1,
++        __m128i *xmm_crc2, __m128i *xmm_crc3,
++        __m128i *xmm_crc_part)
++{
++
++    const __m128i xmm_fold4 = _mm_set_epi32(
++            0x00000001, 0x54442bd4,
++            0x00000001, 0xc6e41596);
++    const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080);
++
++    __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3;
++    __m128i xmm_a0_0, xmm_a0_1;
++    __m128 ps_crc3, psa0_0, psa0_1, ps_res;
++
++    xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1));
++    xmm_shr = xmm_shl;
++    xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3);
++
++    xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl);
++
++    *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr);
++    xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl);
++    *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1);
++
++    *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr);
++    xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl);
++    *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2);
++
++    *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr);
++    xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl);
++    *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3);
++
++    *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr);
++    *xmm_crc_part = _mm_shuffle_epi8(*xmm_crc_part, xmm_shl);
++    *xmm_crc3 = _mm_or_si128(*xmm_crc3, *xmm_crc_part);
++
++    xmm_a0_1 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x10);
++    xmm_a0_0 = _mm_clmulepi64_si128(xmm_a0_0, xmm_fold4, 0x01);
++
++    ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
++    psa0_0 = _mm_castsi128_ps(xmm_a0_0);
++    psa0_1 = _mm_castsi128_ps(xmm_a0_1);
++
++    ps_res = _mm_xor_ps(ps_crc3, psa0_0);
++    ps_res = _mm_xor_ps(ps_res, psa0_1);
++
++    *xmm_crc3 = _mm_castps_si128(ps_res);
++}
++
++ZLIB_INTERNAL void crc_fold_copy(deflate_state *const s,
++        unsigned char *dst, const unsigned char *src, long len)
++{
++    unsigned long algn_diff;
++    __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3;
++
++    CRC_LOAD(s)
++
++    if (len < 16) {
++        if (len == 0)
++            return;
++        goto partial;
++    }
++
++    algn_diff = 0 - (uintptr_t)src & 0xF;
++    if (algn_diff) {
++        xmm_crc_part = _mm_loadu_si128((__m128i *)src);
++        _mm_storeu_si128((__m128i *)dst, xmm_crc_part);
++
++        dst += algn_diff;
++        src += algn_diff;
++        len -= algn_diff;
++
++        partial_fold(s, algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3,
++            &xmm_crc_part);
++    }
++
++    while ((len -= 64) >= 0) {
++        xmm_t0 = _mm_load_si128((__m128i *)src);
++        xmm_t1 = _mm_load_si128((__m128i *)src + 1);
++        xmm_t2 = _mm_load_si128((__m128i *)src + 2);
++        xmm_t3 = _mm_load_si128((__m128i *)src + 3);
++
++        fold_4(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
++
++        _mm_storeu_si128((__m128i *)dst, xmm_t0);
++        _mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
++        _mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
++        _mm_storeu_si128((__m128i *)dst + 3, xmm_t3);
++
++        xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0);
++        xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1);
++        xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2);
++        xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3);
++
++        src += 64;
++        dst += 64;
++    }
++
++    /*
++     * len = num bytes left - 64
++     */
++    if (len + 16 >= 0) {
++        len += 16;
++
++        xmm_t0 = _mm_load_si128((__m128i *)src);
++        xmm_t1 = _mm_load_si128((__m128i *)src + 1);
++        xmm_t2 = _mm_load_si128((__m128i *)src + 2);
++
++        fold_3(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
++
++        _mm_storeu_si128((__m128i *)dst, xmm_t0);
++        _mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
++        _mm_storeu_si128((__m128i *)dst + 2, xmm_t2);
++
++        xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0);
++        xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1);
++        xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2);
++
++        if (len == 0)
++            goto done;
++
++        dst += 48;
++        src += 48;
++    } else if (len + 32 >= 0) {
++        len += 32;
++
++        xmm_t0 = _mm_load_si128((__m128i *)src);
++        xmm_t1 = _mm_load_si128((__m128i *)src + 1);
++
++        fold_2(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
++
++        _mm_storeu_si128((__m128i *)dst, xmm_t0);
++        _mm_storeu_si128((__m128i *)dst + 1, xmm_t1);
++
++        xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0);
++        xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1);
++
++        if (len == 0)
++            goto done;
++
++        dst += 32;
++        src += 32;
++    } else if (len + 48 >= 0) {
++        len += 48;
++
++        xmm_t0 = _mm_load_si128((__m128i *)src);
++
++        fold_1(s, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3);
++
++        _mm_storeu_si128((__m128i *)dst, xmm_t0);
++
++        xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0);
++
++        if (len == 0)
++            goto done;
++
++        dst += 16;
++        src += 16;
++    } else {
++        len += 64;
++        if (len == 0)
++            goto done;
++    }
++
++partial:
++
++#if defined(_MSC_VER)
++    /* VS does not permit the use of _mm_set_epi64x in 32-bit builds */
++    {
++        int32_t parts[4] = {0, 0, 0, 0};
++        memcpy(&parts, src, len);
++        xmm_crc_part = _mm_set_epi32(parts[3], parts[2], parts[1], parts[0]);
++    }
++#else
++    {
++        int64_t parts[2] = {0, 0};
++        memcpy(&parts, src, len);
++        xmm_crc_part = _mm_set_epi64x(parts[1], parts[0]);
++    }
++#endif
++
++    _mm_storeu_si128((__m128i *)dst, xmm_crc_part);
++    partial_fold(s, len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3,
++        &xmm_crc_part);
++done:
++    CRC_SAVE(s)
++}
++
++local const unsigned zalign(16) crc_k[] = {
++    0xccaa009e, 0x00000000, /* rk1 */
++    0x751997d0, 0x00000001, /* rk2 */
++    0xccaa009e, 0x00000000, /* rk5 */
++    0x63cd6124, 0x00000001, /* rk6 */
++    0xf7011640, 0x00000001, /* rk7 */
++    0xdb710640, 0x00000001  /* rk8 */
++};
++
++local const unsigned zalign(16) crc_mask[4] = {
++    0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000
++};
++
++local const unsigned zalign(16) crc_mask2[4] = {
++    0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
++};
++
++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s)
++{
++    const __m128i xmm_mask  = _mm_load_si128((__m128i *)crc_mask);
++    const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2);
++
++    unsigned crc;
++    __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold;
++
++    CRC_LOAD(s)
++
++    /*
++     * k1
++     */
++    crc_fold = _mm_load_si128((__m128i *)crc_k);
++
++    x_tmp0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x10);
++    xmm_crc0 = _mm_clmulepi64_si128(xmm_crc0, crc_fold, 0x01);
++    xmm_crc1 = _mm_xor_si128(xmm_crc1, x_tmp0);
++    xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_crc0);
++
++    x_tmp1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x10);
++    xmm_crc1 = _mm_clmulepi64_si128(xmm_crc1, crc_fold, 0x01);
++    xmm_crc2 = _mm_xor_si128(xmm_crc2, x_tmp1);
++    xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_crc1);
++
++    x_tmp2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x10);
++    xmm_crc2 = _mm_clmulepi64_si128(xmm_crc2, crc_fold, 0x01);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, x_tmp2);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
++
++    /*
++     * k5
++     */
++    crc_fold = _mm_load_si128((__m128i *)crc_k + 1);
++
++    xmm_crc0 = xmm_crc3;
++    xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
++    xmm_crc0 = _mm_srli_si128(xmm_crc0, 8);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
++
++    xmm_crc0 = xmm_crc3;
++    xmm_crc3 = _mm_slli_si128(xmm_crc3, 4);
++    xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc0);
++    xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask2);
++
++    /*
++     * k7
++     */
++    xmm_crc1 = xmm_crc3;
++    xmm_crc2 = xmm_crc3;
++    crc_fold = _mm_load_si128((__m128i *)crc_k + 2);
++
++    xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
++    xmm_crc3 = _mm_and_si128(xmm_crc3, xmm_mask);
++
++    xmm_crc2 = xmm_crc3;
++    xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0x10);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2);
++    xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1);
++
++    crc = _mm_extract_epi32(xmm_crc3, 2);
++    return ~crc;
++    CRC_SAVE(s)
++}
+diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c
+index 7c95b30..59645eb 100644
+--- a/third_party/zlib/deflate.c
++++ b/third_party/zlib/deflate.c
+@@ -48,8 +48,9 @@
+  */
+ 
+ /* @(#) $Id$ */
+-
++#include <assert.h>
+ #include "deflate.h"
++#include "x86.h"
+ 
+ const char deflate_copyright[] =
+    " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler ";
+@@ -85,7 +86,7 @@ local block_state deflate_huff   OF((deflate_state *s, int flush));
+ local void lm_init        OF((deflate_state *s));
+ local void putShortMSB    OF((deflate_state *s, uInt b));
+ local void flush_pending  OF((z_streamp strm));
+-local int read_buf        OF((z_streamp strm, Bytef *buf, unsigned size));
++
+ #ifdef ASMV
+       void match_init OF((void)); /* asm code initialization */
+       uInt longest_match  OF((deflate_state *s, IPos cur_match, int clas));
+@@ -98,6 +99,23 @@ local  void check_match OF((deflate_state *s, IPos start, IPos match,
+                             int length));
+ #endif
+ 
++/* For fill_window_sse.c to use */
++ZLIB_INTERNAL int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
++
++/* From crc32.c */
++extern void ZLIB_INTERNAL crc_reset(deflate_state *const s);
++extern void ZLIB_INTERNAL crc_finalize(deflate_state *const s);
++extern void ZLIB_INTERNAL copy_with_crc(z_streamp strm, Bytef *dst, long size);
++
++#ifdef _MSC_VER
++#define INLINE __inline
++#else
++#define INLINE inline
++#endif
++
++/* Inline optimisation */
++local INLINE Pos insert_string_sse(deflate_state *const s, const Pos str);
++
+ /* ===========================================================================
+  * Local data
+  */
+@@ -167,7 +185,6 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+  */
+ #define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+ 
+-
+ /* ===========================================================================
+  * Insert string str in the dictionary and set match_head to the previous head
+  * of the hash chain (the most recent string with same hash key). Return
+@@ -178,17 +195,28 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+  *    input characters and the first MIN_MATCH bytes of str are valid
+  *    (except for the last MIN_MATCH-1 bytes of the input file).
+  */
++local INLINE Pos insert_string_c(deflate_state *const s, const Pos str)
++{
++    Pos ret;
++
++    UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]);
+ #ifdef FASTEST
+-#define INSERT_STRING(s, str, match_head) \
+-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+-    match_head = s->head[s->ins_h], \
+-    s->head[s->ins_h] = (Pos)(str))
++    ret = s->head[s->ins_h];
+ #else
+-#define INSERT_STRING(s, str, match_head) \
+-   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+-    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+-    s->head[s->ins_h] = (Pos)(str))
++    ret = s->prev[str & s->w_mask] = s->head[s->ins_h];
+ #endif
++    s->head[s->ins_h] = str;
++
++    return ret;
++}
++
++local INLINE Pos insert_string(deflate_state *const s, const Pos str)
++{
++    if (x86_cpu_enable_simd)
++        return insert_string_sse(s, str);
++    return insert_string_c(s, str);
++}
++
+ 
+ /* ===========================================================================
+  * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+@@ -222,6 +250,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+     const char *version;
+     int stream_size;
+ {
++    unsigned window_padding = 8;
+     deflate_state *s;
+     int wrap = 1;
+     static const char my_version[] = ZLIB_VERSION;
+@@ -231,6 +260,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+      * output size for (length,distance) codes is <= 24 bits.
+      */
+ 
++    x86_check_features();
++
+     if (version == Z_NULL || version[0] != my_version[0] ||
+         stream_size != sizeof(z_stream)) {
+         return Z_VERSION_ERROR;
+@@ -286,12 +317,17 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+     s->w_size = 1 << s->w_bits;
+     s->w_mask = s->w_size - 1;
+ 
+-    s->hash_bits = memLevel + 7;
++    if (x86_cpu_enable_simd) {
++        s->hash_bits = 15;
++    } else {
++        s->hash_bits = memLevel + 7;
++    }
++
+     s->hash_size = 1 << s->hash_bits;
+     s->hash_mask = s->hash_size - 1;
+     s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+ 
+-    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
++    s->window = (Bytef *) ZALLOC(strm, s->w_size + window_padding, 2*sizeof(Byte));
+     s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
+     s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
+     s->class_bitmap = NULL;
+@@ -369,11 +405,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+         str = s->strstart;
+         n = s->lookahead - (MIN_MATCH-1);
+         do {
+-            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
+-#ifndef FASTEST
+-            s->prev[str & s->w_mask] = s->head[s->ins_h];
+-#endif
+-            s->head[s->ins_h] = (Pos)str;
++            insert_string(s, str);
+             str++;
+         } while (--n);
+         s->strstart = str;
+@@ -696,7 +728,7 @@ int ZEXPORT deflate (strm, flush)
+     if (s->status == INIT_STATE) {
+ #ifdef GZIP
+         if (s->wrap == 2) {
+-            strm->adler = crc32(0L, Z_NULL, 0);
++            crc_reset(s);
+             put_byte(s, 31);
+             put_byte(s, 139);
+             put_byte(s, 8);
+@@ -975,6 +1007,7 @@ int ZEXPORT deflate (strm, flush)
+     /* Write the trailer */
+ #ifdef GZIP
+     if (s->wrap == 2) {
++        crc_finalize(s);
+         put_byte(s, (Byte)(strm->adler & 0xff));
+         put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+         put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+@@ -1097,7 +1130,7 @@ int ZEXPORT deflateCopy (dest, source)
+  * allocating a large strm->next_in buffer and copying from it.
+  * (See also flush_pending()).
+  */
+-local int read_buf(strm, buf, size)
++ZLIB_INTERNAL int read_buf(strm, buf, size)
+     z_streamp strm;
+     Bytef *buf;
+     unsigned size;
+@@ -1109,15 +1142,16 @@ local int read_buf(strm, buf, size)
+ 
+     strm->avail_in  -= len;
+ 
+-    zmemcpy(buf, strm->next_in, len);
+-    if (strm->state->wrap == 1) {
+-        strm->adler = adler32(strm->adler, buf, len);
+-    }
+ #ifdef GZIP
+-    else if (strm->state->wrap == 2) {
+-        strm->adler = crc32(strm->adler, buf, len);
+-    }
++    if (strm->state->wrap == 2)
++        copy_with_crc(strm, buf, len);
++    else 
+ #endif
++    {
++        zmemcpy(buf, strm->next_in, len);
++        if (strm->state->wrap == 1)
++            strm->adler = adler32(strm->adler, buf, len);
++    }
+     strm->next_in  += len;
+     strm->total_in += len;
+ 
+@@ -1530,7 +1564,19 @@ local void check_match(s, start, match, length)
+  *    performed for at least two bytes (required for the zip translate_eol
+  *    option -- not supported here).
+  */
+-local void fill_window(s)
++local void fill_window_c(deflate_state *s);
++
++local void fill_window(deflate_state *s)
++{
++    if (x86_cpu_enable_simd) {
++        fill_window_sse(s);
++        return;
++    }
++
++    fill_window_c(s);
++}
++
++local void fill_window_c(s)
+     deflate_state *s;
+ {
+     register unsigned n, m;
+@@ -1818,7 +1864,7 @@ local block_state deflate_fast(s, flush, clas)
+          */
+         hash_head = NIL;
+         if (s->lookahead >= MIN_MATCH) {
+-            INSERT_STRING(s, s->strstart, hash_head);
++            hash_head = insert_string(s, s->strstart);
+         }
+ 
+         /* Find the longest match, discarding those <= prev_length.
+@@ -1849,7 +1895,7 @@ local block_state deflate_fast(s, flush, clas)
+                 s->match_length--; /* string at strstart already in table */
+                 do {
+                     s->strstart++;
+-                    INSERT_STRING(s, s->strstart, hash_head);
++                    hash_head = insert_string(s, s->strstart);
+                     /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+                      * always MIN_MATCH bytes ahead.
+                      */
+@@ -1934,7 +1980,7 @@ local block_state deflate_slow(s, flush, clas)
+          */
+         hash_head = NIL;
+         if (s->lookahead >= MIN_MATCH) {
+-            INSERT_STRING(s, s->strstart, hash_head);
++            hash_head = insert_string(s, s->strstart);
+         }
+ 
+         /* Find the longest match, discarding those <= prev_length.
+@@ -2003,7 +2049,7 @@ local block_state deflate_slow(s, flush, clas)
+             s->prev_length -= 2;
+             do {
+                 if (++s->strstart <= max_insert) {
+-                    INSERT_STRING(s, s->strstart, hash_head);
++                    hash_head = insert_string(s, s->strstart);
+                 }
+             } while (--s->prev_length != 0);
+             s->match_available = 0;
+@@ -2163,3 +2209,37 @@ local block_state deflate_huff(s, flush)
+         FLUSH_BLOCK(s, 0);
+     return block_done;
+ }
++
++/* Safe to inline this as GCC/clang will use inline asm and Visual Studio will
++ * use intrinsic without extra params
++ */
++local INLINE Pos insert_string_sse(deflate_state *const s, const Pos str)
++{
++    Pos ret;
++    unsigned *ip, val, h = 0;
++
++    ip = (unsigned *)&s->window[str];
++    val = *ip;
++
++    if (s->level >= 6)
++        val &= 0xFFFFFF;
++
++/* Windows clang should use inline asm */
++#if defined(_MSC_VER) && !defined(__clang__)
++    h = _mm_crc32_u32(h, val);
++#elif defined(__i386__) || defined(__amd64__)
++    __asm__ __volatile__ (
++        "crc32 %1,%0\n\t"
++    : "+r" (h)
++    : "r" (val)
++    );
++#else
++    /* This should never happen */
++    assert(0);
++#endif
++
++    ret = s->head[h & s->hash_mask];
++    s->head[h & s->hash_mask] = str;
++    s->prev[str & s->w_mask] = ret;
++    return ret;
++}
+diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h
+index c795034..c61e4ab 100644
+--- a/third_party/zlib/deflate.h
++++ b/third_party/zlib/deflate.h
+@@ -109,7 +109,7 @@ typedef struct internal_state {
+     uInt   gzindex;      /* where in extra, name, or comment */
+     Byte  method;        /* can only be DEFLATED */
+     int   last_flush;    /* value of flush param for previous deflate call */
+-
++    unsigned zalign(16) crc0[4 * 5];
+                 /* used by deflate.c: */
+ 
+     uInt  w_size;        /* LZ77 window size (32K by default) */
+@@ -348,4 +348,14 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
+               flush = _tr_tally(s, distance, length)
+ #endif
+ 
++/* Functions that are SIMD optimised on x86 */
++void ZLIB_INTERNAL crc_fold_init(deflate_state* const s);
++void ZLIB_INTERNAL crc_fold_copy(deflate_state* const s,
++                                 unsigned char* dst,
++                                 const unsigned char* src,
++                                 long len);
++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state* const s);
++
++void ZLIB_INTERNAL fill_window_sse(deflate_state* s);
++
+ #endif /* DEFLATE_H */
+diff --git a/third_party/zlib/fill_window_sse.c b/third_party/zlib/fill_window_sse.c
+new file mode 100644
+index 0000000..949ccce
+--- /dev/null
++++ b/third_party/zlib/fill_window_sse.c
+@@ -0,0 +1,175 @@
++/*
++ * Fill Window with SSE2-optimized hash shifting
++ *
++ * Copyright (C) 2013 Intel Corporation
++ * Authors:
++ *  Arjan van de Ven    <arjan@linux.intel.com>
++ *  Jim Kukunas         <james.t.kukunas@linux.intel.com>
++ *
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++#include <immintrin.h>
++#include "deflate.h"
++
++#define UPDATE_HASH(s,h,i) \
++    {\
++        if (s->level < 6) { \
++            h = (3483 * (s->window[i]) +\
++                 23081* (s->window[i+1]) +\
++                 6954 * (s->window[i+2]) +\
++                 20947* (s->window[i+3])) & s->hash_mask;\
++        } else {\
++            h = (25881* (s->window[i]) +\
++                 24674* (s->window[i+1]) +\
++                 25811* (s->window[i+2])) & s->hash_mask;\
++        }\
++    }\
++
++extern int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
++
++void fill_window_sse(deflate_state *s)
++{
++    const __m128i xmm_wsize = _mm_set1_epi16(s->w_size);
++
++    register unsigned n;
++    register Posf *p;
++    unsigned more;    /* Amount of free space at the end of the window. */
++    uInt wsize = s->w_size;
++
++    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead");
++
++    do {
++        more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
++
++        /* Deal with !@#$% 64K limit: */
++        if (sizeof(int) <= 2) {
++            if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
++                more = wsize;
++
++            } else if (more == (unsigned)(-1)) {
++                /* Very unlikely, but possible on 16 bit machine if
++                 * strstart == 0 && lookahead == 1 (input done a byte at time)
++                 */
++                more--;
++            }
++        }
++
++        /* If the window is almost full and there is insufficient lookahead,
++         * move the upper half to the lower one to make room in the upper half.
++         */
++        if (s->strstart >= wsize+MAX_DIST(s)) {
++
++            zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
++            s->match_start -= wsize;
++            s->strstart    -= wsize; /* we now have strstart >= MAX_DIST */
++            s->block_start -= (long) wsize;
++
++            /* Slide the hash table (could be avoided with 32 bit values
++               at the expense of memory usage). We slide even when level == 0
++               to keep the hash table consistent if we switch back to level > 0
++               later. (Using level 0 permanently is not an optimal usage of
++               zlib, so we don't care about this pathological case.)
++             */
++            n = s->hash_size;
++            p = &s->head[n];
++            p -= 8;
++            do {
++                __m128i value, result;
++
++                value = _mm_loadu_si128((__m128i *)p);
++                result = _mm_subs_epu16(value, xmm_wsize);
++                _mm_storeu_si128((__m128i *)p, result);
++
++                p -= 8;
++                n -= 8;
++            } while (n > 0);
++
++            n = wsize;
++#ifndef FASTEST
++            p = &s->prev[n];
++            p -= 8;
++            do {
++                __m128i value, result;
++
++                value = _mm_loadu_si128((__m128i *)p);
++                result = _mm_subs_epu16(value, xmm_wsize);
++                _mm_storeu_si128((__m128i *)p, result);
++
++                p -= 8;
++                n -= 8;
++            } while (n > 0);
++#endif
++            more += wsize;
++        }
++        if (s->strm->avail_in == 0) break;
++
++        /* If there was no sliding:
++         *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
++         *    more == window_size - lookahead - strstart
++         * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
++         * => more >= window_size - 2*WSIZE + 2
++         * In the BIG_MEM or MMAP case (not yet supported),
++         *   window_size == input_size + MIN_LOOKAHEAD  &&
++         *   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
++         * Otherwise, window_size == 2*WSIZE so more >= 2.
++         * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
++         */
++        Assert(more >= 2, "more < 2");
++
++        n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
++        s->lookahead += n;
++
++        /* Initialize the hash value now that we have some input: */
++        if (s->lookahead >= MIN_MATCH) {
++            uInt str = s->strstart;
++            s->ins_h = s->window[str];
++            if (str >= 1)
++                UPDATE_HASH(s, s->ins_h, str + 1 - (MIN_MATCH-1));
++#if MIN_MATCH != 3
++            Call UPDATE_HASH() MIN_MATCH-3 more times
++#endif
++        }
++        /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
++         * but this is not important since only literal bytes will be emitted.
++         */
++
++    } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
++
++    /* If the WIN_INIT bytes after the end of the current data have never been
++     * written, then zero those bytes in order to avoid memory check reports of
++     * the use of uninitialized (or uninitialised as Julian writes) bytes by
++     * the longest match routines.  Update the high water mark for the next
++     * time through here.  WIN_INIT is set to MAX_MATCH since the longest match
++     * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
++     */
++    if (s->high_water < s->window_size) {
++        ulg curr = s->strstart + (ulg)(s->lookahead);
++        ulg init;
++
++        if (s->high_water < curr) {
++            /* Previous high water mark below current data -- zero WIN_INIT
++             * bytes or up to end of window, whichever is less.
++             */
++            init = s->window_size - curr;
++            if (init > WIN_INIT)
++                init = WIN_INIT;
++            zmemzero(s->window + curr, (unsigned)init);
++            s->high_water = curr + init;
++        }
++        else if (s->high_water < (ulg)curr + WIN_INIT) {
++            /* High water mark at or above current data, but below current data
++             * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
++             * to end of window, whichever is less.
++             */
++            init = (ulg)curr + WIN_INIT - s->high_water;
++            if (init > s->window_size - s->high_water)
++                init = s->window_size - s->high_water;
++            zmemzero(s->window + s->high_water, (unsigned)init);
++            s->high_water += init;
++        }
++    }
++
++    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD,
++           "not enough room for search");
++}
+diff --git a/third_party/zlib/simd_stub.c b/third_party/zlib/simd_stub.c
+new file mode 100644
+index 0000000..796f1f6
+--- /dev/null
++++ b/third_party/zlib/simd_stub.c
+@@ -0,0 +1,35 @@
++/* simd_stub.c -- stub implementations
++* Copyright (C) 2014 Intel Corporation
++* For conditions of distribution and use, see copyright notice in zlib.h
++*/
++#include <assert.h>
++
++#include "deflate.h"
++#include "x86.h"
++
++int x86_cpu_enable_simd = 0;
++
++void ZLIB_INTERNAL crc_fold_init(deflate_state *const s) {
++    assert(0);
++}
++
++void ZLIB_INTERNAL crc_fold_copy(deflate_state *const s,
++                                 unsigned char *dst,
++                                 const unsigned char *src,
++                                 long len) {
++    assert(0);
++}
++
++unsigned ZLIB_INTERNAL crc_fold_512to32(deflate_state *const s) {
++    assert(0);
++    return 0;
++}
++
++void ZLIB_INTERNAL fill_window_sse(deflate_state *s)
++{
++    assert(0);
++}
++
++void x86_check_features(void)
++{
++}
+diff --git a/third_party/zlib/x86.c b/third_party/zlib/x86.c
+new file mode 100644
+index 0000000..e6532fd
+--- /dev/null
++++ b/third_party/zlib/x86.c
+@@ -0,0 +1,91 @@
++/*
++ * x86 feature check
++ *
++ * Copyright (C) 2013 Intel Corporation. All rights reserved.
++ * Author:
++ *  Jim Kukunas
++ * 
++ * For conditions of distribution and use, see copyright notice in zlib.h
++ */
++
++#include "x86.h"
++
++int x86_cpu_enable_simd = 0;
++
++#ifndef _MSC_VER
++#include <pthread.h>
++
++pthread_once_t cpu_check_inited_once = PTHREAD_ONCE_INIT;
++static void _x86_check_features(void);
++
++void x86_check_features(void)
++{
++  pthread_once(&cpu_check_inited_once, _x86_check_features);
++}
++
++static void _x86_check_features(void)
++{
++    int x86_cpu_has_sse2;
++    int x86_cpu_has_sse42;
++    int x86_cpu_has_pclmulqdq;
++    unsigned eax, ebx, ecx, edx;
++
++    eax = 1;
++#ifdef __i386__
++    __asm__ __volatile__ (
++        "xchg %%ebx, %1\n\t"
++        "cpuid\n\t"
++        "xchg %1, %%ebx\n\t"
++    : "+a" (eax), "=S" (ebx), "=c" (ecx), "=d" (edx)
++    );
++#else
++    __asm__ __volatile__ (
++        "cpuid\n\t"
++    : "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
++    );
++#endif  /* (__i386__) */
++
++    x86_cpu_has_sse2 = edx & 0x4000000;
++    x86_cpu_has_sse42 = ecx & 0x100000;
++    x86_cpu_has_pclmulqdq = ecx & 0x2;
++
++    x86_cpu_enable_simd = x86_cpu_has_sse2 &&
++                          x86_cpu_has_sse42 &&
++                          x86_cpu_has_pclmulqdq;
++}
++#else
++#include <intrin.h>
++#include <windows.h>
++
++static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
++                                         PVOID param,
++                                         PVOID *context);
++static INIT_ONCE cpu_check_inited_once = INIT_ONCE_STATIC_INIT;
++
++void x86_check_features(void)
++{
++    InitOnceExecuteOnce(&cpu_check_inited_once, _x86_check_features,
++                        NULL, NULL);
++}
++
++static BOOL CALLBACK _x86_check_features(PINIT_ONCE once,
++                                         PVOID param,
++                                         PVOID *context)
++{
++    int x86_cpu_has_sse2;
++    int x86_cpu_has_sse42;
++    int x86_cpu_has_pclmulqdq;
++    int regs[4];
++
++    __cpuid(regs, 1);
++
++    x86_cpu_has_sse2 = regs[3] & 0x4000000;
++    x86_cpu_has_sse42= regs[2] & 0x100000;
++    x86_cpu_has_pclmulqdq = regs[2] & 0x2;
++
++    x86_cpu_enable_simd = x86_cpu_has_sse2 &&
++                          x86_cpu_has_sse42 &&
++                          x86_cpu_has_pclmulqdq;
++    return TRUE;
++}
++#endif  /* _MSC_VER */
+diff --git a/third_party/zlib/x86.h b/third_party/zlib/x86.h
+new file mode 100644
+index 0000000..ac3d180
+--- /dev/null
++++ b/third_party/zlib/x86.h
+@@ -0,0 +1,13 @@
++/* x86.h -- check for x86 CPU features
++* Copyright (C) 2013 Intel Corporation Jim Kukunas
++* For conditions of distribution and use, see copyright notice in zlib.h
++*/
++
++#ifndef X86_H
++#define X86_H
++
++extern int x86_cpu_enable_simd;
++
++void x86_check_features(void);
++
++#endif  /* X86_H */
+-- 
+2.7.4
+
diff --git a/trees.c b/trees.c
index 56e9bb1..1fd7759 100644
--- a/trees.c
+++ b/trees.c
@@ -1,5 +1,5 @@
 /* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2010 Jean-loup Gailly
+ * Copyright (C) 1995-2012 Jean-loup Gailly
  * detect_data_type() function provided freely by Cosmin Truta, 2006
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
@@ -74,11 +74,6 @@
  * probability, to avoid transmitting the lengths for unused bit length codes.
  */
 
-#define Buf_size (8 * 2*sizeof(char))
-/* Number of bits used within bi_buf. (bi_buf might be implemented on
- * more than 16 bits on some systems.)
- */
-
 /* ===========================================================================
  * Local data. These are initialized only once.
  */
@@ -151,8 +146,8 @@
 local int  build_bl_tree  OF((deflate_state *s));
 local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
                               int blcodes));
-local void compress_block OF((deflate_state *s, ct_data *ltree,
-                              ct_data *dtree));
+local void compress_block OF((deflate_state *s, const ct_data *ltree,
+                              const ct_data *dtree));
 local int  detect_data_type OF((deflate_state *s));
 local unsigned bi_reverse OF((unsigned value, int length));
 local void bi_windup      OF((deflate_state *s));
@@ -399,7 +394,6 @@
 
     s->bi_buf = 0;
     s->bi_valid = 0;
-    s->last_eob_len = 8; /* enough lookahead for inflate */
 #ifdef DEBUG
     s->compressed_len = 0L;
     s->bits_sent = 0L;
@@ -883,15 +877,17 @@
 }
 
 /* ===========================================================================
+ * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
+ */
+void ZLIB_INTERNAL _tr_flush_bits(s)
+    deflate_state *s;
+{
+    bi_flush(s);
+}
+
+/* ===========================================================================
  * Send one empty static block to give enough lookahead for inflate.
  * This takes 10 bits, of which 7 may remain in the bit buffer.
- * The current inflate code requires 9 bits of lookahead. If the
- * last two codes for the previous block (real code plus EOB) were coded
- * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
- * the last real code. In this case we send two empty static blocks instead
- * of one. (There are no problems if the previous block is stored or fixed.)
- * To simplify the code, we assume the worst case of last real code encoded
- * on one bit only.
  */
 void ZLIB_INTERNAL _tr_align(s)
     deflate_state *s;
@@ -902,20 +898,6 @@
     s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
 #endif
     bi_flush(s);
-    /* Of the 10 bits for the empty block, we have already sent
-     * (10 - bi_valid) bits. The lookahead for the last real code (before
-     * the EOB of the previous block) was thus at least one plus the length
-     * of the EOB plus what we have just sent of the empty static block.
-     */
-    if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
-        send_bits(s, STATIC_TREES<<1, 3);
-        send_code(s, END_BLOCK, static_ltree);
-#ifdef DEBUG
-        s->compressed_len += 10L;
-#endif
-        bi_flush(s);
-    }
-    s->last_eob_len = 7;
 }
 
 /* ===========================================================================
@@ -990,7 +972,8 @@
     } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
 #endif
         send_bits(s, (STATIC_TREES<<1)+last, 3);
-        compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+        compress_block(s, (const ct_data *)static_ltree,
+                       (const ct_data *)static_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->static_len;
 #endif
@@ -998,7 +981,8 @@
         send_bits(s, (DYN_TREES<<1)+last, 3);
         send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
                        max_blindex+1);
-        compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+        compress_block(s, (const ct_data *)s->dyn_ltree,
+                       (const ct_data *)s->dyn_dtree);
 #ifdef DEBUG
         s->compressed_len += 3 + s->opt_len;
 #endif
@@ -1075,8 +1059,8 @@
  */
 local void compress_block(s, ltree, dtree)
     deflate_state *s;
-    ct_data *ltree; /* literal tree */
-    ct_data *dtree; /* distance tree */
+    const ct_data *ltree; /* literal tree */
+    const ct_data *dtree; /* distance tree */
 {
     unsigned dist;      /* distance of matched string */
     int lc;             /* match length or unmatched char (if dist == 0) */
@@ -1118,7 +1102,6 @@
     } while (lx < s->last_lit);
 
     send_code(s, END_BLOCK, ltree);
-    s->last_eob_len = ltree[END_BLOCK].Len;
 }
 
 /* ===========================================================================
@@ -1226,7 +1209,6 @@
     int      header;  /* true if block header must be written */
 {
     bi_windup(s);        /* align on byte boundary */
-    s->last_eob_len = 8; /* enough lookahead for inflate */
 
     if (header) {
         put_short(s, (ush)len);
diff --git a/uncompr.c b/uncompr.c
index ad98be3..242e949 100644
--- a/uncompr.c
+++ b/uncompr.c
@@ -30,7 +30,7 @@
     z_stream stream;
     int err;
 
-    stream.next_in = (Bytef*)source;
+    stream.next_in = (z_const Bytef *)source;
     stream.avail_in = (uInt)sourceLen;
     /* Check for source > 64K on 16-bit machine: */
     if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
diff --git a/zconf.h b/zconf.h
index 73662d8..1b1d88b 100644
--- a/zconf.h
+++ b/zconf.h
@@ -1,5 +1,5 @@
 /* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -18,11 +18,13 @@
  * this permanently in zconf.h using "./configure --zprefix".
  */
 #ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
 
 /* all linked symbols */
 #  define _dist_code            z__dist_code
 #  define _length_code          z__length_code
 #  define _tr_align             z__tr_align
+#  define _tr_flush_bits        z__tr_flush_bits
 #  define _tr_flush_block       z__tr_flush_block
 #  define _tr_init              z__tr_init
 #  define _tr_stored_block      z__tr_stored_block
@@ -30,9 +32,11 @@
 #  define adler32               z_adler32
 #  define adler32_combine       z_adler32_combine
 #  define adler32_combine64     z_adler32_combine64
-#  define compress              z_compress
-#  define compress2             z_compress2
-#  define compressBound         z_compressBound
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
 #  define crc32                 z_crc32
 #  define crc32_combine         z_crc32_combine
 #  define crc32_combine64       z_crc32_combine64
@@ -43,44 +47,53 @@
 #  define deflateInit2_         z_deflateInit2_
 #  define deflateInit_          z_deflateInit_
 #  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
 #  define deflatePrime          z_deflatePrime
 #  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
 #  define deflateSetDictionary  z_deflateSetDictionary
 #  define deflateSetHeader      z_deflateSetHeader
 #  define deflateTune           z_deflateTune
 #  define deflate_copyright     z_deflate_copyright
 #  define get_crc_table         z_get_crc_table
-#  define gz_error              z_gz_error
-#  define gz_intmax             z_gz_intmax
-#  define gz_strwinerror        z_gz_strwinerror
-#  define gzbuffer              z_gzbuffer
-#  define gzclearerr            z_gzclearerr
-#  define gzclose               z_gzclose
-#  define gzclose_r             z_gzclose_r
-#  define gzclose_w             z_gzclose_w
-#  define gzdirect              z_gzdirect
-#  define gzdopen               z_gzdopen
-#  define gzeof                 z_gzeof
-#  define gzerror               z_gzerror
-#  define gzflush               z_gzflush
-#  define gzgetc                z_gzgetc
-#  define gzgets                z_gzgets
-#  define gzoffset              z_gzoffset
-#  define gzoffset64            z_gzoffset64
-#  define gzopen                z_gzopen
-#  define gzopen64              z_gzopen64
-#  define gzprintf              z_gzprintf
-#  define gzputc                z_gzputc
-#  define gzputs                z_gzputs
-#  define gzread                z_gzread
-#  define gzrewind              z_gzrewind
-#  define gzseek                z_gzseek
-#  define gzseek64              z_gzseek64
-#  define gzsetparams           z_gzsetparams
-#  define gztell                z_gztell
-#  define gztell64              z_gztell64
-#  define gzungetc              z_gzungetc
-#  define gzwrite               z_gzwrite
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzvprintf             z_gzvprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzwrite               z_gzwrite
+#  endif
 #  define inflate               z_inflate
 #  define inflateBack           z_inflateBack
 #  define inflateBackEnd        z_inflateBackEnd
@@ -95,16 +108,22 @@
 #  define inflateReset          z_inflateReset
 #  define inflateReset2         z_inflateReset2
 #  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateGetDictionary  z_inflateGetDictionary
 #  define inflateSync           z_inflateSync
 #  define inflateSyncPoint      z_inflateSyncPoint
 #  define inflateUndermine      z_inflateUndermine
+#  define inflateResetKeep      z_inflateResetKeep
 #  define inflate_copyright     z_inflate_copyright
 #  define inflate_fast          z_inflate_fast
 #  define inflate_table         z_inflate_table
-#  define uncompress            z_uncompress
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#  endif
 #  define zError                z_zError
-#  define zcalloc               z_zcalloc
-#  define zcfree                z_zcfree
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
 #  define zlibCompileFlags      z_zlibCompileFlags
 #  define zlibVersion           z_zlibVersion
 
@@ -114,7 +133,9 @@
 #  define alloc_func            z_alloc_func
 #  define charf                 z_charf
 #  define free_func             z_free_func
-#  define gzFile                z_gzFile
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
 #  define gz_header             z_gz_header
 #  define gz_headerp            z_gz_headerp
 #  define in_func               z_in_func
@@ -200,6 +221,12 @@
 #  endif
 #endif
 
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
 /* Some Mac compilers merge all .h files incorrectly: */
 #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
 #  define NO_DUMMY_DECL
@@ -246,6 +273,14 @@
 #  endif
 #endif
 
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
 /* The following definitions for FAR are needed only for MSDOS mixed
  * model programming (small or medium model with some far allocations).
  * This was tested only with MSC; for other MSDOS compilers you may have
@@ -359,12 +394,47 @@
    typedef Byte       *voidp;
 #endif
 
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  elif (ULONG_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned long
+#  elif (USHRT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned short
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
 #if !defined(_WIN32)
 #  define Z_HAVE_UNISTD_H
 #endif
 
+#ifdef HAVE_STDARG_H    /* may be set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
 #ifdef STDC
-#  include <sys/types.h>    /* for off_t */
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+#    include <stdarg.h>         /* for va_list */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  ifndef Z_SOLO
+#    include <stddef.h>         /* for wchar_t */
+#  endif
 #endif
 
 /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
@@ -373,21 +443,38 @@
  * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
  * equivalently requesting no 64-bit operations
  */
-#if -_LARGEFILE64_SOURCE - -1 == 1
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
 #  undef _LARGEFILE64_SOURCE
 #endif
 
-#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
-#  include <unistd.h>       /* for SEEK_* and off_t */
-#  ifdef VMS
-#    include <unixio.h>     /* for off_t */
-#  endif
-#  ifndef z_off_t
-#    define z_off_t off_t
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
 #  endif
 #endif
 
-#ifndef SEEK_SET
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
 #  define SEEK_SET        0       /* Seek from beginning of file.  */
 #  define SEEK_CUR        1       /* Seek from current position.  */
 #  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
@@ -397,18 +484,14 @@
 #  define z_off_t long
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#if !defined(_WIN32) && defined(Z_LARGE64)
 #  define z_off64_t off64_t
 #else
-#  define z_off64_t z_off_t
-#endif
-
-#if defined(__OS400__)
-#  define NO_vsnprintf
-#endif
-
-#if defined(__MVS__)
-#  define NO_vsnprintf
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
 #endif
 
 /* MVS linker does not support external names larger than 8 bytes */
diff --git a/zlib.h b/zlib.h
index e88e5a5..5544c88 100644
--- a/zlib.h
+++ b/zlib.h
@@ -1,7 +1,7 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.2.5, April 19th, 2010
+  version 1.2.8, April 28th, 2013
 
-  Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -24,8 +24,8 @@
 
 
   The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
-  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
 */
 
 #ifndef ZLIB_H
@@ -37,11 +37,11 @@
 extern "C" {
 #endif
 
-#define ZLIB_VERSION "1.2.5"
-#define ZLIB_VERNUM 0x1250
+#define ZLIB_VERSION "1.2.8"
+#define ZLIB_VERNUM 0x1280
 #define ZLIB_VER_MAJOR 1
 #define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 5
+#define ZLIB_VER_REVISION 8
 #define ZLIB_VER_SUBREVISION 0
 
 /*
@@ -83,15 +83,15 @@
 struct internal_state;
 
 typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
+    z_const Bytef *next_in;     /* next input byte */
     uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
+    uLong    total_in;  /* total number of input bytes read so far */
 
     Bytef    *next_out; /* next output byte should be put there */
     uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
+    uLong    total_out; /* total number of bytes output so far */
 
-    char     *msg;      /* last error message, NULL if no error */
+    z_const char *msg;  /* last error message, NULL if no error */
     struct internal_state FAR *state; /* not visible by applications */
 
     alloc_func zalloc;  /* used to allocate the internal state */
@@ -332,8 +332,9 @@
 
     Z_FINISH can be used immediately after deflateInit if all the compression
   is to be done in a single step.  In this case, avail_out must be at least the
-  value returned by deflateBound (see below).  If deflate does not return
-  Z_STREAM_END, then it must be called again as described above.
+  value returned by deflateBound (see below).  Then deflate is guaranteed to
+  return Z_STREAM_END.  If not enough output space is provided, deflate will
+  not return Z_STREAM_END, and it must be called again as described above.
 
     deflate() sets strm->adler to the adler32 checksum of all input read
   so far (that is, total_in bytes).
@@ -456,23 +457,29 @@
   error.  However if all decompression is to be performed in a single step (a
   single call of inflate), the parameter flush should be set to Z_FINISH.  In
   this case all pending input is processed and all pending output is flushed;
-  avail_out must be large enough to hold all the uncompressed data.  (The size
-  of the uncompressed data may have been saved by the compressor for this
-  purpose.) The next operation on this stream must be inflateEnd to deallocate
-  the decompression state.  The use of Z_FINISH is never required, but can be
-  used to inform inflate that a faster approach may be used for the single
-  inflate() call.
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.) The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
 
      In this implementation, inflate() always flushes as much output as
   possible to the output buffer, and always uses the faster approach on the
-  first call.  So the only effect of the flush parameter in this implementation
-  is on the return value of inflate(), as noted below, or when it returns early
-  because Z_BLOCK or Z_TREES is used.
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
 
      If a preset dictionary is needed after this call (see inflateSetDictionary
-  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
   chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
-  strm->adler to the adler32 checksum of all output produced so far (that is,
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
   total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
   below.  At the end of the stream, inflate() checks that its computed adler32
   checksum is equal to that saved by the compressor and returns Z_STREAM_END
@@ -483,7 +490,9 @@
   initializing with inflateInit2().  Any information contained in the gzip
   header is not retained, so applications that need that information should
   instead use raw inflate, see inflateInit2() below, or inflateBack() and
-  perform their own processing of the gzip header and trailer.
+  perform their own processing of the gzip header and trailer.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  producted so far.  The CRC-32 is checked against the gzip trailer.
 
     inflate() returns Z_OK if some progress has been made (more input processed
   or more output produced), Z_STREAM_END if the end of the compressed data has
@@ -585,10 +594,15 @@
                                              uInt  dictLength));
 /*
      Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output.  This function must be called
-   immediately after deflateInit, deflateInit2 or deflateReset, before any call
-   of deflate.  The compressor and decompressor must use exactly the same
-   dictionary (see inflateSetDictionary).
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
 
      The dictionary should consist of strings (byte sequences) that are likely
    to be encountered later in the data to be compressed, with the most commonly
@@ -615,8 +629,8 @@
      deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
    parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
    inconsistent (for example if deflate has already been called for this stream
-   or if the compression method is bsort).  deflateSetDictionary does not
-   perform any compression: this will be done by deflate().
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
 */
 
 ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
@@ -693,9 +707,29 @@
    deflation of sourceLen bytes.  It must be called after deflateInit() or
    deflateInit2(), and after deflateSetHeader(), if used.  This would be used
    to allocate an output buffer for deflation in a single pass, and so would be
-   called before deflate().
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
 */
 
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
 ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
                                      int bits,
                                      int value));
@@ -708,8 +742,9 @@
    than or equal to 16, and that many of the least significant bits of value
    will be inserted in the output.
 
-     deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent.
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
 */
 
 ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
@@ -795,10 +830,11 @@
    if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
    can be determined from the adler32 value returned by that call of inflate.
    The compressor and decompressor must use exactly the same dictionary (see
-   deflateSetDictionary).  For raw inflate, this function can be called
-   immediately after inflateInit2() or inflateReset() and before any call of
-   inflate() to set the dictionary.  The application must insure that the
-   dictionary that was used for compression is provided.
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
 
      inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
    parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
@@ -808,19 +844,38 @@
    inflate().
 */
 
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+                                             Bytef *dictionary,
+                                             uInt  *dictLength));
+/*
+     Returns the sliding dictionary being maintained by inflate.  dictLength is
+   set to the number of bytes in the dictionary, and that many bytes are copied
+   to dictionary.  dictionary must have enough space, where 32768 bytes is
+   always enough.  If inflateGetDictionary() is called with dictionary equal to
+   Z_NULL, then only the dictionary length is returned, and nothing is copied.
+   Similary, if dictLength is Z_NULL, then it is not set.
+
+     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+   stream state is inconsistent.
+*/
+
 ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
 /*
-     Skips invalid compressed data until a full flush point (see above the
-   description of deflate with Z_FULL_FLUSH) can be found, or until all
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
    available input is skipped.  No output is provided.
 
-     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
-   if no more input was provided, Z_DATA_ERROR if no flush point has been
-   found, or Z_STREAM_ERROR if the stream structure was inconsistent.  In the
-   success case, the application may save the current current value of total_in
-   which indicates where valid compressed data was found.  In the error case,
-   the application may repeatedly call inflateSync, providing more input each
-   time, until success or end of the input data.
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurrences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
 */
 
 ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
@@ -967,12 +1022,13 @@
      See inflateBack() for the usage of these routines.
 
      inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
-   the paramaters are invalid, Z_MEM_ERROR if the internal state could not be
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
    allocated, or Z_VERSION_ERROR if the version of the library does not match
    the version of the header file.
 */
 
-typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef unsigned (*in_func) OF((void FAR *,
+                                z_const unsigned char FAR * FAR *));
 typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
 
 ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
@@ -980,11 +1036,12 @@
                                     out_func out, void FAR *out_desc));
 /*
      inflateBack() does a raw inflate with a single call using a call-back
-   interface for input and output.  This is more efficient than inflate() for
-   file i/o applications in that it avoids copying between the output and the
-   sliding window by simply making the window itself the output buffer.  This
-   function trusts the application to not change the output buffer passed by
-   the output function, at least until inflateBack() returns.
+   interface for input and output.  This is potentially more efficient than
+   inflate() for file i/o applications, in that it avoids copying between the
+   output and the sliding window by simply making the window itself the output
+   buffer.  inflate() can be faster on modern CPUs when used with large
+   buffers.  inflateBack() trusts the application to not change the output
+   buffer passed by the output function, at least until inflateBack() returns.
 
      inflateBackInit() must be called first to allocate the internal state
    and to initialize the state with the user-provided window buffer.
@@ -1093,6 +1150,7 @@
      27-31: 0 (reserved)
  */
 
+#ifndef Z_SOLO
 
                         /* utility functions */
 
@@ -1154,10 +1212,11 @@
 
      uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
    enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
 */
 
-
                         /* gzip file access functions */
 
 /*
@@ -1167,7 +1226,7 @@
    wrapper, documented in RFC 1952, wrapped around a deflate stream.
 */
 
-typedef voidp gzFile;       /* opaque gzip file descriptor */
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
 
 /*
 ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
@@ -1177,13 +1236,28 @@
    a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
    compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
    for fixed code compression as in "wb9F".  (See the description of
-   deflateInit2 for more information about the strategy parameter.) Also "a"
-   can be used instead of "w" to request that the gzip stream that will be
-   written be appended to the file.  "+" will result in an error, since reading
-   and writing to the same gzip file is not supported.
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
 
      gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
 
      gzopen returns NULL if the file could not be opened, if there was
    insufficient memory to allocate the gzFile state, or if an invalid mode was
@@ -1202,7 +1276,11 @@
    descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
    fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
    mode);.  The duplicated descriptor should be saved to avoid a leak, since
-   gzdopen does not close fd if it fails.
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
 
      gzdopen returns NULL if there was insufficient memory to allocate the
    gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
@@ -1240,14 +1318,26 @@
 ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
 /*
      Reads the given number of uncompressed bytes from the compressed file.  If
-   the input file was not in gzip format, gzread copies the given number of
-   bytes into the buffer.
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
 
      After reaching the end of a gzip stream in the input, gzread will continue
-   to read, looking for another gzip stream, or failing that, reading the rest
-   of the input file directly without decompression.  The entire input file
-   will be read if gzread is called until it returns less than the requested
-   len.
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
 
      gzread returns the number of uncompressed bytes actually read, less than
    len for end of file, or -1 for error.
@@ -1261,7 +1351,7 @@
    error.
 */
 
-ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
 /*
      Converts, formats, and writes the arguments to the compressed file under
    control of the format string, as in fprintf.  gzprintf returns the number of
@@ -1306,7 +1396,10 @@
 ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
 /*
      Reads one byte from the compressed file.  gzgetc returns this byte or -1
-   in case of end of file or error.
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
 */
 
 ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
@@ -1402,9 +1495,7 @@
 ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
 /*
      Returns true (1) if file is being copied directly while reading, or false
-   (0) if file is a gzip stream being decompressed.  This state can change from
-   false to true while reading the input file if the end of a gzip stream is
-   reached, but is followed by data that is not another gzip stream.
+   (0) if file is a gzip stream being decompressed.
 
      If the input file is empty, gzdirect() will return true, since the input
    does not contain a gzip stream.
@@ -1413,6 +1504,13 @@
    cause buffers to be allocated to allow reading the file to determine if it
    is a gzip file.  Therefore if gzbuffer() is used, it should be called before
    gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
 */
 
 ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
@@ -1424,7 +1522,8 @@
    must not be called more than once on the same allocation.
 
      gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
-   file operation error, or Z_OK on success.
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
 */
 
 ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
@@ -1462,6 +1561,7 @@
    file that is being written concurrently.
 */
 
+#endif /* !Z_SOLO */
 
                         /* checksum functions */
 
@@ -1497,16 +1597,17 @@
      Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
    and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
    each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
-   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
 */
 
 ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
 /*
      Update a running CRC-32 with the bytes buf[0..len-1] and return the
    updated CRC-32.  If buf is Z_NULL, this function returns the required
-   initial value for the for the crc.  Pre- and post-conditioning (one's
-   complement) is performed within this function so it shouldn't be done by the
-   application.
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
 
    Usage example:
 
@@ -1549,17 +1650,48 @@
                                          const char *version,
                                          int stream_size));
 #define deflateInit(strm, level) \
-        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+        deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
 #define inflateInit(strm) \
-        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+        inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
 #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
         deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+                      (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
 #define inflateInit2(strm, windowBits) \
-        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                      (int)sizeof(z_stream))
 #define inflateBackInit(strm, windowBits, window) \
         inflateBackInit_((strm), (windowBits), (window), \
-                                            ZLIB_VERSION, sizeof(z_stream))
+                      ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+#  ifdef MOZZCONF_H
+#    undef gzgetc
+#    define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : MOZ_Z_gzgetc(g))
+#  else
+#    define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#  endif
+#endif
 
 /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
  * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
@@ -1567,7 +1699,7 @@
  * functions are changed to 64 bits) -- in case these are set on systems
  * without large file support, _LFS64_LARGEFILE must also be true
  */
-#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
+#ifdef Z_LARGE64
    ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
    ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
    ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
@@ -1576,32 +1708,41 @@
    ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
 #endif
 
-#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0
-#  ifdef gzopen
-#    undef gzopen
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    ifdef gzopen
+#      undef gzopen
+#    endif
+#    define gzopen gzopen64
+#    ifdef gzseek
+#      undef gzseek
+#    endif
+#    define gzseek gzseek64
+#    ifdef gztell
+#      undef gztell
+#    endif
+#    define gztell gztell64
+#    ifdef gzoffset
+#      undef gzoffset
+#    endif
+#    define gzoffset gzoffset64
+#    ifdef adler32_combine
+#      undef adler32_combine
+#    endif
+#    define adler32_combine adler32_combine64
+#    ifdef crc32_combine
+#      undef crc32_combine
+#    endif
+#    define crc32_combine crc32_combine64
 #  endif
-#  define gzopen gzopen64
-#  ifdef gzseek
-#    undef gzseek
-#  endif
-#  define gzseek gzseek64
-#  ifdef gztell
-#    undef gztell
-#  endif
-#  define gztell gztell64
-#  ifdef gzoffset
-#    undef gzoffset
-#  endif
-#  define gzoffset gzoffset64
-#  ifdef adler32_combine
-#    undef adler32_combine
-#  endif
-#  define adler32_combine adler32_combine64
-#  ifdef crc32_combine
-#    undef crc32_combine
-#  endif
-#  define crc32_combine crc32_combine64
-#  ifdef _LARGEFILE64_SOURCE
+#  ifndef Z_LARGE64
      ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
      ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
      ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
@@ -1625,6 +1766,13 @@
    ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
 #endif
 
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
 /* hack for buggy compilers */
 #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
     struct internal_state {int dummy;};
@@ -1633,8 +1781,21 @@
 /* undocumented functions */
 ZEXTERN const char   * ZEXPORT zError           OF((int));
 ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
-ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
 ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#  ifndef Z_SOLO
+ZEXTERN int            ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+                                                  const char *format,
+                                                  va_list va));
+#  endif
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/zutil.c b/zutil.c
index 898ed34..23d2ebe 100644
--- a/zutil.c
+++ b/zutil.c
@@ -1,17 +1,20 @@
 /* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
+ * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* @(#) $Id$ */
 
 #include "zutil.h"
+#ifndef Z_SOLO
+#  include "gzguts.h"
+#endif
 
 #ifndef NO_DUMMY_DECL
 struct internal_state      {int dummy;}; /* for buggy compilers */
 #endif
 
-const char * const z_errmsg[10] = {
+z_const char * const z_errmsg[10] = {
 "need dictionary",     /* Z_NEED_DICT       2  */
 "stream end",          /* Z_STREAM_END      1  */
 "",                    /* Z_OK              0  */
@@ -85,27 +88,27 @@
 #ifdef FASTEST
     flags += 1L << 21;
 #endif
-#ifdef STDC
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
 #  ifdef NO_vsnprintf
-        flags += 1L << 25;
+    flags += 1L << 25;
 #    ifdef HAS_vsprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_vsnprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  endif
 #else
-        flags += 1L << 24;
+    flags += 1L << 24;
 #  ifdef NO_snprintf
-        flags += 1L << 25;
+    flags += 1L << 25;
 #    ifdef HAS_sprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  else
 #    ifdef HAS_snprintf_void
-        flags += 1L << 26;
+    flags += 1L << 26;
 #    endif
 #  endif
 #endif
@@ -181,6 +184,7 @@
 }
 #endif
 
+#ifndef Z_SOLO
 
 #ifdef SYS16BIT
 
@@ -316,3 +320,5 @@
 }
 
 #endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/zutil.h b/zutil.h
index 3c8326f..fe9e53c 100644
--- a/zutil.h
+++ b/zutil.h
@@ -1,5 +1,5 @@
 /* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2010 Jean-loup Gailly.
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
@@ -13,7 +13,7 @@
 #ifndef ZUTIL_H
 #define ZUTIL_H
 
-#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
+#ifdef HAVE_HIDDEN
 #  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
 #else
 #  define ZLIB_INTERNAL
@@ -21,7 +21,7 @@
 
 #include "zlib.h"
 
-#ifdef STDC
+#if defined(STDC) && !defined(Z_SOLO)
 #  if !(defined(_WIN32_WCE) && defined(_MSC_VER))
 #    include <stddef.h>
 #  endif
@@ -44,6 +44,10 @@
 #  endif
 #endif
 
+#ifdef Z_SOLO
+   typedef long ptrdiff_t;  /* guess -- will be caught if guess is wrong */
+#endif
+
 #ifndef local
 #  define local static
 #endif
@@ -55,13 +59,13 @@
 typedef ush FAR ushf;
 typedef unsigned long  ulg;
 
-extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
 /* (size given to avoid silly warnings with Visual C++) */
 
 #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
 
 #define ERR_RETURN(strm,err) \
-  return (strm->msg = (char*)ERR_MSG(err), (err))
+  return (strm->msg = ERR_MSG(err), (err))
 /* To be used only when the state is known to be valid */
 
         /* common constants */
@@ -93,16 +97,18 @@
 
 #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
 #  define OS_CODE  0x00
-#  if defined(__TURBOC__) || defined(__BORLANDC__)
-#    if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
-       /* Allow compilation with ANSI keywords only enabled */
-       void _Cdecl farfree( void *block );
-       void *_Cdecl farmalloc( unsigned long nbytes );
-#    else
-#      include <alloc.h>
+#  ifndef Z_SOLO
+#    if defined(__TURBOC__) || defined(__BORLANDC__)
+#      if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+         /* Allow compilation with ANSI keywords only enabled */
+         void _Cdecl farfree( void *block );
+         void *_Cdecl farmalloc( unsigned long nbytes );
+#      else
+#        include <alloc.h>
+#      endif
+#    else /* MSC or DJGPP */
+#      include <malloc.h>
 #    endif
-#  else /* MSC or DJGPP */
-#    include <malloc.h>
 #  endif
 #endif
 
@@ -122,18 +128,20 @@
 
 #ifdef OS2
 #  define OS_CODE  0x06
-#  ifdef M_I86
+#  if defined(M_I86) && !defined(Z_SOLO)
 #    include <malloc.h>
 #  endif
 #endif
 
 #if defined(MACOS) || defined(TARGET_OS_MAC)
 #  define OS_CODE  0x07
-#  if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-#    include <unix.h> /* for fdopen */
-#  else
-#    ifndef fdopen
-#      define fdopen(fd,mode) NULL /* No fdopen() */
+#  ifndef Z_SOLO
+#    if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+#      include <unix.h> /* for fdopen */
+#    else
+#      ifndef fdopen
+#        define fdopen(fd,mode) NULL /* No fdopen() */
+#      endif
 #    endif
 #  endif
 #endif
@@ -174,14 +182,15 @@
 #  endif
 #endif
 
-#if defined(__BORLANDC__)
+#if defined(__BORLANDC__) && !defined(MSDOS)
   #pragma warn -8004
   #pragma warn -8008
   #pragma warn -8066
 #endif
 
 /* provide prototypes for these when building zlib without LFS */
-#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+#if !defined(_WIN32) && \
+    (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
 #endif
@@ -198,42 +207,7 @@
 
          /* functions */
 
-#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#if defined(__CYGWIN__)
-#  ifndef HAVE_VSNPRINTF
-#    define HAVE_VSNPRINTF
-#  endif
-#endif
-#ifndef HAVE_VSNPRINTF
-#  ifdef MSDOS
-     /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
-        but for now we just assume it doesn't. */
-#    define NO_vsnprintf
-#  endif
-#  ifdef __TURBOC__
-#    define NO_vsnprintf
-#  endif
-#  ifdef WIN32
-     /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
-#    if !defined(vsnprintf) && !defined(NO_vsnprintf)
-#      if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
-#         define vsnprintf _vsnprintf
-#      endif
-#    endif
-#  endif
-#  ifdef __SASC
-#    define NO_vsnprintf
-#  endif
-#endif
-#ifdef VMS
-#  define NO_vsnprintf
-#endif
-
-#if defined(pyr)
+#if defined(pyr) || defined(Z_SOLO)
 #  define NO_MEMCPY
 #endif
 #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
@@ -282,14 +256,19 @@
 #  define Tracecv(c,x)
 #endif
 
-
-voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
-                        unsigned size));
-void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+#ifndef Z_SOLO
+   voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+                                    unsigned size));
+   void ZLIB_INTERNAL zcfree  OF((voidpf opaque, voidpf ptr));
+#endif
 
 #define ZALLOC(strm, items, size) \
            (*((strm)->zalloc))((strm)->opaque, (items), (size))
 #define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
 #define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
 
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+                    (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
 #endif /* ZUTIL_H */