diff options
-rw-r--r-- | Android.bp | 309 | ||||
-rw-r--r-- | CMakeLists.txt | 60 | ||||
-rw-r--r-- | CleanSpec.mk | 49 | ||||
-rw-r--r-- | METADATA | 15 | ||||
-rw-r--r-- | MODULE_LICENSE_BSD_LIKE | 0 | ||||
-rw-r--r-- | OWNERS.android | 1 | ||||
-rw-r--r-- | TEST_MAPPING | 27 | ||||
-rw-r--r-- | contrib/minigzip/minigzip.c | 651 | ||||
-rw-r--r-- | libz.map.txt | 151 | ||||
-rw-r--r-- | zconf.h | 4 | ||||
-rw-r--r-- | zlib.h | 63 |
11 files changed, 1330 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..6895ea3 --- /dev/null +++ b/Android.bp @@ -0,0 +1,309 @@ +package { + default_applicable_licenses: ["external_zlib_license"], +} + +license { + name: "external_zlib_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-BSD", + "SPDX-license-identifier-Zlib", + ], + license_text: [ + "LICENSE", + ], +} + +srcs_opt = [ + "adler32_simd.c", + // See https://chromium-review.googlesource.com/749732. + // TODO: causes `atest org.apache.harmony.tests.java.util.zip.DeflaterTest` failures. + // "contrib/optimizations/inffast_chunk.c", + // "contrib/optimizations/inflate.c", + // This file doesn't build for non-neon, so it can't be in the main srcs. + "crc32_simd.c", +] + +cflags_arm = [ + // Testing with zlib_bench shows -O3 is a win for ARM but a bit of a wash + // for x86, so match the BUILD file in only enabling this for ARM. + "-O3", + // We need a non-NEON libz.a for the NDK, and cpu_features.c won't build + // without this. + "-DCPU_NO_SIMD", +] +cflags_arm_neon = [ + // Undo the -DCPU_NO_SIMD from the generic (non-NEON) ARM flags. + "-UCPU_NO_SIMD", + // We no longer support non-Neon platform builds, but the NDK just has one libz. + "-DADLER32_SIMD_NEON", + // TODO: causes `atest org.apache.harmony.tests.java.util.zip.DeflaterTest` failures. + // "-DINFLATE_CHUNK_SIMD_NEON", + // HWCAP_CRC32 is checked at runtime, so it's okay to turn crc32 + // acceleration on for both 32- and 64-bit. + "-DCRC32_ARMV8_CRC32", +] +cflags_arm64 = cflags_arm + cflags_arm_neon + +// The *host* x86 configuration (with *lower* CPU feature requirements). +cflags_x86 = [ + // See ARMV8_OS_LINUX above. + "-DX86_NOT_WINDOWS", + // TODO: see arm above. + // "-DINFLATE_CHUNK_SIMD_SSE2", + // Android's host CPU feature requirements are *lower* than the + // corresponding device CPU feature requirements, so it's easier to just + // say "no SIMD for you" rather than specificially disable SSSE3. + // We should have a conversation about that, but not until we at least have + // data on how many Studio users have CPUs that don't make the grade... + // https://issuetracker.google.com/171235570 + "-DCPU_NO_SIMD", +] +// The *device* x86 configuration (with *higher* CPU feature requirements). +cflags_android_x86 = [ + // Android's x86/x86-64 ABI includes SSE2 and SSSE3. + "-UCPU_NO_SIMD", + "-DADLER32_SIMD_SSSE3", + // PCLMUL isn't in the ABI, but it won't actually be used unless CPUID + // reports that the processor really does have the instruction. + "-mpclmul", + "-DCRC32_SIMD_SSE42_PCLMUL", +] +srcs_x86 = [ + "crc_folding.c", + "fill_window_sse.c", +] + srcs_opt + +// This optimization is applicable to arm64 and x86-64. +cflags_64 = ["-DINFLATE_CHUNK_READ_64LE"] + +libz_srcs = [ + "adler32.c", + "compress.c", + "cpu_features.c", + "crc32.c", + "deflate.c", + "gzclose.c", + "gzlib.c", + "gzread.c", + "gzwrite.c", + "infback.c", + "inffast.c", + "inflate.c", + "inftrees.c", + "trees.c", + "uncompr.c", + "zutil.c", +] + +cc_defaults { + name: "libz_defaults", + + cflags: [ + // We do support hidden visibility, so turn that on. + "-DHAVE_HIDDEN", + // We do support const, so turn that on. + "-DZLIB_CONST", + // Enable -O3 as per chromium. + "-O3", + "-Wall", + "-Werror", + "-Wno-unused", + "-Wno-unused-parameter", + ], + stl: "none", + export_include_dirs: ["."], + srcs: libz_srcs, + + arch: { + arm: { + // TODO: This is to work around b/24465209. Remove after root cause + // is fixed. + pack_relocations: false, + ldflags: ["-Wl,--hash-style=both"], + + cflags: cflags_arm, + neon: { + cflags: cflags_arm_neon, + srcs: srcs_opt, + }, + }, + arm64: { + cflags: cflags_arm64 + cflags_64, + srcs: srcs_opt, + }, + x86: { + cflags: cflags_x86, + srcs: srcs_x86, + }, + x86_64: { + cflags: cflags_x86 + cflags_64, + srcs: srcs_x86, + }, + }, + target: { + android_arm: { + cflags: [ + // Since we're building for the platform, we claim to be Linux rather than + // Android so we use getauxval() directly instead of the NDK + // android_getCpuFeatures which isn't available to us anyway. + "-DARMV8_OS_LINUX", + ], + }, + android_x86: { + cflags: cflags_android_x86, + }, + android_x86_64: { + cflags: cflags_android_x86, + }, + darwin_arm64: { + cflags: [ + "-DARMV8_OS_MACOS", + ], + }, + linux_arm64: { + cflags: [ + // Since we're building for the platform, we claim to be Linux rather than + // Android so we use getauxval() directly instead of the NDK + // android_getCpuFeatures which isn't available to us anyway. + "-DARMV8_OS_LINUX", + ], + }, + }, +} + +cc_library { + name: "libz", + defaults: ["libz_defaults"], + + host_supported: true, + unique_host_soname: true, + static_ndk_lib: true, + + vendor_available: true, + product_available: true, + vndk: { + enabled: true, + support_system_process: true, + }, + ramdisk_available: true, + vendor_ramdisk_available: true, + recovery_available: true, + native_bridge_supported: true, + + target: { + linux_bionic: { + enabled: true, + }, + windows: { + enabled: true, + }, + }, + + stubs: { + versions: [ + "29", + "30", + ], + symbol_file: "libz.map.txt", + }, +} + +// A more stable build of libz. Build configuration of this library should be +// the same for different targets. This is only used by imgdiff. + +cc_library { + name: "libz_stable", + visibility: [ + "//bootable/recovery/applypatch", + "//bootable/recovery/tests", + ], + cflags: [ + // We do support hidden visibility, so turn that on. + "-DHAVE_HIDDEN", + // We do support const, so turn that on. + "-DZLIB_CONST", + // Enable -O3 as per chromium + "-O3", + "-Wall", + "-Werror", + "-Wno-unused", + "-Wno-unused-parameter", + ], + stl: "none", + export_include_dirs: ["."], + srcs: libz_srcs, + + host_supported: true, + vendor_available: true, + recovery_available: true, +} + +cc_binary_host { + name: "minigzip", + srcs: ["contrib/minigzip/minigzip.c"], + cflags: [ + "-Wall", + "-Werror", + "-DUSE_MMAP", + ], + static_libs: ["libz"], + stl: "none", +} + +cc_binary { + name: "zlib_bench", + srcs: ["contrib/bench/zlib_bench.cc"], + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + ], + host_supported: true, + shared_libs: ["libz"], + // We build zlib_bench32 and zlib_bench64 so it's easy to test LP32. + compile_multilib: "both", + multilib: { + lib32: { + suffix: "32", + }, + lib64: { + suffix: "64", + }, + }, +} + +cc_test { + name: "zlib_tests", + srcs: [ + "contrib/tests/infcover.cc", + "contrib/tests/utils_unittest.cc", + "google/compression_utils_portable.cc", + ], + include_dirs: [ + "external/zlib/google", + // These tests include "gtest.h" rather than the usual "gtest/gtest.h". + "external/googletest/googletest/include/gtest/", + ], + shared_libs: ["libz"], + host_supported: true, + test_suites: ["device-tests"], +} + +ndk_headers { + name: "libz_headers", + from: "", + to: "", + srcs: [ + "zconf.h", + "zlib.h", + ], + license: "LICENSE", +} + +ndk_library { + name: "libz", + symbol_file: "libz.map.txt", + first_version: "9", + unversioned_until: "current", +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..08c8bd5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Build zlib for Windows x86_64 using MSVC. +# + +project(libz LANGUAGES C) +cmake_minimum_required(VERSION 3.18.1) + +add_library(libz STATIC + # Optimizations for x86-64 + adler32_simd.c + crc32_simd.c + crc_folding.c + fill_window_sse.c + + # Common sources + adler32.c + compress.c + cpu_features.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + infback.c + inffast.c + inflate.c + inftrees.c + trees.c + uncompr.c + zutil.c +) + +target_compile_definitions(libz PRIVATE + # Enable optimizations: cpu_features.c will enable them at runtime using __cpuid. + ADLER32_SIMD_SSSE3 + CRC32_SIMD_SSE42_PCLMUL + INFLATE_CHUNK_READ_64LE + + X86_WINDOWS + ZLIB_CONST +) + +set(out ${CMAKE_CURRENT_BINARY_DIR}) +configure_file(zconf.h ${out}/dist/include/zconf.h COPYONLY) +configure_file(zlib.h ${out}/dist/include/zlib.h COPYONLY) diff --git a/CleanSpec.mk b/CleanSpec.mk new file mode 100644 index 0000000..b84e1b6 --- /dev/null +++ b/CleanSpec.mk @@ -0,0 +1,49 @@ +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..ffc16d3 --- /dev/null +++ b/METADATA @@ -0,0 +1,15 @@ +name: "zlib" +description: "The Chromium fork of the zlib compression library." +third_party { + url { + type: GIT + value: "https://chromium.googlesource.com/chromium/src/third_party/zlib/" + } + version: "cb89dc607cd4b85d98867f14216c3370109be64d" + license_type: NOTICE + last_upgrade_date { + year: 2022 + month: 3 + day: 23 + } +} diff --git a/MODULE_LICENSE_BSD_LIKE b/MODULE_LICENSE_BSD_LIKE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/MODULE_LICENSE_BSD_LIKE diff --git a/OWNERS.android b/OWNERS.android new file mode 100644 index 0000000..7529cb9 --- /dev/null +++ b/OWNERS.android @@ -0,0 +1 @@ +include platform/system/core:/janitors/OWNERS diff --git a/TEST_MAPPING b/TEST_MAPPING new file mode 100644 index 0000000..b2c8b36 --- /dev/null +++ b/TEST_MAPPING @@ -0,0 +1,27 @@ +{ + "presubmit": [ + { + "name": "puffin_unittest" + }, + { + "name": "recovery_unit_test" + }, + { + "name": "update_engine_unittests" + }, + { + "name": "ziparchive-tests" + }, + { + "name": "zlib_tests" + }, + { + "name": "CtsLibcoreTestCases", + "options": [ + { + "include-filter": "org.apache.harmony.tests.java.util.zip" + } + ] + } + ] +} diff --git a/contrib/minigzip/minigzip.c b/contrib/minigzip/minigzip.c new file mode 100644 index 0000000..e22fb08 --- /dev/null +++ b/contrib/minigzip/minigzip.c @@ -0,0 +1,651 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include <stdio.h> + +#ifdef STDC +# include <string.h> +# include <stdlib.h> +#endif + +#ifdef USE_MMAP +# include <sys/types.h> +# include <sys/mman.h> +# include <sys/stat.h> +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include <fcntl.h> +# include <io.h> +# ifdef UNDER_CE +# include <stdlib.h> +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include <windows.h> +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +#ifdef Z_SOLO +/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ + +#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) +# include <unistd.h> /* for unlink() */ +#endif + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(q, p) + void *q, *p; +{ + (void)q; + free(p); +} + +typedef struct gzFile_s { + FILE *file; + int write; + int err; + char *msg; + z_stream strm; +} *gzFile; + +gzFile gzopen OF((const char *, const char *)); +gzFile gzdopen OF((int, const char *)); +gzFile gz_open OF((const char *, int, const char *)); + +gzFile gzopen(path, mode) +const char *path; +const char *mode; +{ + return gz_open(path, -1, mode); +} + +gzFile gzdopen(fd, mode) +int fd; +const char *mode; +{ + return gz_open(NULL, fd, mode); +} + +gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gzFile gz; + int ret; + + gz = malloc(sizeof(struct gzFile_s)); + if (gz == NULL) + return NULL; + gz->write = strchr(mode, 'w') != NULL; + gz->strm.zalloc = myalloc; + gz->strm.zfree = myfree; + gz->strm.opaque = Z_NULL; + if (gz->write) + ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); + else { + gz->strm.next_in = 0; + gz->strm.avail_in = Z_NULL; + ret = inflateInit2(&(gz->strm), 15 + 16); + } + if (ret != Z_OK) { + free(gz); + return NULL; + } + gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : + fopen(path, gz->write ? "wb" : "rb"); + if (gz->file == NULL) { + gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); + free(gz); + return NULL; + } + gz->err = 0; + gz->msg = ""; + return gz; +} + +int gzwrite OF((gzFile, const void *, unsigned)); + +int gzwrite(gz, buf, len) + gzFile gz; + const void *buf; + unsigned len; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL || !gz->write) + return 0; + strm = &(gz->strm); + strm->next_in = (void *)buf; + strm->avail_in = len; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_NO_FLUSH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + return len; +} + +int gzread OF((gzFile, void *, unsigned)); + +int gzread(gz, buf, len) + gzFile gz; + void *buf; + unsigned len; +{ + int ret; + unsigned got; + unsigned char in[1]; + z_stream *strm; + + if (gz == NULL || gz->write) + return 0; + if (gz->err) + return 0; + strm = &(gz->strm); + strm->next_out = (void *)buf; + strm->avail_out = len; + do { + got = fread(in, 1, 1, gz->file); + if (got == 0) + break; + strm->next_in = in; + strm->avail_in = 1; + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_DATA_ERROR) { + gz->err = Z_DATA_ERROR; + gz->msg = strm->msg; + return 0; + } + if (ret == Z_STREAM_END) + inflateReset(strm); + } while (strm->avail_out); + return len - strm->avail_out; +} + +int gzclose OF((gzFile)); + +int gzclose(gz) + gzFile gz; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL) + return Z_STREAM_ERROR; + strm = &(gz->strm); + if (gz->write) { + strm->next_in = Z_NULL; + strm->avail_in = 0; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_FINISH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + deflateEnd(strm); + } + else + inflateEnd(strm); + fclose(gz->file); + free(gz); + return Z_OK; +} + +const char *gzerror OF((gzFile, int *)); + +const char *gzerror(gz, err) + gzFile gz; + int *err; +{ + *err = gz->err; + return gz->msg; +} + +#endif + +static char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); +#else + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); +#endif + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + unsigned len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf, sizeof(buf), "%s", file); +#else + strcpy(buf, file); +#endif + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); +#else + strcat(infile, GZ_SUFFIX); +#endif + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outmode, sizeof(outmode), "%s", "wb6 "); +#else + strcpy(outmode, "wb6 "); +#endif + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/libz.map.txt b/libz.map.txt new file mode 100644 index 0000000..850bbf8 --- /dev/null +++ b/libz.map.txt @@ -0,0 +1,151 @@ +# This file is copied from src/zlib.map and annotated with comments for the NDK +# stub library generation script. +ZLIB_1.2.0 { + global: + compressBound; + deflateBound; + inflateBack; + inflateBackEnd; + inflateBackInit_; + inflateCopy; + local: + deflate_copyright; # var + inflate_copyright; # var + inflate_fast; + inflate_table; + zcalloc; + zcfree; + z_errmsg; # var + gz_error; + gz_intmax; + _*; +}; + +ZLIB_1.2.0.2 { + gzclearerr; + gzungetc; + zlibCompileFlags; +} ZLIB_1.2.0; + +ZLIB_1.2.0.8 { + deflatePrime; +} ZLIB_1.2.0.2; + +ZLIB_1.2.2 { + adler32_combine; + crc32_combine; + deflateSetHeader; + inflateGetHeader; +} ZLIB_1.2.0.8; + +ZLIB_1.2.2.3 { + deflateTune; + gzdirect; +} ZLIB_1.2.2; + +ZLIB_1.2.2.4 { + inflatePrime; +} ZLIB_1.2.2.3; + +ZLIB_1.2.3.3 { + adler32_combine64; + crc32_combine64; + gzopen64; + gzseek64; + gztell64; + inflateUndermine; +} ZLIB_1.2.2.4; + +ZLIB_1.2.3.4 { + inflateReset2; + inflateMark; +} ZLIB_1.2.3.3; + +ZLIB_1.2.3.5 { + gzbuffer; + gzoffset; + gzoffset64; + gzclose_r; + gzclose_w; +} ZLIB_1.2.3.4; + +ZLIB_1.2.5.1 { + deflatePending; +} ZLIB_1.2.3.5; + +ZLIB_1.2.5.2 { + deflateResetKeep; + gzgetc_; + inflateResetKeep; +} ZLIB_1.2.5.1; + +ZLIB_1.2.7.1 { # introduced=19 + inflateGetDictionary; + gzvprintf; +} ZLIB_1.2.5.2; + +ZLIB_1.2.9 { # introduced=28 + inflateCodesUsed; + inflateValidate; + uncompress2; + gzfread; + gzfwrite; + deflateGetDictionary; + adler32_z; + crc32_z; +} ZLIB_1.2.7.1; + +# These were all exposed by the old NDK stub library. Unclear if they still +# should be, but at least some of them are marked as being exported in zlib.h +# and the tree doesn't build without them. +ZLIB_NDK { + _dist_code; + _length_code; + _tr_align; + _tr_flush_bits; # introduced=21 + _tr_flush_block; + _tr_init; + _tr_stored_block; + _tr_tally; + adler32; + compress2; + compress; + crc32; + deflate; + deflateCopy; + deflateEnd; + deflateInit2_; + deflateInit_; + deflateParams; + deflateReset; + deflateSetDictionary; + get_crc_table; + gzclose; + gzdopen; + gzeof; + gzerror; + gzflush; + gzgetc; + gzgets; + gzopen; + gzprintf; + gzputc; + gzputs; + gzread; + gzrewind; + gzseek; + gzsetparams; + gztell; + gzwrite; + inflate; + inflateEnd; + inflateInit2_; + inflateInit_; + inflateReset; + inflateSetDictionary; + inflateSync; + inflateSyncPoint; + uncompress; + zError; + zlibVersion; +}; @@ -8,6 +8,10 @@ #ifndef ZCONF_H #define ZCONF_H +// ANDROID CHNAGE: Upstream chromium renames all the functions; we don't want +// that. +#define CHROMIUM_ZLIB_NO_CHROMECONF + /* * This library is also built as a part of AOSP, which does not need to include * chromeconf.h. This config does not want chromeconf.h, so it can set this @@ -45,6 +45,49 @@ extern "C" { #define ZLIB_VER_SUBREVISION 0 /* + * In Android's NDK we have one zlib.h for all the versions. + * zlib users tend to use ZLIB_VERNUM to check API availability, + * so we need to translate __ANDROID_API__ appropriately. + * + * ZLIB_1.2.7.1 and ZLIB_1.2.9 are the only API changes in the NDK's + * supported range of API levels. + * + * jb-mr2-dev (18): 1.2.7 (but not 1.2.7.1, where the APIs were added!) + * https://android.googlesource.com/platform/external/zlib/+/refs/heads/jb-mr2-dev/src/zlib.h + * kitkat-dev (19): 1.2.8 + * https://android.googlesource.com/platform/external/zlib/+/refs/heads/kitkat-dev/src/zlib.h + * + * oreo-mr1-dev (27): 1.2.8 + * https://android.googlesource.com/platform/external/zlib/+/refs/heads/oreo-mr1-dev/src/zlib.h + * pie-dev (28): 1.2.11 + * https://android.googlesource.com/platform/external/zlib/+/refs/heads/pie-dev/src/zlib.h + * + * So: + * >= 28 --> 1.2.11 + * >= 19 --> 1.2.8 + * < 19 --> 1.2.7 + */ +#if defined(__ANDROID__) +# if __ANDROID_API__ >= 28 + /* Already okay. */ +# elif __ANDROID_API__ >= 19 +# undef ZLIB_VERSION +# define ZLIB_VERSION "1.2.8" +# undef ZLIB_VERNUM +# define ZLIB_VERNUM 0x1280 +# undef ZLIB_VER_REVISION +# define ZLIB_VER_REVISION 8 +# else +# undef ZLIB_VERSION +# define ZLIB_VERSION "1.2.6" +# undef ZLIB_VERNUM +# define ZLIB_VERNUM 0x1260 +# undef ZLIB_VER_REVISION +# define ZLIB_VER_REVISION 6 +# endif +#endif + +/* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) @@ -652,9 +695,11 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); +#endif /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied @@ -904,9 +949,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 19 ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); +#endif /* 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 @@ -1280,8 +1327,10 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen)); +#endif /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of @@ -1417,8 +1466,10 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); Z_STREAM_ERROR. */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, gzFile file)); +#endif /* Read up to nitems items of size size from file to buf, otherwise operating as gzread() does. This duplicates the interface of stdio's fread(), with @@ -1451,8 +1502,10 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, z_size_t nitems, gzFile file)); +#endif /* gzfwrite() writes nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If @@ -1704,8 +1757,10 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, z_size_t len)); +#endif /* Same as adler32(), but with a size_t length. */ @@ -1739,8 +1794,10 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, z_size_t len)); +#endif /* Same as crc32(), but with a size_t length. */ @@ -1912,8 +1969,12 @@ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +#endif +#if !defined(__ANDROID__) || __ANDROID_API__ >= 28 ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +#endif ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) @@ -1922,9 +1983,11 @@ ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO +# if !defined(__ANDROID__) || __ANDROID_API__ >= 19 ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, const char *format, va_list va)); +# endif # endif #endif |