• 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 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