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 #define PATCH_CHECK(retCode, exper, ...) \ 41 if (!(retCode)) { \ 42 PATCH_LOGE(__VA_ARGS__); \ 43 exper; \ 44 } 45 46 #define PATCH_ONLY_CHECK(retCode, exper) \ 47 if (!(retCode)) { \ 48 exper; \ 49 } 50 51 #define PATCH_IS_TRUE_DONE(retCode, exper) \ 52 if ((retCode)) { \ 53 exper; \ 54 } 55 56 enum { 57 PATCH_SUCCESS = 0, 58 PATCH_INVALID_PARAM, 59 PATCH_NEW_FILE, 60 PATCH_EXCEED_LIMIT, 61 PATCH_INVALID_PATCH, 62 }; 63 64 /* 65 * The pkgdiff patch header looks like this: 66 * 67 * "pkgdiff0" (8) [magic number and version] 68 * block count (4) 69 * for each block: 70 * block type (4) [BLOCK_{NORMAL, DEFLATE, RAW, Lz4}] 71 * if block type == BLOCK_NORMAL: 72 * source start (8) 73 * source len (8) 74 * bsdiff patch offset (8) [from start of patch file] 75 * if block type == BLOCK_DEFLATE: 76 * source start (8) 77 * source len (8) 78 * bsdiff patch offset (8) [from start of patch file] 79 * source expanded len (8) [size of uncompressed source] 80 * target expected len (8) [size of uncompressed target] 81 * zip level (4) 82 * method (4) 83 * windowBits (4) 84 * memLevel (4) 85 * strategy (4) 86 * if block type == BLOCK_LZ4: 87 * source start (8) 88 * source len (8) 89 * bsdiff patch offset (8) [from start of patch file] 90 * source expanded len (8) [size of uncompressed source] 91 * target expected len (8) [size of uncompressed target] 92 * lz4 level (4) 93 * method (4) 94 * blockIndependence (4) 95 * contentChecksumFlag (4) 96 * blockSizeID (4) 97 * autoFlush (4) 98 * if block type == RAW: 99 * target len (4) 100 * data (target len) 101 * 102 */ 103 104 /* Header is 105 0 8 "BSDIFF40" 106 8 8 length of bzip2ed ctrl block 107 16 8 length of bzip2ed diff block 108 24 8 length of new file 109 */ 110 /* File is 111 0 32 Header 112 32 40 Bzip2ed ctrl block 113 40 48 Bzip2ed diff block 114 48 56 Bzip2ed extra block 115 */ 116 117 // patch block types 118 #define BLOCK_NORMAL 0 119 #define BLOCK_GZIP 1 120 #define BLOCK_DEFLATE 2 121 #define BLOCK_RAW 3 122 #define BLOCK_LZ4 4 123 124 static constexpr size_t GZIP_HEADER_LEN = 10; 125 static constexpr size_t VERSION = 2; 126 static constexpr unsigned short HEADER_CRC = 0x02; /* bit 1 set: CRC16 for the gzip header */ 127 static constexpr unsigned short EXTRA_FIELD = 0x04; /* bit 2 set: extra field present */ 128 static constexpr unsigned short ORIG_NAME = 0x08; /* bit 3 set: original file name present */ 129 static constexpr unsigned short COMMENT = 0x10; /* bit 4 set: file comment present */ 130 static constexpr unsigned short ENCRYPTED = 0x20; /* bit 5 set: file is encrypted */ 131 static constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; 132 133 // The gzip footer size really is fixed. 134 static constexpr size_t GZIP_FOOTER_LEN = 8; 135 static constexpr size_t LZ4_HEADER_LEN = 4; 136 static constexpr size_t IGMDIFF_LIMIT_UNIT = 10240; 137 138 static constexpr int LZ4S_MAGIC = 0x184D2204; 139 static constexpr int LZ4B_MAGIC = 0x184C2102; 140 static constexpr int GZIP_MAGIC = 0x00088b1f; 141 142 static constexpr int PATCH_NORMAL_MIN_HEADER_LEN = 24; 143 static constexpr int PATCH_DEFLATE_MIN_HEADER_LEN = 60; 144 static constexpr int PATCH_LZ4_MIN_HEADER_LEN = 64; 145 146 constexpr const char *BSDIFF_MAGIC = "BSDIFF40"; 147 constexpr const char *PKGDIFF_MAGIC = "PKGDIFF0"; 148 149 struct PatchHeader { 150 size_t srcStart = 0; 151 size_t srcLength = 0; 152 size_t patchOffset = 0; 153 size_t expandedLen = 0; 154 size_t targetSize = 0; 155 }; 156 157 struct ControlData { 158 int64_t diffLength; 159 int64_t extraLength; 160 int64_t offsetIncrement; 161 uint8_t *diffNewStart; 162 uint8_t *diffOldStart; 163 uint8_t *extraNewStart; 164 }; 165 166 struct MemMapInfo { 167 uint8_t *memory {}; 168 size_t length {}; 169 int fd {-1}; ~MemMapInfoMemMapInfo170 ~MemMapInfo() 171 { 172 if (memory != nullptr) { 173 munmap(memory, length); 174 } 175 memory = nullptr; 176 if (fd != -1) { 177 close(fd); 178 fd = -1; 179 } 180 } 181 }; 182 183 int32_t WriteDataToFile(const std::string &fileName, const std::vector<uint8_t> &data, size_t dataSize); 184 int32_t PatchMapFile(const std::string &fileName, MemMapInfo &info); 185 std::string GeneraterBufferHash(const BlockBuffer &buffer); 186 std::string ConvertSha256Hex(const BlockBuffer &buffer); 187 } // namespace UpdatePatch 188 #endif // DIFF_PATCH_H