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