• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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