Add a simple MappedFile to libbase and switch fastboot and libziparchive over.
This allows us to remove libziparchive's dependency on libutils. Bug: http://b/79112958 Test: ran libbase and libziparchive tests, ran fastboot manually Change-Id: I95c651976dad222863e5b8c37d4514b778f5dce7
This commit is contained in:
parent
7a08c896dd
commit
e8f4b14301
13 changed files with 224 additions and 69 deletions
|
@ -47,6 +47,7 @@ cc_defaults {
|
|||
"chrono_utils.cpp",
|
||||
"file.cpp",
|
||||
"logging.cpp",
|
||||
"mapped_file.cpp",
|
||||
"parsenetaddress.cpp",
|
||||
"properties.cpp",
|
||||
"quick_exit.cpp",
|
||||
|
@ -124,6 +125,7 @@ cc_test {
|
|||
"file_test.cpp",
|
||||
"logging_test.cpp",
|
||||
"macros_test.cpp",
|
||||
"mapped_file_test.cpp",
|
||||
"parsedouble_test.cpp",
|
||||
"parseint_test.cpp",
|
||||
"parsenetaddress_test.cpp",
|
||||
|
|
74
base/include/android-base/mapped_file.h
Normal file
74
base/include/android-base/mapped_file.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "android-base/macros.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
/**
|
||||
* A region of a file mapped into memory.
|
||||
*/
|
||||
class MappedFile {
|
||||
public:
|
||||
/**
|
||||
* Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
|
||||
* `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
|
||||
* will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
|
||||
*/
|
||||
static std::unique_ptr<MappedFile> FromFd(int fd, off64_t offset, size_t length, int prot);
|
||||
|
||||
/**
|
||||
* Removes the mapping.
|
||||
*/
|
||||
~MappedFile();
|
||||
|
||||
char* data() { return base_ + offset_; }
|
||||
size_t size() { return size_; }
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
|
||||
|
||||
char* base_;
|
||||
size_t size_;
|
||||
|
||||
size_t offset_;
|
||||
|
||||
#if defined(_WIN32)
|
||||
MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
|
||||
: base_(base), size_(size), offset_(offset), handle_(handle) {}
|
||||
HANDLE handle_;
|
||||
#else
|
||||
MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
71
base/mapped_file.cpp
Normal file
71
base/mapped_file.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#include "android-base/mapped_file.h"
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
static off64_t InitPageSize() {
|
||||
#if defined(_WIN32)
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwAllocationGranularity;
|
||||
#else
|
||||
return sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<MappedFile> MappedFile::FromFd(int fd, off64_t offset, size_t length, int prot) {
|
||||
static off64_t page_size = InitPageSize();
|
||||
size_t slop = offset % page_size;
|
||||
off64_t file_offset = offset - slop;
|
||||
off64_t file_length = length + slop;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle =
|
||||
CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), nullptr,
|
||||
(prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
|
||||
if (handle == nullptr) return nullptr;
|
||||
void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
|
||||
file_offset, file_length);
|
||||
if (base == nullptr) {
|
||||
CloseHandle(handle);
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<MappedFile>(
|
||||
new MappedFile{static_cast<char*>(base), length, slop, handle});
|
||||
#else
|
||||
void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
|
||||
if (base == MAP_FAILED) return nullptr;
|
||||
return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
|
||||
#endif
|
||||
}
|
||||
|
||||
MappedFile::~MappedFile() {
|
||||
#if defined(_WIN32)
|
||||
if (base_ != nullptr) UnmapViewOfFile(base_);
|
||||
if (handle_ != nullptr) CloseHandle(handle_);
|
||||
#else
|
||||
if (base_ != nullptr) munmap(base_, size_);
|
||||
#endif
|
||||
|
||||
base_ = nullptr;
|
||||
offset_ = size_ = 0;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
40
base/mapped_file_test.cpp
Normal file
40
base/mapped_file_test.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#include "android-base/mapped_file.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "android-base/file.h"
|
||||
#include "android-base/test_utils.h"
|
||||
#include "android-base/unique_fd.h"
|
||||
|
||||
TEST(mapped_file, smoke) {
|
||||
TemporaryFile tf;
|
||||
ASSERT_TRUE(tf.fd != -1);
|
||||
ASSERT_TRUE(android::base::WriteStringToFd("hello world", tf.fd));
|
||||
|
||||
auto m = android::base::MappedFile::FromFd(tf.fd, 3, 2, PROT_READ);
|
||||
ASSERT_EQ(2u, m->size());
|
||||
ASSERT_EQ('l', m->data()[0]);
|
||||
ASSERT_EQ('o', m->data()[1]);
|
||||
}
|
|
@ -79,8 +79,8 @@ using android::base::Split;
|
|||
using android::base::Trim;
|
||||
using android::base::unique_fd;
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#if defined(_WIN32)
|
||||
#define O_CLOEXEC O_NOINHERIT
|
||||
#endif
|
||||
|
||||
static const char* serial = nullptr;
|
||||
|
|
|
@ -41,10 +41,10 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/mapped_file.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <utils/FileMap.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "transport.h"
|
||||
|
@ -467,15 +467,14 @@ RetCode FastBootDriver::SendBuffer(int fd, size_t size) {
|
|||
|
||||
while (remaining) {
|
||||
// Memory map the file
|
||||
android::FileMap filemap;
|
||||
size_t len = std::min(remaining, MAX_MAP_SIZE);
|
||||
|
||||
if (!filemap.create(NULL, fd, offset, len, true)) {
|
||||
auto mapping{android::base::MappedFile::FromFd(fd, offset, len, PROT_READ)};
|
||||
if (!mapping) {
|
||||
error_ = "Creating filemap failed";
|
||||
return IO_ERROR;
|
||||
}
|
||||
|
||||
if ((ret = SendBuffer(filemap.getDataPtr(), len))) {
|
||||
if ((ret = SendBuffer(mapping->data(), mapping->size()))) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,14 +84,6 @@ cc_library {
|
|||
"libz",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
shared_libs: [
|
||||
"libutils",
|
||||
],
|
||||
},
|
||||
host: {
|
||||
static_libs: ["libutils"],
|
||||
},
|
||||
linux_bionic: {
|
||||
enabled: true,
|
||||
},
|
||||
|
|
|
@ -14,17 +14,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Read-only access to Zip archives, with minimal heap allocation.
|
||||
*/
|
||||
#ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
|
||||
#define LIBZIPARCHIVE_ZIPARCHIVE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/Compat.h>
|
||||
|
||||
/* Zip compression methods we support */
|
||||
enum {
|
||||
|
@ -273,5 +272,3 @@ class Reader {
|
|||
int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
||||
const uint32_t uncompressed_length, Writer* writer, uint64_t* crc_out);
|
||||
} // namespace zip_archive
|
||||
|
||||
#endif // LIBZIPARCHIVE_ZIPARCHIVE_H_
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LIBZIPARCHIVE_ZIPWRITER_H_
|
||||
#define LIBZIPARCHIVE_ZIPWRITER_H_
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
@ -25,7 +24,6 @@
|
|||
#include <vector>
|
||||
|
||||
#include "android-base/macros.h"
|
||||
#include "utils/Compat.h"
|
||||
|
||||
struct z_stream_s;
|
||||
typedef struct z_stream_s z_stream;
|
||||
|
@ -183,5 +181,3 @@ class ZipWriter {
|
|||
std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
|
||||
std::vector<uint8_t> buffer_;
|
||||
};
|
||||
|
||||
#endif /* LIBZIPARCHIVE_ZIPWRITER_H_ */
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
|
||||
#define LOG_TAG "ziparchive"
|
||||
|
||||
#include <assert.h>
|
||||
#include "ziparchive/zip_archive.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -40,12 +41,10 @@
|
|||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/macros.h> // TEMP_FAILURE_RETRY may or may not be in unistd
|
||||
#include <android-base/mapped_file.h>
|
||||
#include <android-base/memory.h>
|
||||
#include <android-base/utf8.h>
|
||||
#include <log/log.h>
|
||||
#include <utils/Compat.h>
|
||||
#include <utils/FileMap.h>
|
||||
#include "ziparchive/zip_archive.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#include "entry_name_utils-inl.h"
|
||||
|
@ -58,12 +57,6 @@ using android::base::get_unaligned;
|
|||
// specified in the local file header and the central directory.
|
||||
static const bool kCrcChecksEnabled = false;
|
||||
|
||||
// This is for windows. If we don't open a file in binary mode, weird
|
||||
// things will happen.
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
// The maximum number of bytes to scan backwards for the EOCD start.
|
||||
static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
|
||||
|
||||
|
@ -196,7 +189,7 @@ ZipArchive::ZipArchive(const int fd, bool assume_ownership)
|
|||
close_file(assume_ownership),
|
||||
directory_offset(0),
|
||||
central_directory(),
|
||||
directory_map(new android::FileMap()),
|
||||
directory_map(),
|
||||
num_entries(0),
|
||||
hash_table_size(0),
|
||||
hash_table(nullptr) {
|
||||
|
@ -212,7 +205,7 @@ ZipArchive::ZipArchive(void* address, size_t length)
|
|||
close_file(false),
|
||||
directory_offset(0),
|
||||
central_directory(),
|
||||
directory_map(new android::FileMap()),
|
||||
directory_map(),
|
||||
num_entries(0),
|
||||
hash_table_size(0),
|
||||
hash_table(nullptr) {}
|
||||
|
@ -303,8 +296,7 @@ static int32_t MapCentralDirectory0(const char* debug_file_name, ZipArchive* arc
|
|||
* in archive.
|
||||
*/
|
||||
|
||||
if (!archive->InitializeCentralDirectory(debug_file_name,
|
||||
static_cast<off64_t>(eocd->cd_start_offset),
|
||||
if (!archive->InitializeCentralDirectory(static_cast<off64_t>(eocd->cd_start_offset),
|
||||
static_cast<size_t>(eocd->cd_size))) {
|
||||
ALOGE("Zip: failed to intialize central directory.\n");
|
||||
return kMmapFailed;
|
||||
|
@ -823,7 +815,7 @@ class MemoryWriter : public zip_archive::Writer {
|
|||
|
||||
virtual bool Append(uint8_t* buf, size_t buf_size) override {
|
||||
if (bytes_written_ + buf_size > size_) {
|
||||
ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", size_,
|
||||
ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
|
||||
bytes_written_ + buf_size);
|
||||
return false;
|
||||
}
|
||||
|
@ -910,7 +902,7 @@ class FileWriter : public zip_archive::Writer {
|
|||
|
||||
virtual bool Append(uint8_t* buf, size_t buf_size) override {
|
||||
if (total_bytes_written_ + buf_size > declared_length_) {
|
||||
ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", declared_length_,
|
||||
ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", declared_length_,
|
||||
total_bytes_written_ + buf_size);
|
||||
return false;
|
||||
}
|
||||
|
@ -919,7 +911,7 @@ class FileWriter : public zip_archive::Writer {
|
|||
if (result) {
|
||||
total_bytes_written_ += buf_size;
|
||||
} else {
|
||||
ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
|
||||
ALOGW("Zip: unable to write %zu bytes to file; %s", buf_size, strerror(errno));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1048,7 +1040,7 @@ int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
|
|||
}
|
||||
} while (zerr == Z_OK);
|
||||
|
||||
assert(zerr == Z_STREAM_END); /* other errors should've been caught */
|
||||
CHECK_EQ(zerr, Z_STREAM_END); /* other errors should've been caught */
|
||||
|
||||
// NOTE: zstream.adler is always set to 0, because we're using the -MAX_WBITS
|
||||
// "feature" of zlib to tell it there won't be a zlib file header. zlib
|
||||
|
@ -1255,16 +1247,14 @@ void CentralDirectory::Initialize(void* map_base_ptr, off64_t cd_start_offset, s
|
|||
length_ = cd_size;
|
||||
}
|
||||
|
||||
bool ZipArchive::InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
|
||||
size_t cd_size) {
|
||||
bool ZipArchive::InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size) {
|
||||
if (mapped_zip.HasFd()) {
|
||||
if (!directory_map->create(debug_file_name, mapped_zip.GetFileDescriptor(), cd_start_offset,
|
||||
cd_size, true /* read only */)) {
|
||||
return false;
|
||||
}
|
||||
directory_map = android::base::MappedFile::FromFd(mapped_zip.GetFileDescriptor(),
|
||||
cd_start_offset, cd_size, PROT_READ);
|
||||
if (!directory_map) return false;
|
||||
|
||||
CHECK_EQ(directory_map->getDataLength(), cd_size);
|
||||
central_directory.Initialize(directory_map->getDataPtr(), 0 /*offset*/, cd_size);
|
||||
CHECK_EQ(directory_map->size(), cd_size);
|
||||
central_directory.Initialize(directory_map->data(), 0 /*offset*/, cd_size);
|
||||
} else {
|
||||
if (mapped_zip.GetBasePtr() == nullptr) {
|
||||
ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer\n");
|
||||
|
|
|
@ -14,8 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
|
||||
#define LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
|
||||
#pragma once
|
||||
|
||||
#include <ziparchive/zip_archive.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -24,9 +25,8 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <utils/FileMap.h>
|
||||
#include <ziparchive/zip_archive.h>
|
||||
#include "android-base/macros.h"
|
||||
#include "android-base/mapped_file.h"
|
||||
|
||||
static const char* kErrorMessages[] = {
|
||||
"Success",
|
||||
|
@ -164,7 +164,7 @@ struct ZipArchive {
|
|||
// mapped central directory area
|
||||
off64_t directory_offset;
|
||||
CentralDirectory central_directory;
|
||||
std::unique_ptr<android::FileMap> directory_map;
|
||||
std::unique_ptr<android::base::MappedFile> directory_map;
|
||||
|
||||
// number of entries in the Zip archive
|
||||
uint16_t num_entries;
|
||||
|
@ -180,8 +180,5 @@ struct ZipArchive {
|
|||
ZipArchive(void* address, size_t length);
|
||||
~ZipArchive();
|
||||
|
||||
bool InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
|
||||
size_t cd_size);
|
||||
bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
|
||||
};
|
||||
|
||||
#endif // LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/mapped_file.h>
|
||||
#include <android-base/test_utils.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <utils/FileMap.h>
|
||||
#include <ziparchive/zip_archive.h>
|
||||
#include <ziparchive/zip_archive_stream_entry.h>
|
||||
|
||||
|
@ -416,11 +416,10 @@ TEST(ziparchive, OpenFromMemory) {
|
|||
ASSERT_EQ(0, fstat(fd, &sb));
|
||||
|
||||
// Memory map the file first and open the archive from the memory region.
|
||||
android::FileMap file_map;
|
||||
file_map.create(zip_path.c_str(), fd, 0 /*offset*/, sb.st_size, true);
|
||||
auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
|
||||
ZipArchiveHandle handle;
|
||||
ASSERT_EQ(0, OpenArchiveFromMemory(file_map.getDataPtr(), file_map.getDataLength(),
|
||||
zip_path.c_str(), &handle));
|
||||
ASSERT_EQ(0,
|
||||
OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
|
||||
|
||||
// Assert one entry can be found and extracted correctly.
|
||||
std::string BINARY_PATH("META-INF/com/google/android/update-binary");
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include <vector>
|
||||
|
||||
#include "android-base/logging.h"
|
||||
#include "utils/Compat.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "entry_name_utils-inl.h"
|
||||
#include "zip_archive_common.h"
|
||||
|
@ -303,10 +301,10 @@ int32_t ZipWriter::PrepareDeflate() {
|
|||
|
||||
if (zerr != Z_OK) {
|
||||
if (zerr == Z_VERSION_ERROR) {
|
||||
ALOGE("Installed zlib is not compatible with linked version (%s)", ZLIB_VERSION);
|
||||
LOG(ERROR) << "Installed zlib is not compatible with linked version (" << ZLIB_VERSION << ")";
|
||||
return HandleError(kZlibError);
|
||||
} else {
|
||||
ALOGE("deflateInit2 failed (zerr=%d)", zerr);
|
||||
LOG(ERROR) << "deflateInit2 failed (zerr=" << zerr << ")";
|
||||
return HandleError(kZlibError);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue