1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef DIFF_PATCH_H 17 #define DIFF_PATCH_H 18 19 #ifdef __WIN32 20 #include "pkg_utils.h" 21 #else 22 #include <sys/mman.h> 23 #endif 24 #include <cstdlib> 25 #include <unistd.h> 26 #include <vector> 27 #include "log/log.h" 28 #include "patch/update_patch.h" 29 30 namespace UpdatePatch { 31 #ifdef __WIN32 32 #undef ERROR 33 #endif 34 35 #define PATCH_LOGE(format, ...) Logger(Updater::ERROR, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) 36 #define PATCH_DEBUG(format, ...) Logger(Updater::DEBUG, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) 37 #define PATCH_LOGI(format, ...) Logger(Updater::INFO, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) 38 #define PATCH_LOGW(format, ...) Logger(Updater::WARNING, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) 39 40 enum { 41 PATCH_SUCCESS = 0, 42 PATCH_INVALID_PARAM, 43 PATCH_NEW_FILE, 44 PATCH_EXCEED_LIMIT, 45 PATCH_INVALID_PATCH, 46 }; 47 48 /* 49 * The pkgdiff patch header looks like this: 50 * 51 * "pkgdiff0" (8) [magic number and version] 52 * block count (4) 53 * for each block: 54 * block type (4) [BLOCK_{NORMAL, DEFLATE, RAW, Lz4}] 55 * if block type == BLOCK_NORMAL: 56 * source start (8) 57 * source len (8) 58 * bsdiff patch offset (8) [from start of patch file] 59 * if block type == BLOCK_DEFLATE: 60 * source start (8) 61 * source len (8) 62 * bsdiff patch offset (8) [from start of patch file] 63 * source expanded len (8) [size of uncompressed source] 64 * target expected len (8) [size of uncompressed target] 65 * zip level (4) 66 * method (4) 67 * windowBits (4) 68 * memLevel (4) 69 * strategy (4) 70 * if block type == BLOCK_LZ4: 71 * source start (8) 72 * source len (8) 73 * bsdiff patch offset (8) [from start of patch file] 74 * source expanded len (8) [size of uncompressed source] 75 * target expected len (8) [size of uncompressed target] 76 * lz4 level (4) 77 * method (4) 78 * blockIndependence (4) 79 * contentChecksumFlag (4) 80 * blockSizeID (4) 81 * autoFlush (4) 82 * if block type == RAW: 83 * target len (4) 84 * data (target len) 85 * 86 */ 87 88 /* Header is 89 0 8 "BSDIFF40" 90 8 8 length of bzip2ed ctrl block 91 16 8 length of bzip2ed diff block 92 24 8 length of new file 93 */ 94 /* File is 95 0 32 Header 96 32 40 Bzip2ed ctrl block 97 40 48 Bzip2ed diff block 98 48 56 Bzip2ed extra block 99 */ 100 101 // patch block types 102 #define BLOCK_NORMAL 0 103 #define BLOCK_GZIP 1 104 #define BLOCK_DEFLATE 2 105 #define BLOCK_RAW 3 106 #define BLOCK_LZ4 4 107 108 static constexpr size_t GZIP_HEADER_LEN = 10; 109 static constexpr size_t VERSION = 2; 110 static constexpr unsigned short HEADER_CRC = 0x02; /* bit 1 set: CRC16 for the gzip header */ 111 static constexpr unsigned short EXTRA_FIELD = 0x04; /* bit 2 set: extra field present */ 112 static constexpr unsigned short ORIG_NAME = 0x08; /* bit 3 set: original file name present */ 113 static constexpr unsigned short COMMENT = 0x10; /* bit 4 set: file comment present */ 114 static constexpr unsigned short ENCRYPTED = 0x20; /* bit 5 set: file is encrypted */ 115 static constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; 116 117 // The gzip footer size really is fixed. 118 static constexpr size_t GZIP_FOOTER_LEN = 8; 119 static constexpr size_t LZ4_HEADER_LEN = 4; 120 static constexpr size_t IGMDIFF_LIMIT_UNIT = 10240; 121 122 static constexpr int LZ4S_MAGIC = 0x184D2204; 123 static constexpr int LZ4B_MAGIC = 0x184C2102; 124 static constexpr int GZIP_MAGIC = 0x00088b1f; 125 126 static constexpr int PATCH_NORMAL_MIN_HEADER_LEN = 24; 127 static constexpr int PATCH_DEFLATE_MIN_HEADER_LEN = 60; 128 static constexpr int PATCH_LZ4_MIN_HEADER_LEN = 64; 129 130 constexpr const char *BSDIFF_MAGIC = "BSDIFF40"; 131 constexpr const char *PKGDIFF_MAGIC = "PKGDIFF0"; 132 133 struct PatchHeader { 134 size_t srcStart = 0; 135 size_t srcLength = 0; 136 size_t patchOffset = 0; 137 size_t expandedLen = 0; 138 size_t targetSize = 0; 139 }; 140 141 struct ControlData { 142 int64_t diffLength; 143 int64_t extraLength; 144 int64_t offsetIncrement; 145 uint8_t *diffNewStart; 146 uint8_t *diffOldStart; 147 uint8_t *extraNewStart; 148 }; 149 150 struct MemMapInfo { 151 uint8_t *memory {}; 152 size_t length {}; 153 int fd {-1}; ~MemMapInfoMemMapInfo154 ~MemMapInfo() 155 { 156 if (memory != nullptr) { 157 munmap(memory, length); 158 } 159 memory = nullptr; 160 if (fd != -1) { 161 close(fd); 162 fd = -1; 163 } 164 } 165 }; 166 167 int32_t WriteDataToFile(const std::string &fileName, const std::vector<uint8_t> &data, size_t dataSize); 168 int32_t PatchMapFile(const std::string &fileName, MemMapInfo &info); 169 std::string GeneraterBufferHash(const BlockBuffer &buffer); 170 std::string ConvertSha256Hex(const BlockBuffer &buffer); 171 } // namespace UpdatePatch 172 #endif // DIFF_PATCH_H