blob: 839960ee2aaf532ea3b0e3d7fe85a3e898eaed81 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Alex Deymof1cbe172015-03-05 15:58:37 -080016
17#include "update_engine/payload_generator/payload_generation_config.h"
18
Yifan Hong398cb542018-10-18 11:29:40 -070019#include <algorithm>
Kelvin Zhang8389dfe2022-01-13 12:47:11 -080020#include <charconv>
Yifan Hong398cb542018-10-18 11:29:40 -070021#include <utility>
22
Daniel Zhengc145c712023-05-02 15:12:03 -070023#include <android-base/parseint.h>
Alex Deymoa26432a2015-03-12 16:08:04 -070024#include <base/logging.h>
Yifan Hong398cb542018-10-18 11:29:40 -070025#include <base/strings/string_number_conversions.h>
26#include <brillo/strings/string_utils.h>
Akilesh Kailash3632df92021-04-13 22:30:15 +000027#include <libsnapshot/cow_format.h>
Alex Deymoa26432a2015-03-12 16:08:04 -070028
Kelvin Zhang0aa4fae2021-10-28 09:15:27 -070029#include "bsdiff/constants.h"
Kelvin Zhangf67dc492021-12-08 15:35:31 -080030#include "payload_consumer/payload_constants.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080031#include "update_engine/common/utils.h"
Sen Jiang0a582fb2018-06-26 19:27:21 -070032#include "update_engine/payload_generator/boot_img_filesystem.h"
Alex Deymof1cbe172015-03-05 15:58:37 -080033#include "update_engine/payload_generator/delta_diff_generator.h"
Sen Jiangdcbc0ae2016-03-18 15:33:19 -070034#include "update_engine/payload_generator/delta_diff_utils.h"
Kelvin Zhang446989a2021-12-08 13:49:07 -080035#include "update_engine/payload_generator/erofs_filesystem.h"
Alex Deymob42b98d2015-07-06 17:42:38 -070036#include "update_engine/payload_generator/ext2_filesystem.h"
Alex Deymo20bdc702016-12-07 21:07:11 -080037#include "update_engine/payload_generator/mapfile_filesystem.h"
Alex Deymob42b98d2015-07-06 17:42:38 -070038#include "update_engine/payload_generator/raw_filesystem.h"
Amin Hassani77c25fc2019-01-29 10:24:19 -080039#include "update_engine/payload_generator/squashfs_filesystem.h"
Kelvin Zhang957c7082023-07-25 20:35:16 -070040#include "update_engine/update_metadata.pb.h"
Alex Deymof1cbe172015-03-05 15:58:37 -080041
Yifan Hong398cb542018-10-18 11:29:40 -070042using std::string;
43
Alex Deymof1cbe172015-03-05 15:58:37 -080044namespace chromeos_update_engine {
45
Sen Jiang05feee02015-11-11 15:59:49 -080046bool PostInstallConfig::IsEmpty() const {
Alex Deymo5b91c6b2016-08-04 20:33:36 -070047 return !run && path.empty() && filesystem_type.empty() && !optional;
Sen Jiang05feee02015-11-11 15:59:49 -080048}
49
Sen Jiang3a4dfac2018-08-30 16:57:38 -070050bool VerityConfig::IsEmpty() const {
51 return hash_tree_data_extent.num_blocks() == 0 &&
52 hash_tree_extent.num_blocks() == 0 && hash_tree_algorithm.empty() &&
53 hash_tree_salt.empty() && fec_data_extent.num_blocks() == 0 &&
54 fec_extent.num_blocks() == 0 && fec_roots == 0;
55}
56
Kelvin Zhangb4416c92022-08-02 11:12:57 -070057void VerityConfig::Clear() {
58 hash_tree_data_extent.Clear();
59 hash_tree_extent.Clear();
60 hash_tree_algorithm.clear();
61 hash_tree_salt.clear();
62 fec_data_extent.Clear();
63 fec_extent.Clear();
64 fec_roots = 0;
65}
66
Alex Deymo35589c22015-06-07 17:33:18 +020067bool PartitionConfig::ValidateExists() const {
68 TEST_AND_RETURN_FALSE(!path.empty());
69 TEST_AND_RETURN_FALSE(utils::FileExists(path.c_str()));
70 TEST_AND_RETURN_FALSE(size > 0);
Alex Deymof1cbe172015-03-05 15:58:37 -080071 // The requested size is within the limits of the file.
Alex Deymo35589c22015-06-07 17:33:18 +020072 TEST_AND_RETURN_FALSE(static_cast<off_t>(size) <=
73 utils::FileSize(path.c_str()));
Alex Deymof1cbe172015-03-05 15:58:37 -080074 return true;
75}
76
Alex Deymob42b98d2015-07-06 17:42:38 -070077bool PartitionConfig::OpenFilesystem() {
78 if (path.empty())
79 return true;
80 fs_interface.reset();
Sen Jiangdcbc0ae2016-03-18 15:33:19 -070081 if (diff_utils::IsExtFilesystem(path)) {
Alex Deymob42b98d2015-07-06 17:42:38 -070082 fs_interface = Ext2Filesystem::CreateFromFile(path);
Sen Jiangdcbc0ae2016-03-18 15:33:19 -070083 // TODO(deymo): The delta generator algorithm doesn't support a block size
84 // different than 4 KiB. Remove this check once that's fixed. b/26972455
Alex Deymo20bdc702016-12-07 21:07:11 -080085 if (fs_interface) {
Sen Jiangdcbc0ae2016-03-18 15:33:19 -070086 TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
Alex Deymo20bdc702016-12-07 21:07:11 -080087 return true;
88 }
Alex Deymob42b98d2015-07-06 17:42:38 -070089 }
Kelvin Zhang8389dfe2022-01-13 12:47:11 -080090 fs_interface = ErofsFilesystem::CreateFromFile(path, erofs_compression_param);
Kelvin Zhang446989a2021-12-08 13:49:07 -080091 if (fs_interface) {
92 TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
93 return true;
94 }
Alex Deymob42b98d2015-07-06 17:42:38 -070095
Alex Deymo20bdc702016-12-07 21:07:11 -080096 if (!mapfile_path.empty()) {
97 fs_interface = MapfileFilesystem::CreateFromFile(path, mapfile_path);
98 if (fs_interface) {
99 TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
100 return true;
101 }
Alex Deymob42b98d2015-07-06 17:42:38 -0700102 }
Alex Deymo20bdc702016-12-07 21:07:11 -0800103
Sen Jiang0a582fb2018-06-26 19:27:21 -0700104 fs_interface = BootImgFilesystem::CreateFromFile(path);
105 if (fs_interface) {
106 TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
107 return true;
108 }
109
Amin Hassani77c25fc2019-01-29 10:24:19 -0800110 fs_interface = SquashfsFilesystem::CreateFromFile(path,
Kelvin Zhanged9b2082023-05-25 13:58:19 -0700111 /*extract_deflates=*/true);
Amin Hassani77c25fc2019-01-29 10:24:19 -0800112 if (fs_interface) {
113 TEST_AND_RETURN_FALSE(fs_interface->GetBlockSize() == kBlockSize);
114 return true;
115 }
116
Alex Deymo20bdc702016-12-07 21:07:11 -0800117 // Fall back to a RAW filesystem.
118 TEST_AND_RETURN_FALSE(size % kBlockSize == 0);
119 fs_interface = RawFilesystem::Create(
120 "<" + name + "-partition>", kBlockSize, size / kBlockSize);
Alex Deymob42b98d2015-07-06 17:42:38 -0700121 return true;
122}
123
Alex Deymof1cbe172015-03-05 15:58:37 -0800124bool ImageConfig::ValidateIsEmpty() const {
Sen Jiang981eb112015-08-25 17:03:18 -0700125 return partitions.empty();
Alex Deymof1cbe172015-03-05 15:58:37 -0800126}
127
128bool ImageConfig::LoadImageSize() {
Sen Jiang981eb112015-08-25 17:03:18 -0700129 for (PartitionConfig& part : partitions) {
130 if (part.path.empty())
131 continue;
132 part.size = utils::FileSize(part.path);
133 }
Alex Deymof1cbe172015-03-05 15:58:37 -0800134 return true;
135}
136
Sen Jiang05feee02015-11-11 15:59:49 -0800137bool ImageConfig::LoadPostInstallConfig(const brillo::KeyValueStore& store) {
138 bool found_postinstall = false;
139 for (PartitionConfig& part : partitions) {
Daniel Zheng04f10af2024-02-21 13:03:54 -0800140 bool run_postinstall{};
Sen Jiang05feee02015-11-11 15:59:49 -0800141 if (!store.GetBoolean("RUN_POSTINSTALL_" + part.name, &run_postinstall) ||
142 !run_postinstall)
143 continue;
144 found_postinstall = true;
145 part.postinstall.run = true;
146 store.GetString("POSTINSTALL_PATH_" + part.name, &part.postinstall.path);
147 store.GetString("FILESYSTEM_TYPE_" + part.name,
148 &part.postinstall.filesystem_type);
Alex Deymo5b91c6b2016-08-04 20:33:36 -0700149 store.GetBoolean("POSTINSTALL_OPTIONAL_" + part.name,
150 &part.postinstall.optional);
Sen Jiang05feee02015-11-11 15:59:49 -0800151 }
152 if (!found_postinstall) {
153 LOG(ERROR) << "No valid postinstall config found.";
154 return false;
155 }
156 return true;
157}
158
Yifan Hong398cb542018-10-18 11:29:40 -0700159bool ImageConfig::LoadDynamicPartitionMetadata(
160 const brillo::KeyValueStore& store) {
161 auto metadata = std::make_unique<DynamicPartitionMetadata>();
162 string buf;
163 if (!store.GetString("super_partition_groups", &buf)) {
164 LOG(ERROR) << "Dynamic partition info missing super_partition_groups.";
165 return false;
166 }
167 auto group_names = brillo::string_utils::Split(buf, " ");
168 for (const auto& group_name : group_names) {
169 DynamicPartitionGroup* group = metadata->add_groups();
170 group->set_name(group_name);
Yifan Hong8683ed42019-11-01 16:58:29 -0700171 if (!store.GetString("super_" + group_name + "_group_size", &buf) &&
172 !store.GetString(group_name + "_size", &buf)) {
173 LOG(ERROR) << "Missing super_" << group_name + "_group_size or "
174 << group_name << "_size.";
Yifan Hong398cb542018-10-18 11:29:40 -0700175 return false;
176 }
177
Daniel Zheng04f10af2024-02-21 13:03:54 -0800178 uint64_t max_size{};
Yifan Hong398cb542018-10-18 11:29:40 -0700179 if (!base::StringToUint64(buf, &max_size)) {
Yifan Hong8683ed42019-11-01 16:58:29 -0700180 LOG(ERROR) << "Group size for " << group_name << " = " << buf
181 << " is not an integer.";
Yifan Hong398cb542018-10-18 11:29:40 -0700182 return false;
183 }
184 group->set_size(max_size);
185
Yifan Hong8683ed42019-11-01 16:58:29 -0700186 if (store.GetString("super_" + group_name + "_partition_list", &buf) ||
187 store.GetString(group_name + "_partition_list", &buf)) {
Yifan Hong398cb542018-10-18 11:29:40 -0700188 auto partition_names = brillo::string_utils::Split(buf, " ");
189 for (const auto& partition_name : partition_names) {
190 group->add_partition_names()->assign(partition_name);
191 }
192 }
193 }
Yifan Hong05b3b962019-09-26 17:19:21 -0700194
195 bool snapshot_enabled = false;
196 store.GetBoolean("virtual_ab", &snapshot_enabled);
197 metadata->set_snapshot_enabled(snapshot_enabled);
Kelvin Zhangad8ea102021-01-14 10:14:44 -0500198 bool vabc_enabled = false;
Kelvin Zhang413982e2021-03-02 15:34:50 -0500199 if (store.GetBoolean("virtual_ab_compression", &vabc_enabled) &&
200 vabc_enabled) {
201 LOG(INFO) << "Target build supports VABC";
Kelvin Zhangad8ea102021-01-14 10:14:44 -0500202 metadata->set_vabc_enabled(vabc_enabled);
203 }
Kelvin Zhang4ca06c12021-02-04 17:16:40 -0500204 // We use "gz" compression by default for VABC.
205 if (metadata->vabc_enabled()) {
Kelvin Zhang363380a2022-02-10 12:26:52 -0800206 std::string compression_method;
207 if (store.GetString("virtual_ab_compression_method", &compression_method)) {
208 LOG(INFO) << "Using VABC compression method '" << compression_method
209 << "'";
210 } else {
211 LOG(INFO) << "No VABC compression method specified. Defaulting to 'gz'";
212 compression_method = "gz";
213 }
214 metadata->set_vabc_compression_param(compression_method);
Daniel Zhengc145c712023-05-02 15:12:03 -0700215 std::string cow_version;
216 if (!store.GetString("virtual_ab_cow_version", &cow_version)) {
Daniel Zhengc5be0d22024-03-26 16:14:42 -0700217 metadata->set_cow_version(2);
Daniel Zhengc145c712023-05-02 15:12:03 -0700218 } else {
219 uint32_t cow_version_num{};
220 android::base::ParseUint(cow_version, &cow_version_num);
221 metadata->set_cow_version(cow_version_num);
222 }
Daniel Zheng4ff04912024-01-08 14:49:51 -0800223 std::string compression_factor;
224 if (store.GetString("virtual_ab_compression_factor", &compression_factor)) {
225 LOG(INFO) << "Using VABC compression factor " << compression_factor;
226 } else {
227 LOG(INFO) << "No compression factor specified. Defaulting to 4k";
228 compression_factor = "4096";
229 }
230 size_t compression_factor_value{};
Daniel Zheng722f6f82024-03-26 16:18:33 -0700231 if (!android::base::ParseUint(compression_factor,
232 &compression_factor_value)) {
233 LOG(ERROR) << "failed to parse compression factor value: "
234 << compression_factor;
235 return false;
236 }
237 CHECK_EQ(static_cast<int>(compression_factor_value % kBlockSize), 0);
238 CHECK_EQ(static_cast<int>(compression_factor_value &
239 (compression_factor_value - 1)),
240 0);
Daniel Zheng4ff04912024-01-08 14:49:51 -0800241 metadata->set_compression_factor(compression_factor_value);
Kelvin Zhang4ca06c12021-02-04 17:16:40 -0500242 }
Yifan Hong398cb542018-10-18 11:29:40 -0700243 dynamic_partition_metadata = std::move(metadata);
244 return true;
245}
246
247bool ImageConfig::ValidateDynamicPartitionMetadata() const {
248 if (dynamic_partition_metadata == nullptr) {
249 LOG(ERROR) << "dynamic_partition_metadata is not loaded.";
250 return false;
251 }
252
253 for (const auto& group : dynamic_partition_metadata->groups()) {
254 uint64_t sum_size = 0;
255 for (const auto& partition_name : group.partition_names()) {
256 auto partition_config = std::find_if(partitions.begin(),
257 partitions.end(),
258 [&partition_name](const auto& e) {
259 return e.name == partition_name;
260 });
261
262 if (partition_config == partitions.end()) {
263 LOG(ERROR) << "Cannot find partition " << partition_name
264 << " which is in " << group.name() << "_partition_list";
265 return false;
266 }
267 sum_size += partition_config->size;
268 }
269
270 if (sum_size > group.size()) {
271 LOG(ERROR) << "Sum of sizes in " << group.name() << "_partition_list is "
272 << sum_size << ", which is greater than " << group.name()
273 << "_size (" << group.size() << ")";
274 return false;
275 }
276 }
277 return true;
278}
279
Alex Deymoa4073ef2016-03-22 23:40:53 -0700280PayloadVersion::PayloadVersion(uint64_t major_version, uint32_t minor_version) {
281 major = major_version;
282 minor = minor_version;
283}
284
285bool PayloadVersion::Validate() const {
Amin Hassani55c75412019-10-07 11:20:39 -0700286 TEST_AND_RETURN_FALSE(major == kBrilloMajorPayloadVersion);
Alex Deymoa4073ef2016-03-22 23:40:53 -0700287 TEST_AND_RETURN_FALSE(minor == kFullPayloadMinorVersion ||
Alex Deymoa4073ef2016-03-22 23:40:53 -0700288 minor == kSourceMinorPayloadVersion ||
289 minor == kOpSrcHashMinorPayloadVersion ||
Amin Hassani77d7cbc2018-02-07 16:21:33 -0800290 minor == kBrotliBsdiffMinorPayloadVersion ||
Sen Jiang3a4dfac2018-08-30 16:57:38 -0700291 minor == kPuffdiffMinorPayloadVersion ||
Tianjief5baff42020-07-17 21:43:22 -0700292 minor == kVerityMinorPayloadVersion ||
Tianjiec7001692021-08-26 16:06:05 -0700293 minor == kPartialUpdateMinorPayloadVersion ||
Kelvin Zhangf67dc492021-12-08 15:35:31 -0800294 minor == kZucchiniMinorPayloadVersion ||
295 minor == kLZ4DIFFMinorPayloadVersion);
Alex Deymoa4073ef2016-03-22 23:40:53 -0700296 return true;
297}
298
Sen Jiangcebb6882019-02-26 16:23:28 +0800299bool PayloadVersion::OperationAllowed(InstallOperation::Type operation) const {
Alex Deymoa4073ef2016-03-22 23:40:53 -0700300 switch (operation) {
301 // Full operations:
302 case InstallOperation::REPLACE:
303 case InstallOperation::REPLACE_BZ:
304 // These operations were included in the original payload format.
Alex Deymoa4073ef2016-03-22 23:40:53 -0700305 case InstallOperation::REPLACE_XZ:
Amin Hassani55c75412019-10-07 11:20:39 -0700306 // These operations are included minor version 3 or newer and full
307 // payloads.
308 return true;
Alex Deymoa4073ef2016-03-22 23:40:53 -0700309
Alex Deymo0497d052016-03-23 09:16:59 -0700310 case InstallOperation::ZERO:
311 case InstallOperation::DISCARD:
312 // The implementation of these operations had a bug in earlier versions
313 // that prevents them from being used in any payload. We will enable
314 // them for delta payloads for now.
Amin Hassani77d7cbc2018-02-07 16:21:33 -0800315 return minor >= kBrotliBsdiffMinorPayloadVersion;
Alex Deymo0497d052016-03-23 09:16:59 -0700316
Alex Deymoa4073ef2016-03-22 23:40:53 -0700317 case InstallOperation::SOURCE_COPY:
318 case InstallOperation::SOURCE_BSDIFF:
319 return minor >= kSourceMinorPayloadVersion;
320
Amin Hassaniefa62d92017-11-09 13:46:56 -0800321 case InstallOperation::BROTLI_BSDIFF:
Amin Hassani77d7cbc2018-02-07 16:21:33 -0800322 return minor >= kBrotliBsdiffMinorPayloadVersion;
323
Tianjie Xu15de2fd2018-02-05 17:46:48 -0800324 case InstallOperation::PUFFDIFF:
Amin Hassani77d7cbc2018-02-07 16:21:33 -0800325 return minor >= kPuffdiffMinorPayloadVersion;
Amin Hassani2fe84322020-10-28 21:43:23 +0000326
Tianjiec7001692021-08-26 16:06:05 -0700327 case InstallOperation::ZUCCHINI:
328 return minor >= kZucchiniMinorPayloadVersion;
Kelvin Zhangf67dc492021-12-08 15:35:31 -0800329 case InstallOperation::LZ4DIFF_BSDIFF:
330 case InstallOperation::LZ4DIFF_PUFFDIFF:
331 return minor >= kLZ4DIFFMinorPayloadVersion;
Tianjiec7001692021-08-26 16:06:05 -0700332
Amin Hassani2fe84322020-10-28 21:43:23 +0000333 case InstallOperation::MOVE:
334 case InstallOperation::BSDIFF:
335 NOTREACHED();
Alex Deymoa4073ef2016-03-22 23:40:53 -0700336 }
337 return false;
338}
339
Tianjief5baff42020-07-17 21:43:22 -0700340bool PayloadVersion::IsDeltaOrPartial() const {
Alex Deymoa4073ef2016-03-22 23:40:53 -0700341 return minor != kFullPayloadMinorVersion;
342}
343
Alex Deymof1cbe172015-03-05 15:58:37 -0800344bool PayloadGenerationConfig::Validate() const {
Alex Deymoa4073ef2016-03-22 23:40:53 -0700345 TEST_AND_RETURN_FALSE(version.Validate());
Tianjief5baff42020-07-17 21:43:22 -0700346 TEST_AND_RETURN_FALSE(version.IsDeltaOrPartial() ==
347 (is_delta || is_partial_update));
Alex Deymof1cbe172015-03-05 15:58:37 -0800348 if (is_delta) {
Sen Jiang981eb112015-08-25 17:03:18 -0700349 for (const PartitionConfig& part : source.partitions) {
350 if (!part.path.empty()) {
351 TEST_AND_RETURN_FALSE(part.ValidateExists());
352 TEST_AND_RETURN_FALSE(part.size % block_size == 0);
353 }
Sen Jiang3a4dfac2018-08-30 16:57:38 -0700354 // Source partition should not have postinstall or verity config.
Sen Jiang05feee02015-11-11 15:59:49 -0800355 TEST_AND_RETURN_FALSE(part.postinstall.IsEmpty());
Sen Jiang3a4dfac2018-08-30 16:57:38 -0700356 TEST_AND_RETURN_FALSE(part.verity.IsEmpty());
Alex Deymof1cbe172015-03-05 15:58:37 -0800357 }
358
Alex Deymof1cbe172015-03-05 15:58:37 -0800359 } else {
360 // All the "source" image fields must be empty for full payloads.
361 TEST_AND_RETURN_FALSE(source.ValidateIsEmpty());
Alex Deymof1cbe172015-03-05 15:58:37 -0800362 }
363
364 // In all cases, the target image must exists.
Sen Jiang981eb112015-08-25 17:03:18 -0700365 for (const PartitionConfig& part : target.partitions) {
366 TEST_AND_RETURN_FALSE(part.ValidateExists());
367 TEST_AND_RETURN_FALSE(part.size % block_size == 0);
Sen Jiang3a4dfac2018-08-30 16:57:38 -0700368 if (version.minor < kVerityMinorPayloadVersion)
369 TEST_AND_RETURN_FALSE(part.verity.IsEmpty());
Sen Jiang981eb112015-08-25 17:03:18 -0700370 }
Alex Deymof1cbe172015-03-05 15:58:37 -0800371
Tianjief5baff42020-07-17 21:43:22 -0700372 if (version.minor < kPartialUpdateMinorPayloadVersion) {
373 TEST_AND_RETURN_FALSE(!is_partial_update);
374 }
375
Alex Deymo2d3b2d62015-07-17 17:34:36 -0700376 TEST_AND_RETURN_FALSE(hard_chunk_size == -1 ||
377 hard_chunk_size % block_size == 0);
378 TEST_AND_RETURN_FALSE(soft_chunk_size % block_size == 0);
Alex Deymo9b244df2015-03-11 21:51:18 -0700379
380 TEST_AND_RETURN_FALSE(rootfs_partition_size % block_size == 0);
Alex Deymo9b244df2015-03-11 21:51:18 -0700381
Alex Deymof1cbe172015-03-05 15:58:37 -0800382 return true;
383}
384
Kelvin Zhang0aa4fae2021-10-28 09:15:27 -0700385void PayloadGenerationConfig::ParseCompressorTypes(
386 const std::string& compressor_types) {
387 auto types = brillo::string_utils::Split(compressor_types, ":");
388 CHECK_LE(types.size(), 2UL)
389 << "Only two compressor types are allowed: bz2 and brotli";
390 CHECK_GT(types.size(), 0UL) << "Please pass in at least 1 valid compressor. "
391 "Allowed values are bz2 and brotli.";
392 compressors.clear();
393 for (const auto& type : types) {
394 if (type == "bz2") {
395 compressors.emplace_back(bsdiff::CompressorType::kBZ2);
396 } else if (type == "brotli") {
397 compressors.emplace_back(bsdiff::CompressorType::kBrotli);
398 } else {
399 LOG(FATAL) << "Unknown compressor type: " << type;
400 }
401 }
402}
403
Kelvin Zhang22987982022-01-04 14:37:28 -0800404bool PayloadGenerationConfig::OperationEnabled(
405 InstallOperation::Type op) const noexcept {
406 if (!version.OperationAllowed(op)) {
407 return false;
408 }
409 switch (op) {
410 case InstallOperation::ZUCCHINI:
411 return enable_zucchini;
412 case InstallOperation::LZ4DIFF_BSDIFF:
413 case InstallOperation::LZ4DIFF_PUFFDIFF:
414 return enable_lz4diff;
Kelvin Zhang957c7082023-07-25 20:35:16 -0700415 case InstallOperation::PUFFDIFF:
416 return enable_puffdiff;
Kelvin Zhang22987982022-01-04 14:37:28 -0800417 default:
418 return true;
419 }
420}
421
Kelvin Zhang8389dfe2022-01-13 12:47:11 -0800422CompressionAlgorithm PartitionConfig::ParseCompressionParam(
423 std::string_view param) {
424 CompressionAlgorithm algo;
425 auto algo_name = param;
426 const auto pos = param.find_first_of(',');
427 if (pos != std::string::npos) {
428 algo_name = param.substr(0, pos);
429 }
430 if (algo_name == "lz4") {
431 algo.set_type(CompressionAlgorithm::LZ4);
432 CHECK_EQ(pos, std::string::npos)
433 << "Invalid compression param " << param
434 << ", compression level not supported for lz4";
435 } else if (algo_name == "lz4hc") {
436 algo.set_type(CompressionAlgorithm::LZ4HC);
437 if (pos != std::string::npos) {
438 const auto level = param.substr(pos + 1);
439 int level_num = 0;
440 const auto [ptr, ec] =
441 std::from_chars(level.data(), level.data() + level.size(), level_num);
442 CHECK_EQ(ec, std::errc()) << "Failed to parse compression level " << level
443 << ", compression param: " << param;
444 algo.set_level(level_num);
445 } else {
446 LOG(FATAL) << "Unrecognized compression type: " << algo_name
447 << ", param: " << param;
448 }
449 }
450 return algo;
451}
452
Alex Deymof1cbe172015-03-05 15:58:37 -0800453} // namespace chromeos_update_engine