From 09e468f84cc245fba61d69165b4af8f1ec4cdfd5 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Fri, 29 Sep 2017 14:39:33 -0700 Subject: Move rangeset.h and print_sha1.h into otautil. Also drop the "bootable/recovery" path in LOCAL_C_INCLUDES from applypatch modules. Test: lunch aosp_{angler,bullhead,fugu,dragon,sailfish}-userdebug; mmma bootable/recovery Change-Id: Idd602a796894f971ee4f8fa3eafe36c42d9de986 --- Android.mk | 1 + applypatch/Android.mk | 34 ++-- applypatch/applypatch.cpp | 2 +- applypatch/bspatch.cpp | 2 +- applypatch/imgdiff.cpp | 2 +- applypatch/include/applypatch/imgdiff_image.h | 2 +- otautil/include/otautil/print_sha1.h | 47 +++++ otautil/include/otautil/rangeset.h | 278 ++++++++++++++++++++++++++ print_sha1.h | 47 ----- rangeset.h | 278 -------------------------- tests/Android.mk | 1 + tests/component/applypatch_test.cpp | 2 +- tests/component/updater_test.cpp | 2 +- tests/unit/rangeset_test.cpp | 4 +- updater/blockimg.cpp | 4 +- updater/install.cpp | 4 +- verifier.cpp | 2 +- 17 files changed, 357 insertions(+), 355 deletions(-) create mode 100644 otautil/include/otautil/print_sha1.h create mode 100644 otautil/include/otautil/rangeset.h delete mode 100644 print_sha1.h delete mode 100644 rangeset.h diff --git a/Android.mk b/Android.mk index b40e23dc4..5fe37fd60 100644 --- a/Android.mk +++ b/Android.mk @@ -229,6 +229,7 @@ LOCAL_SRC_FILES := \ asn1_decoder.cpp \ verifier.cpp LOCAL_STATIC_LIBRARIES := \ + libotautil \ libcrypto_utils \ libcrypto \ libbase diff --git a/applypatch/Android.mk b/applypatch/Android.mk index 05d937004..66494e607 100644 --- a/applypatch/Android.mk +++ b/applypatch/Android.mk @@ -25,12 +25,13 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE := libapplypatch LOCAL_MODULE_TAGS := eng LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include + $(LOCAL_PATH)/include +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/include LOCAL_STATIC_LIBRARIES := \ libedify \ libotafault \ + libotautil \ libbase \ libcrypto \ libbspatch \ @@ -50,11 +51,12 @@ LOCAL_SRC_FILES := \ imgpatch.cpp LOCAL_MODULE := libimgpatch LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include + $(LOCAL_PATH)/include +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/include LOCAL_STATIC_LIBRARIES := \ libedify \ + libotautil \ libcrypto \ libbspatch \ libbase \ @@ -75,11 +77,12 @@ LOCAL_SRC_FILES := \ LOCAL_MODULE := libimgpatch LOCAL_MODULE_HOST_OS := linux LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery -LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include + $(LOCAL_PATH)/include +LOCAL_EXPORT_C_INCLUDE_DIRS := \ + $(LOCAL_PATH)/include LOCAL_STATIC_LIBRARIES := \ libedify \ + libotautil \ libcrypto \ libbspatch \ libbase \ @@ -97,9 +100,9 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ applypatch_modes.cpp LOCAL_MODULE := libapplypatch_modes -LOCAL_C_INCLUDES := bootable/recovery LOCAL_STATIC_LIBRARIES := \ libapplypatch \ + libotautil \ libbase \ libedify \ libcrypto @@ -111,7 +114,6 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES := applypatch_main.cpp LOCAL_MODULE := applypatch -LOCAL_C_INCLUDES := bootable/recovery LOCAL_STATIC_LIBRARIES := \ libapplypatch_modes \ libapplypatch \ @@ -141,6 +143,7 @@ libimgdiff_cflags := \ -DZLIB_CONST libimgdiff_static_libraries := \ + libotautil \ libbsdiff \ libdivsufsort \ libdivsufsort64 \ @@ -161,8 +164,7 @@ LOCAL_CFLAGS := \ LOCAL_STATIC_LIBRARIES := \ $(libimgdiff_static_libraries) LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery + $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include include $(BUILD_STATIC_LIBRARY) @@ -177,8 +179,7 @@ LOCAL_CFLAGS := \ LOCAL_STATIC_LIBRARIES := \ $(libimgdiff_static_libraries) LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery + $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include include $(BUILD_HOST_STATIC_LIBRARY) @@ -193,6 +194,5 @@ LOCAL_STATIC_LIBRARIES := \ $(libimgdiff_static_libraries) \ libbz LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - bootable/recovery + $(LOCAL_PATH)/include include $(BUILD_HOST_EXECUTABLE) diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index 729d2a910..c8b75df79 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -40,7 +40,7 @@ #include "edify/expr.h" #include "otafault/ota_io.h" -#include "print_sha1.h" +#include "otautil/print_sha1.h" static int LoadPartitionContents(const std::string& filename, FileContents* file); static size_t FileSink(const unsigned char* data, size_t len, int fd); diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp index b2f29fbd6..c291464a8 100644 --- a/applypatch/bspatch.cpp +++ b/applypatch/bspatch.cpp @@ -31,7 +31,7 @@ #include "applypatch/applypatch.h" #include "edify/expr.h" -#include "print_sha1.h" +#include "otautil/print_sha1.h" void ShowBSDiffLicense() { puts("The bsdiff library used herein is:\n" diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp index c887a854d..3a61a7d0d 100644 --- a/applypatch/imgdiff.cpp +++ b/applypatch/imgdiff.cpp @@ -166,7 +166,7 @@ #include #include "applypatch/imgdiff_image.h" -#include "rangeset.h" +#include "otautil/rangeset.h" using android::base::get_unaligned; diff --git a/applypatch/include/applypatch/imgdiff_image.h b/applypatch/include/applypatch/imgdiff_image.h index 491043dc1..3d29547cb 100644 --- a/applypatch/include/applypatch/imgdiff_image.h +++ b/applypatch/include/applypatch/imgdiff_image.h @@ -29,7 +29,7 @@ #include #include "imgdiff.h" -#include "rangeset.h" +#include "otautil/rangeset.h" class ImageChunk { public: diff --git a/otautil/include/otautil/print_sha1.h b/otautil/include/otautil/print_sha1.h new file mode 100644 index 000000000..03a8d292a --- /dev/null +++ b/otautil/include/otautil/print_sha1.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef RECOVERY_PRINT_SHA1_H +#define RECOVERY_PRINT_SHA1_H + +#include +#include + +#include + +static std::string print_sha1(const uint8_t* sha1, size_t len) { + const char* hex = "0123456789abcdef"; + std::string result = ""; + for (size_t i = 0; i < len; ++i) { + result.push_back(hex[(sha1[i] >> 4) & 0xf]); + result.push_back(hex[sha1[i] & 0xf]); + } + return result; +} + +[[maybe_unused]] static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) { + return print_sha1(sha1, SHA_DIGEST_LENGTH); +} + +[[maybe_unused]] static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) { + return print_sha1(sha1, 4); +} + +[[maybe_unused]] static std::string print_hex(const uint8_t* bytes, size_t len) { + return print_sha1(bytes, len); +} + +#endif // RECOVERY_PRINT_SHA1_H diff --git a/otautil/include/otautil/rangeset.h b/otautil/include/otautil/rangeset.h new file mode 100644 index 000000000..f224a08be --- /dev/null +++ b/otautil/include/otautil/rangeset.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2017 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 + +#include +#include +#include + +#include +#include +#include +#include + +using Range = std::pair; + +class RangeSet { + public: + RangeSet() : blocks_(0) {} + + explicit RangeSet(std::vector&& pairs) { + CHECK_NE(pairs.size(), static_cast(0)) << "Invalid number of tokens"; + + // Sanity check the input. + size_t result = 0; + for (const auto& range : pairs) { + CHECK_LT(range.first, range.second) + << "Empty or negative range: " << range.first << ", " << range.second; + size_t sz = range.second - range.first; + CHECK_LE(result, SIZE_MAX - sz) << "RangeSet size overflow"; + result += sz; + } + + ranges_ = pairs; + blocks_ = result; + } + + static RangeSet Parse(const std::string& range_text) { + std::vector pieces = android::base::Split(range_text, ","); + CHECK_GE(pieces.size(), static_cast(3)) << "Invalid range text: " << range_text; + + size_t num; + CHECK(android::base::ParseUint(pieces[0], &num, static_cast(INT_MAX))) + << "Failed to parse the number of tokens: " << range_text; + + CHECK_NE(num, static_cast(0)) << "Invalid number of tokens: " << range_text; + CHECK_EQ(num % 2, static_cast(0)) << "Number of tokens must be even: " << range_text; + CHECK_EQ(num, pieces.size() - 1) << "Mismatching number of tokens: " << range_text; + + std::vector pairs; + for (size_t i = 0; i < num; i += 2) { + size_t first; + CHECK(android::base::ParseUint(pieces[i + 1], &first, static_cast(INT_MAX))); + size_t second; + CHECK(android::base::ParseUint(pieces[i + 2], &second, static_cast(INT_MAX))); + + pairs.emplace_back(first, second); + } + + return RangeSet(std::move(pairs)); + } + + std::string ToString() const { + if (ranges_.empty()) { + return ""; + } + std::string result = std::to_string(ranges_.size() * 2); + for (const auto& r : ranges_) { + result += android::base::StringPrintf(",%zu,%zu", r.first, r.second); + } + + return result; + } + + // Get the block number for the i-th (starting from 0) block in the RangeSet. + size_t GetBlockNumber(size_t idx) const { + CHECK_LT(idx, blocks_) << "Out of bound index " << idx << " (total blocks: " << blocks_ << ")"; + + for (const auto& range : ranges_) { + if (idx < range.second - range.first) { + return range.first + idx; + } + idx -= (range.second - range.first); + } + + CHECK(false) << "Failed to find block number for index " << idx; + return 0; // Unreachable, but to make compiler happy. + } + + // RangeSet has half-closed half-open bounds. For example, "3,5" contains blocks 3 and 4. So "3,5" + // and "5,7" are not overlapped. + bool Overlaps(const RangeSet& other) const { + for (const auto& range : ranges_) { + size_t start = range.first; + size_t end = range.second; + for (const auto& other_range : other.ranges_) { + size_t other_start = other_range.first; + size_t other_end = other_range.second; + // [start, end) vs [other_start, other_end) + if (!(other_start >= end || start >= other_end)) { + return true; + } + } + } + return false; + } + + // size() gives the number of Range's in this RangeSet. + size_t size() const { + return ranges_.size(); + } + + // blocks() gives the number of all blocks in this RangeSet. + size_t blocks() const { + return blocks_; + } + + // We provide const iterators only. + std::vector::const_iterator cbegin() const { + return ranges_.cbegin(); + } + + std::vector::const_iterator cend() const { + return ranges_.cend(); + } + + // Need to provide begin()/end() since range-based loop expects begin()/end(). + std::vector::const_iterator begin() const { + return ranges_.cbegin(); + } + + std::vector::const_iterator end() const { + return ranges_.cend(); + } + + // Reverse const iterators for MoveRange(). + std::vector::const_reverse_iterator crbegin() const { + return ranges_.crbegin(); + } + + std::vector::const_reverse_iterator crend() const { + return ranges_.crend(); + } + + const Range& operator[](size_t i) const { + return ranges_[i]; + } + + bool operator==(const RangeSet& other) const { + // The orders of Range's matter. "4,1,5,8,10" != "4,8,10,1,5". + return (ranges_ == other.ranges_); + } + + bool operator!=(const RangeSet& other) const { + return ranges_ != other.ranges_; + } + + protected: + // Actual limit for each value and the total number are both INT_MAX. + std::vector ranges_; + size_t blocks_; +}; + +static constexpr size_t kBlockSize = 4096; + +// The class is a sorted version of a RangeSet; and it's useful in imgdiff to split the input +// files when we're handling large zip files. Specifically, we can treat the input file as a +// continuous RangeSet (i.e. RangeSet("0-99") for a 100 blocks file); and break it down into +// several smaller chunks based on the zip entries. + +// For example, [source: 0-99] can be split into +// [split_src1: 10-29]; [split_src2: 40-49, 60-69]; [split_src3: 70-89] +// Here "10-29" simply means block 10th to block 29th with respect to the original input file. +// Also, note that the split sources should be mutual exclusive, but they don't need to cover +// every block in the original source. +class SortedRangeSet : public RangeSet { + public: + SortedRangeSet() {} + + // Ranges in the the set should be mutually exclusive; and they're sorted by the start block. + explicit SortedRangeSet(std::vector&& pairs) : RangeSet(std::move(pairs)) { + std::sort(ranges_.begin(), ranges_.end()); + } + + void Insert(const Range& to_insert) { + SortedRangeSet rs({ to_insert }); + Insert(rs); + } + + // Insert the input SortedRangeSet; keep the ranges sorted and merge the overlap ranges. + void Insert(const SortedRangeSet& rs) { + if (rs.size() == 0) { + return; + } + // Merge and sort the two RangeSets. + std::vector temp = std::move(ranges_); + std::copy(rs.begin(), rs.end(), std::back_inserter(temp)); + std::sort(temp.begin(), temp.end()); + + Clear(); + // Trim overlaps and insert the result back to ranges_. + Range to_insert = temp.front(); + for (auto it = temp.cbegin() + 1; it != temp.cend(); it++) { + if (it->first <= to_insert.second) { + to_insert.second = std::max(to_insert.second, it->second); + } else { + ranges_.push_back(to_insert); + blocks_ += (to_insert.second - to_insert.first); + to_insert = *it; + } + } + ranges_.push_back(to_insert); + blocks_ += (to_insert.second - to_insert.first); + } + + void Clear() { + blocks_ = 0; + ranges_.clear(); + } + + using RangeSet::Overlaps; + bool Overlaps(size_t start, size_t len) const { + RangeSet rs({ { start / kBlockSize, (start + len - 1) / kBlockSize + 1 } }); + return Overlaps(rs); + } + + // Compute the block range the file occupies, and insert that range. + void Insert(size_t start, size_t len) { + Range to_insert{ start / kBlockSize, (start + len - 1) / kBlockSize + 1 }; + Insert(to_insert); + } + + // Given an offset of the file, checks if the corresponding block (by considering the file as + // 0-based continuous block ranges) is covered by the SortedRangeSet. If so, returns the offset + // within this SortedRangeSet. + // + // For example, the 4106-th byte of a file is from block 1, assuming a block size of 4096-byte. + // The mapped offset within a SortedRangeSet("1-9 15-19") is 10. + // + // An offset of 65546 falls into the 16-th block in a file. Block 16 is contained as the 10-th + // item in SortedRangeSet("1-9 15-19"). So its data can be found at offset 40970 (i.e. 4096 * 10 + // + 10) in a range represented by this SortedRangeSet. + size_t GetOffsetInRangeSet(size_t old_offset) const { + size_t old_block_start = old_offset / kBlockSize; + size_t new_block_start = 0; + for (const auto& range : ranges_) { + // Find the index of old_block_start. + if (old_block_start >= range.second) { + new_block_start += (range.second - range.first); + } else if (old_block_start >= range.first) { + new_block_start += (old_block_start - range.first); + return (new_block_start * kBlockSize + old_offset % kBlockSize); + } else { + CHECK(false) << "block_start " << old_block_start + << " is missing between two ranges: " << this->ToString(); + return 0; + } + } + CHECK(false) << "block_start " << old_block_start + << " exceeds the limit of current RangeSet: " << this->ToString(); + return 0; + } +}; \ No newline at end of file diff --git a/print_sha1.h b/print_sha1.h deleted file mode 100644 index d0c18b355..000000000 --- a/print_sha1.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#ifndef RECOVERY_PRINT_SHA1_H -#define RECOVERY_PRINT_SHA1_H - -#include -#include - -#include - -static std::string print_sha1(const uint8_t* sha1, size_t len) { - const char* hex = "0123456789abcdef"; - std::string result = ""; - for (size_t i = 0; i < len; ++i) { - result.push_back(hex[(sha1[i]>>4) & 0xf]); - result.push_back(hex[sha1[i] & 0xf]); - } - return result; -} - -[[maybe_unused]] static std::string print_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) { - return print_sha1(sha1, SHA_DIGEST_LENGTH); -} - -[[maybe_unused]] static std::string short_sha1(const uint8_t sha1[SHA_DIGEST_LENGTH]) { - return print_sha1(sha1, 4); -} - -[[maybe_unused]] static std::string print_hex(const uint8_t* bytes, size_t len) { - return print_sha1(bytes, len); -} - -#endif // RECOVERY_PRINT_SHA1_H diff --git a/rangeset.h b/rangeset.h deleted file mode 100644 index f224a08be..000000000 --- a/rangeset.h +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2017 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 - -#include -#include -#include - -#include -#include -#include -#include - -using Range = std::pair; - -class RangeSet { - public: - RangeSet() : blocks_(0) {} - - explicit RangeSet(std::vector&& pairs) { - CHECK_NE(pairs.size(), static_cast(0)) << "Invalid number of tokens"; - - // Sanity check the input. - size_t result = 0; - for (const auto& range : pairs) { - CHECK_LT(range.first, range.second) - << "Empty or negative range: " << range.first << ", " << range.second; - size_t sz = range.second - range.first; - CHECK_LE(result, SIZE_MAX - sz) << "RangeSet size overflow"; - result += sz; - } - - ranges_ = pairs; - blocks_ = result; - } - - static RangeSet Parse(const std::string& range_text) { - std::vector pieces = android::base::Split(range_text, ","); - CHECK_GE(pieces.size(), static_cast(3)) << "Invalid range text: " << range_text; - - size_t num; - CHECK(android::base::ParseUint(pieces[0], &num, static_cast(INT_MAX))) - << "Failed to parse the number of tokens: " << range_text; - - CHECK_NE(num, static_cast(0)) << "Invalid number of tokens: " << range_text; - CHECK_EQ(num % 2, static_cast(0)) << "Number of tokens must be even: " << range_text; - CHECK_EQ(num, pieces.size() - 1) << "Mismatching number of tokens: " << range_text; - - std::vector pairs; - for (size_t i = 0; i < num; i += 2) { - size_t first; - CHECK(android::base::ParseUint(pieces[i + 1], &first, static_cast(INT_MAX))); - size_t second; - CHECK(android::base::ParseUint(pieces[i + 2], &second, static_cast(INT_MAX))); - - pairs.emplace_back(first, second); - } - - return RangeSet(std::move(pairs)); - } - - std::string ToString() const { - if (ranges_.empty()) { - return ""; - } - std::string result = std::to_string(ranges_.size() * 2); - for (const auto& r : ranges_) { - result += android::base::StringPrintf(",%zu,%zu", r.first, r.second); - } - - return result; - } - - // Get the block number for the i-th (starting from 0) block in the RangeSet. - size_t GetBlockNumber(size_t idx) const { - CHECK_LT(idx, blocks_) << "Out of bound index " << idx << " (total blocks: " << blocks_ << ")"; - - for (const auto& range : ranges_) { - if (idx < range.second - range.first) { - return range.first + idx; - } - idx -= (range.second - range.first); - } - - CHECK(false) << "Failed to find block number for index " << idx; - return 0; // Unreachable, but to make compiler happy. - } - - // RangeSet has half-closed half-open bounds. For example, "3,5" contains blocks 3 and 4. So "3,5" - // and "5,7" are not overlapped. - bool Overlaps(const RangeSet& other) const { - for (const auto& range : ranges_) { - size_t start = range.first; - size_t end = range.second; - for (const auto& other_range : other.ranges_) { - size_t other_start = other_range.first; - size_t other_end = other_range.second; - // [start, end) vs [other_start, other_end) - if (!(other_start >= end || start >= other_end)) { - return true; - } - } - } - return false; - } - - // size() gives the number of Range's in this RangeSet. - size_t size() const { - return ranges_.size(); - } - - // blocks() gives the number of all blocks in this RangeSet. - size_t blocks() const { - return blocks_; - } - - // We provide const iterators only. - std::vector::const_iterator cbegin() const { - return ranges_.cbegin(); - } - - std::vector::const_iterator cend() const { - return ranges_.cend(); - } - - // Need to provide begin()/end() since range-based loop expects begin()/end(). - std::vector::const_iterator begin() const { - return ranges_.cbegin(); - } - - std::vector::const_iterator end() const { - return ranges_.cend(); - } - - // Reverse const iterators for MoveRange(). - std::vector::const_reverse_iterator crbegin() const { - return ranges_.crbegin(); - } - - std::vector::const_reverse_iterator crend() const { - return ranges_.crend(); - } - - const Range& operator[](size_t i) const { - return ranges_[i]; - } - - bool operator==(const RangeSet& other) const { - // The orders of Range's matter. "4,1,5,8,10" != "4,8,10,1,5". - return (ranges_ == other.ranges_); - } - - bool operator!=(const RangeSet& other) const { - return ranges_ != other.ranges_; - } - - protected: - // Actual limit for each value and the total number are both INT_MAX. - std::vector ranges_; - size_t blocks_; -}; - -static constexpr size_t kBlockSize = 4096; - -// The class is a sorted version of a RangeSet; and it's useful in imgdiff to split the input -// files when we're handling large zip files. Specifically, we can treat the input file as a -// continuous RangeSet (i.e. RangeSet("0-99") for a 100 blocks file); and break it down into -// several smaller chunks based on the zip entries. - -// For example, [source: 0-99] can be split into -// [split_src1: 10-29]; [split_src2: 40-49, 60-69]; [split_src3: 70-89] -// Here "10-29" simply means block 10th to block 29th with respect to the original input file. -// Also, note that the split sources should be mutual exclusive, but they don't need to cover -// every block in the original source. -class SortedRangeSet : public RangeSet { - public: - SortedRangeSet() {} - - // Ranges in the the set should be mutually exclusive; and they're sorted by the start block. - explicit SortedRangeSet(std::vector&& pairs) : RangeSet(std::move(pairs)) { - std::sort(ranges_.begin(), ranges_.end()); - } - - void Insert(const Range& to_insert) { - SortedRangeSet rs({ to_insert }); - Insert(rs); - } - - // Insert the input SortedRangeSet; keep the ranges sorted and merge the overlap ranges. - void Insert(const SortedRangeSet& rs) { - if (rs.size() == 0) { - return; - } - // Merge and sort the two RangeSets. - std::vector temp = std::move(ranges_); - std::copy(rs.begin(), rs.end(), std::back_inserter(temp)); - std::sort(temp.begin(), temp.end()); - - Clear(); - // Trim overlaps and insert the result back to ranges_. - Range to_insert = temp.front(); - for (auto it = temp.cbegin() + 1; it != temp.cend(); it++) { - if (it->first <= to_insert.second) { - to_insert.second = std::max(to_insert.second, it->second); - } else { - ranges_.push_back(to_insert); - blocks_ += (to_insert.second - to_insert.first); - to_insert = *it; - } - } - ranges_.push_back(to_insert); - blocks_ += (to_insert.second - to_insert.first); - } - - void Clear() { - blocks_ = 0; - ranges_.clear(); - } - - using RangeSet::Overlaps; - bool Overlaps(size_t start, size_t len) const { - RangeSet rs({ { start / kBlockSize, (start + len - 1) / kBlockSize + 1 } }); - return Overlaps(rs); - } - - // Compute the block range the file occupies, and insert that range. - void Insert(size_t start, size_t len) { - Range to_insert{ start / kBlockSize, (start + len - 1) / kBlockSize + 1 }; - Insert(to_insert); - } - - // Given an offset of the file, checks if the corresponding block (by considering the file as - // 0-based continuous block ranges) is covered by the SortedRangeSet. If so, returns the offset - // within this SortedRangeSet. - // - // For example, the 4106-th byte of a file is from block 1, assuming a block size of 4096-byte. - // The mapped offset within a SortedRangeSet("1-9 15-19") is 10. - // - // An offset of 65546 falls into the 16-th block in a file. Block 16 is contained as the 10-th - // item in SortedRangeSet("1-9 15-19"). So its data can be found at offset 40970 (i.e. 4096 * 10 - // + 10) in a range represented by this SortedRangeSet. - size_t GetOffsetInRangeSet(size_t old_offset) const { - size_t old_block_start = old_offset / kBlockSize; - size_t new_block_start = 0; - for (const auto& range : ranges_) { - // Find the index of old_block_start. - if (old_block_start >= range.second) { - new_block_start += (range.second - range.first); - } else if (old_block_start >= range.first) { - new_block_start += (old_block_start - range.first); - return (new_block_start * kBlockSize + old_offset % kBlockSize); - } else { - CHECK(false) << "block_start " << old_block_start - << " is missing between two ranges: " << this->ToString(); - return 0; - } - } - CHECK(false) << "block_start " << old_block_start - << " exceeds the limit of current RangeSet: " << this->ToString(); - return 0; - } -}; \ No newline at end of file diff --git a/tests/Android.mk b/tests/Android.mk index 31c7de177..b0f71a832 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -201,6 +201,7 @@ LOCAL_SRC_FILES := \ LOCAL_STATIC_LIBRARIES := \ libimgdiff \ libimgpatch \ + libotautil \ libbsdiff \ libbspatch \ libziparchive \ diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp index 42542898b..15ec08fe7 100644 --- a/tests/component/applypatch_test.cpp +++ b/tests/component/applypatch_test.cpp @@ -35,7 +35,7 @@ #include "applypatch/applypatch.h" #include "applypatch/applypatch_modes.h" #include "common/test_constants.h" -#include "print_sha1.h" +#include "otautil/print_sha1.h" static void sha1sum(const std::string& fname, std::string* sha1, size_t* fsize = nullptr) { ASSERT_NE(nullptr, sha1); diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index e35870dc7..e6aec4ad6 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -41,7 +41,7 @@ #include "edify/expr.h" #include "otautil/SysUtil.h" #include "otautil/error_code.h" -#include "print_sha1.h" +#include "otautil/print_sha1.h" #include "updater/blockimg.h" #include "updater/install.h" #include "updater/updater.h" diff --git a/tests/unit/rangeset_test.cpp b/tests/unit/rangeset_test.cpp index 15bcec855..b3ed99215 100644 --- a/tests/unit/rangeset_test.cpp +++ b/tests/unit/rangeset_test.cpp @@ -21,7 +21,7 @@ #include -#include "rangeset.h" +#include "otautil/rangeset.h" TEST(RangeSetTest, Parse_smoke) { RangeSet rs = RangeSet::Parse("2,1,10"); @@ -156,4 +156,4 @@ TEST(SortedRangeSetTest, file_range) { ASSERT_EQ(static_cast(40970), rs.GetOffsetInRangeSet(4096 * 16 + 10)); // block#10 not in range. ASSERT_EXIT(rs.GetOffsetInRangeSet(40970), ::testing::KilledBySignal(SIGABRT), ""); -} \ No newline at end of file +} diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 0f8364441..ce3cea4f3 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -52,8 +52,8 @@ #include "edify/expr.h" #include "otafault/ota_io.h" #include "otautil/error_code.h" -#include "print_sha1.h" -#include "rangeset.h" +#include "otautil/print_sha1.h" +#include "otautil/rangeset.h" #include "updater/install.h" #include "updater/updater.h" diff --git a/updater/install.cpp b/updater/install.cpp index 01210f51c..9425d1872 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include "edify/expr.h" @@ -61,8 +62,7 @@ #include "otafault/ota_io.h" #include "otautil/DirUtil.h" #include "otautil/error_code.h" -#include "print_sha1.h" -#include "tune2fs.h" +#include "otautil/print_sha1.h" #include "updater/updater.h" // Send over the buffer to recovery though the command pipe. diff --git a/verifier.cpp b/verifier.cpp index 18437fb7a..283e04300 100644 --- a/verifier.cpp +++ b/verifier.cpp @@ -32,7 +32,7 @@ #include #include "asn1_decoder.h" -#include "print_sha1.h" +#include "otautil/print_sha1.h" static constexpr size_t MiB = 1024 * 1024; -- cgit v1.2.3