aboutsummaryrefslogtreecommitdiff
path: root/patch_utils.h
diff options
context:
space:
mode:
authorSamuel Huang <huangs@chromium.org>2018-03-13 18:19:34 +0000
committerEdward Lesmes <ehmaldonado@google.com>2021-07-23 21:50:59 +0000
commit06f1ae9aaca969ee95ef840f22b6b461c304542d (patch)
treef1e5c6624e70628e81fbf38d6cd14b974abe5d93 /patch_utils.h
downloadzucchini-06f1ae9aaca969ee95ef840f22b6b461c304542d.tar.gz
[Zucchini] Move Zucchini from /chrome/installer/ to /components/.
(Use "git log --follow" to see older revisions of files). /components/ is the most logical place to put Zucchini, which only depends on /base and /testing/gtest. This move also enables Zucchini to be used by the Component Updater. Details: - Move all files; run the following to change deps and guards: sed 's/chrome\/installer/components/' *.cc *.h -i sed 's/CHROME_INSTALLER/COMPONENTS/' *.cc *.h -i - Sorting works out pretty well! - Change all 'chrome/installer/zucchini' to 'components/zucchini' throughout other parts of the repo; sort if necessary. - Fix 6 'git cl lint' errors. - Change 1 Bind() usage to BindRepeated(). - Update OWNER. Bug: 729154 Change-Id: I50c5a7d411ea85f707b5994ab319dfb2a1acccf7 Reviewed-on: https://chromium-review.googlesource.com/954923 Reviewed-by: Greg Thompson <grt@chromium.org> Reviewed-by: Jochen Eisinger <jochen@chromium.org> Reviewed-by: Samuel Huang <huangs@chromium.org> Commit-Queue: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/master@{#542857} NOKEYCHECK=True GitOrigin-RevId: 577ef6c435e8d43be6e3e60ccbcbd1881780f4ec
Diffstat (limited to 'patch_utils.h')
-rw-r--r--patch_utils.h152
1 files changed, 152 insertions, 0 deletions
diff --git a/patch_utils.h b/patch_utils.h
new file mode 100644
index 0000000..77cf2f3
--- /dev/null
+++ b/patch_utils.h
@@ -0,0 +1,152 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ZUCCHINI_PATCH_UTILS_H_
+#define COMPONENTS_ZUCCHINI_PATCH_UTILS_H_
+
+#include <stdint.h>
+
+#include <iterator>
+#include <type_traits>
+
+#include "components/zucchini/image_utils.h"
+
+namespace zucchini {
+
+// Constants that appear inside a patch.
+enum class PatchType : uint32_t {
+ // Patch contains a single raw element, corresponding to an element match that
+ // covers the entire images, and with ExecutableType::kExeTypeNoOp.
+ kRawPatch = 0,
+
+ // Patch contains a single executable element, corresponding to an element
+ // match that covers the entire images.
+ kSinglePatch = 1,
+
+ // Patch contains multiple raw and/or executable elements.
+ kEnsemblePatch = 2,
+
+ // Used when type is uninitialized.
+ kUnrecognisedPatch
+};
+
+// A Zucchini 'ensemble' patch is the concatenation of a patch header with a
+// list of patch 'elements', each containing data for patching individual
+// elements.
+
+// Supported by MSVC, g++, and clang++. Ensures no gaps in packing.
+#pragma pack(push, 1)
+
+// Header for a Zucchini patch, found at the beginning of an ensemble patch.
+struct PatchHeader {
+ // Magic signature at the beginning of a Zucchini patch file.
+ enum : uint32_t { kMagic = 'Z' | ('u' << 8) | ('c' << 16) };
+
+ uint32_t magic = 0;
+ uint32_t old_size = 0;
+ uint32_t old_crc = 0;
+ uint32_t new_size = 0;
+ uint32_t new_crc = 0;
+};
+
+// Sanity check.
+static_assert(sizeof(PatchHeader) == 20, "PatchHeader is 20 bytes");
+
+// Header for a patch element, found at the beginning of every patch element.
+struct PatchElementHeader {
+ uint32_t old_offset;
+ uint32_t new_offset;
+ uint32_t old_length;
+ uint32_t new_length;
+ uint32_t exe_type;
+};
+
+// Sanity check.
+static_assert(sizeof(PatchElementHeader) == 20,
+ "PatchElementHeader is 28 bytes");
+
+#pragma pack(pop)
+
+// Descibes a raw FIX operation.
+struct RawDeltaUnit {
+ offset_t copy_offset; // Offset in copy regions.
+ int8_t diff; // Bytewise difference.
+};
+
+// A Zucchini patch contains data streams encoded using varint format to reduce
+// uncompressed size.
+
+// Writes |value| as a varint in |dst| and returns an iterator pointing beyond
+// the written region. |dst| is assumed to hold enough space. Typically, this
+// will write to a vector using back insertion, e.g.:
+// EncodeVarUInt(value, std::back_inserter(vector));
+template <class T, class It>
+It EncodeVarUInt(T value, It dst) {
+ static_assert(std::is_unsigned<T>::value, "Value type must be unsigned");
+
+ while (value >= 0x80) {
+ *dst++ = static_cast<uint8_t>(value) | 0x80;
+ value >>= 7;
+ }
+ *dst++ = static_cast<uint8_t>(value);
+ return dst;
+}
+
+// Same as EncodeVarUInt(), but for signed values.
+template <class T, class It>
+It EncodeVarInt(T value, It dst) {
+ static_assert(std::is_signed<T>::value, "Value type must be signed");
+
+ using unsigned_value_type = typename std::make_unsigned<T>::type;
+ if (value < 0)
+ return EncodeVarUInt((unsigned_value_type(~value) << 1) | 1, dst);
+ else
+ return EncodeVarUInt(unsigned_value_type(value) << 1, dst);
+}
+
+// Tries to read a varint unsigned integer from |[first, last)|. If
+// succesful, writes result into |value| and returns the number of bytes
+// read from |[first, last)|. Otherwise returns 0.
+template <class T, class It>
+typename std::iterator_traits<It>::difference_type DecodeVarUInt(It first,
+ It last,
+ T* value) {
+ static_assert(std::is_unsigned<T>::value, "Value type must be unsigned");
+
+ uint8_t sh = 0;
+ T val = 0;
+ for (auto it = first; it != last;) {
+ val |= T(*it & 0x7F) << sh;
+ if (*(it++) < 0x80) {
+ *value = val;
+ return it - first;
+ }
+ sh += 7;
+ if (sh >= sizeof(T) * 8) // Overflow!
+ return 0;
+ }
+ return 0;
+}
+
+// Same as DecodeVarUInt(), but for signed values.
+template <class T, class It>
+typename std::iterator_traits<It>::difference_type DecodeVarInt(It first,
+ It last,
+ T* value) {
+ static_assert(std::is_signed<T>::value, "Value type must be signed");
+
+ typename std::make_unsigned<T>::type tmp = 0;
+ auto res = DecodeVarUInt(first, last, &tmp);
+ if (res) {
+ if (tmp & 1)
+ *value = ~static_cast<T>(tmp >> 1);
+ else
+ *value = static_cast<T>(tmp >> 1);
+ }
+ return res;
+}
+
+} // namespace zucchini
+
+#endif // COMPONENTS_ZUCCHINI_PATCH_UTILS_H_