Skip to content

Commit 064238e

Browse files
committed
Use Result types in image_aggregator.cc
This allows it to report errors without aborting, and reported errors include stack trace information rather than only the line number of the failing assertion. image_aggregator at one time had a non-Cuttlefish dependency, which was a reason to not use the Result type throughout. The dependent code has since stopped using image_aggregator, and the image_aggregator code has moved to a new repository (GitHub). Bug: b/434998699
1 parent 57386fd commit 064238e

File tree

3 files changed

+119
-124
lines changed

3 files changed

+119
-124
lines changed

base/cvd/cuttlefish/host/commands/assemble_cvd/disk_builder.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,13 @@ Result<bool> DiskBuilder::BuildCompositeDiskIfNecessary() {
211211
if (vm_manager_ == VmmMode::kCrosvm) {
212212
CF_EXPECT(!header_path_.empty(), "No header path");
213213
CF_EXPECT(!footer_path_.empty(), "No footer path");
214-
CreateCompositeDisk(partitions_, AbsolutePath(header_path_),
215-
AbsolutePath(footer_path_),
216-
AbsolutePath(composite_disk_path_),
217-
read_only_);
214+
CF_EXPECT(CreateCompositeDisk(
215+
partitions_, AbsolutePath(header_path_), AbsolutePath(footer_path_),
216+
AbsolutePath(composite_disk_path_), read_only_));
218217
} else {
219218
// If this doesn't fit into the disk, it will fail while aggregating. The
220219
// aggregator doesn't maintain any sparse attributes.
221-
AggregateImage(partitions_, AbsolutePath(composite_disk_path_));
220+
CF_EXPECT(AggregateImage(partitions_, AbsolutePath(composite_disk_path_)));
222221
}
223222

224223
using android::base::WriteStringToFile;

base/cvd/cuttlefish/host/libs/image_aggregator/image_aggregator.cc

Lines changed: 106 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -141,60 +141,52 @@ struct PartitionInfo {
141141
* disk file, as the imag eflashing process also can handle Android-Sparse
142142
* images.
143143
*/
144-
std::uint64_t ExpandedStorageSize(const std::string& file_path) {
144+
Result<uint64_t> ExpandedStorageSize(const std::string& file_path) {
145145
android::base::unique_fd fd(open(file_path.c_str(), O_RDONLY));
146-
CHECK(fd.get() >= 0) << "Could not open \"" << file_path << "\""
147-
<< strerror(errno);
146+
CF_EXPECTF(fd.get() >= 0, "Could not open '{}': {}", file_path,
147+
strerror(errno));
148148

149149
std::uint64_t file_size = FileSize(file_path);
150150

151151
// Try to read the disk in a nicely-aligned block size unless the whole file
152152
// is smaller.
153153
constexpr uint64_t MAGIC_BLOCK_SIZE = 4096;
154154
std::string magic(std::min(file_size, MAGIC_BLOCK_SIZE), '\0');
155-
if (!android::base::ReadFully(fd, magic.data(), magic.size())) {
156-
PLOG(FATAL) << "Fail to read: " << file_path;
157-
return 0;
158-
}
159-
CHECK(lseek(fd, 0, SEEK_SET) != -1)
160-
<< "Fail to seek(\"" << file_path << "\")" << strerror(errno);
155+
156+
CF_EXPECTF(android::base::ReadFully(fd, magic.data(), magic.size()),
157+
"Failed to read '{}': {}'", file_path, strerror(errno));
158+
159+
CF_EXPECTF(lseek(fd, 0, SEEK_SET) != -1, "Failed to lseek('{}'): {}",
160+
file_path, strerror(errno));
161161

162162
// Composite disk image
163163
if (android::base::StartsWith(magic, CDISK_MAGIC)) {
164164
// seek to the beginning of proto message
165-
CHECK(lseek(fd, CDISK_MAGIC.size(), SEEK_SET) != -1)
166-
<< "Fail to seek(\"" << file_path << "\")" << strerror(errno);
165+
CF_EXPECTF(lseek(fd, CDISK_MAGIC.size(), SEEK_SET) != -1,
166+
"Failed to lseek('{}'): {}", file_path, strerror(errno));
167+
167168
std::string message;
168-
if (!android::base::ReadFdToString(fd, &message)) {
169-
PLOG(FATAL) << "Fail to read(cdisk): " << file_path;
170-
return 0;
171-
}
169+
CF_EXPECTF(android::base::ReadFdToString(fd, &message),
170+
"Failed to read '{}': {}", file_path, strerror(errno));
171+
172172
CompositeDisk cdisk;
173-
if (!cdisk.ParseFromString(message)) {
174-
PLOG(FATAL) << "Fail to parse(cdisk): " << file_path;
175-
return 0;
176-
}
173+
CF_EXPECTF(cdisk.ParseFromString(message), "Failed to parse '{}': {}",
174+
file_path, strerror(errno));
175+
177176
return cdisk.length();
178177
}
179178

180179
// Qcow2 image
181180
if (android::base::StartsWith(magic, Qcow2Image::MagicString())) {
182-
Result<Qcow2Image> image = Qcow2Image::OpenExisting(file_path);
183-
CHECK(image.ok()) << image.error().FormatForEnv();
184-
185-
Result<uint64_t> size = image->VirtualSizeBytes();
186-
CHECK(size.ok()) << size.error().FormatForEnv();
187-
return *size;
181+
Qcow2Image image = CF_EXPECT(Qcow2Image::OpenExisting(file_path));
182+
return CF_EXPECT(image.VirtualSizeBytes());
188183
}
189184

190185
// Android-Sparse
191186
if (android::base::StartsWith(magic, AndroidSparseImage::MagicString())) {
192-
Result<AndroidSparseImage> image = AndroidSparseImage::OpenExisting(file_path);
193-
CHECK(image.ok()) << image.error().FormatForEnv();
194-
195-
Result<uint64_t> size = image->VirtualSizeBytes();
196-
CHECK(size.ok()) << size.error().FormatForEnv();
197-
return *size;
187+
AndroidSparseImage image =
188+
CF_EXPECT(AndroidSparseImage::OpenExisting(file_path));
189+
return CF_EXPECT(image.VirtualSizeBytes());
198190
}
199191

200192
// raw image file
@@ -240,7 +232,7 @@ class CompositeDiskBuilder {
240232
std::uint64_t next_disk_offset_ = sizeof(GptBeginning);
241233
bool read_only_ = true;
242234

243-
static const std::uint8_t* GetPartitionGUID(ImagePartition source) {
235+
static Result<const std::uint8_t*> GetPartitionGUID(ImagePartition source) {
244236
// Due to some endianness mismatch in e2fsprogs GUID vs GPT, the GUIDs are
245237
// rearranged to make the right GUIDs appear in gdisk
246238
switch (source.type) {
@@ -256,25 +248,26 @@ class CompositeDiskBuilder {
256248
0xba, 0x4b, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b};
257249
return kEfiSystemPartitionGuid;
258250
default:
259-
LOG(FATAL) << "Unknown partition type: " << (int) source.type;
251+
return CF_ERR("Unknown partition type: " << (int)source.type);
260252
}
261253
}
262254

263255
public:
264256
CompositeDiskBuilder(bool read_only) : read_only_(read_only) {}
265257

266-
void AppendPartition(ImagePartition source) {
267-
uint64_t size = ExpandedStorageSize(source.image_file_path);
258+
Result<void> AppendPartition(ImagePartition source) {
259+
uint64_t size = CF_EXPECT(ExpandedStorageSize(source.image_file_path));
268260
auto aligned_size = AlignToPartitionSize(size);
269-
CHECK(size == aligned_size || read_only_)
270-
<< "read-write partition " << source.label
271-
<< " is not aligned to the size of " << (1 << PARTITION_SIZE_SHIFT);
261+
CF_EXPECTF(size == aligned_size || read_only_,
262+
"read-write partition '{}' is not aligned to the size of '{}'",
263+
source.label, (1 << PARTITION_SIZE_SHIFT));
272264
partitions_.push_back(PartitionInfo{
273265
.source = source,
274266
.size = size,
275267
.offset = next_disk_offset_,
276268
});
277269
next_disk_offset_ = next_disk_offset_ + aligned_size;
270+
return {};
278271
}
279272

280273
std::uint64_t DiskSize() const {
@@ -286,8 +279,8 @@ class CompositeDiskBuilder {
286279
* and `footer_file` will be populated with the contents of `Beginning()` and
287280
* `End()`.
288281
*/
289-
CompositeDisk MakeCompositeDiskSpec(const std::string& header_file,
290-
const std::string& footer_file) const {
282+
Result<CompositeDisk> MakeCompositeDiskSpec(
283+
const std::string& header_file, const std::string& footer_file) const {
291284
CompositeDisk disk;
292285
disk.set_version(2);
293286
disk.set_length(DiskSize());
@@ -303,8 +296,9 @@ class CompositeDiskBuilder {
303296
component->set_read_write_capability(
304297
read_only_ ? ReadWriteCapability::READ_ONLY
305298
: ReadWriteCapability::READ_WRITE);
306-
uint64_t size = ExpandedStorageSize(partition.source.image_file_path);
307-
CHECK(partition.size == size);
299+
uint64_t size =
300+
CF_EXPECT(ExpandedStorageSize(partition.source.image_file_path));
301+
CF_EXPECT_EQ(partition.size, size);
308302
// When partition's aligned size differs from its (unaligned) size
309303
// reading the disk within the guest os would fail due to the gap.
310304
// Putting any disk bigger than 4K can fill this gap.
@@ -333,11 +327,8 @@ class CompositeDiskBuilder {
333327
* This method is not deterministic: some data is generated such as the disk
334328
* uuids.
335329
*/
336-
GptBeginning Beginning() const {
337-
if (partitions_.size() > GPT_NUM_PARTITIONS) {
338-
LOG(FATAL) << "Too many partitions: " << partitions_.size();
339-
return {};
340-
}
330+
Result<GptBeginning> Beginning() const {
331+
CF_EXPECT_LE(partitions_.size(), GPT_NUM_PARTITIONS, "Too many partitions");
341332
GptBeginning gpt = {
342333
.protective_mbr = ProtectiveMbr(DiskSize()),
343334
.header =
@@ -363,10 +354,9 @@ class CompositeDiskBuilder {
363354
(partition.offset + partition.AlignedSize()) / kSectorSize - 1,
364355
};
365356
SetRandomUuid(gpt.entries[i].unique_partition_guid);
366-
const std::uint8_t* const type_guid = GetPartitionGUID(partition.source);
367-
if (type_guid == nullptr) {
368-
LOG(FATAL) << "Could not recognize partition guid";
369-
}
357+
const std::uint8_t* const type_guid =
358+
CF_EXPECT(GetPartitionGUID(partition.source));
359+
CF_EXPECT(type_guid != nullptr, "Could not recognize partition guid");
370360
memcpy(gpt.entries[i].partition_type_guid, type_guid, 16);
371361
std::u16string wide_name(partitions_[i].source.label.begin(),
372362
partitions_[i].source.label.end());
@@ -399,29 +389,24 @@ class CompositeDiskBuilder {
399389
}
400390
};
401391

402-
bool WriteBeginning(SharedFD out, const GptBeginning& beginning) {
392+
Result<void> WriteBeginning(SharedFD out, const GptBeginning& beginning) {
403393
std::string begin_str((const char*) &beginning, sizeof(GptBeginning));
404-
if (WriteAll(out, begin_str) != begin_str.size()) {
405-
LOG(ERROR) << "Could not write GPT beginning: " << out->StrError();
406-
return false;
407-
}
408-
return true;
394+
CF_EXPECT_EQ(WriteAll(out, begin_str), begin_str.size(),
395+
"Could not write GPT beginning: " << out->StrError());
396+
return {};
409397
}
410398

411-
bool WriteEnd(SharedFD out, const GptEnd& end) {
399+
Result<void> WriteEnd(SharedFD out, const GptEnd& end) {
412400
auto disk_size = (end.footer.current_lba + 1) * kSectorSize;
413401
auto footer_start = (end.footer.last_usable_lba + 1) * kSectorSize;
414402
auto padding = disk_size - footer_start - sizeof(GptEnd);
415403
std::string padding_str(padding, '\0');
416-
if (WriteAll(out, padding_str) != padding_str.size()) {
417-
LOG(ERROR) << "Could not write GPT end padding: " << out->StrError();
418-
return false;
419-
}
420-
if (WriteAllBinary(out, &end) != sizeof(end)) {
421-
LOG(ERROR) << "Could not write GPT end contents: " << out->StrError();
422-
return false;
423-
}
424-
return true;
404+
405+
CF_EXPECT_EQ(WriteAll(out, padding_str), padding_str.size(),
406+
"Could not write GPT end padding: " << out->StrError());
407+
CF_EXPECT_EQ(WriteAllBinary(out, &end), sizeof(end),
408+
"Could not write GPT end contents: " << out->StrError());
409+
return {};
425410
}
426411

427412
/**
@@ -436,13 +421,11 @@ bool WriteEnd(SharedFD out, const GptEnd& end) {
436421
* crosvm has read-only support for Android-Sparse files, but QEMU does not
437422
* support them.
438423
*/
439-
void DeAndroidSparse(const std::vector<ImagePartition>& partitions) {
424+
Result<void> DeAndroidSparse(const std::vector<ImagePartition>& partitions) {
440425
for (const auto& partition : partitions) {
441-
Result<void> res = ForceRawImage(partition.image_file_path);
442-
if (!res.ok()) {
443-
LOG(FATAL) << "Desparse failed: " << res.error().FormatForEnv();
444-
}
426+
CF_EXPECT(ForceRawImage(partition.image_file_path));
445427
}
428+
return {};
446429
}
447430

448431
} // namespace
@@ -451,69 +434,80 @@ uint64_t AlignToPartitionSize(uint64_t size) {
451434
return AlignToPowerOf2(size, PARTITION_SIZE_SHIFT);
452435
}
453436

454-
void AggregateImage(const std::vector<ImagePartition>& partitions,
455-
const std::string& output_path) {
456-
DeAndroidSparse(partitions);
437+
Result<void> AggregateImage(const std::vector<ImagePartition>& partitions,
438+
const std::string& output_path) {
439+
CF_EXPECT(DeAndroidSparse(partitions));
440+
457441
CompositeDiskBuilder builder(false);
458442
for (auto& partition : partitions) {
459443
builder.AppendPartition(partition);
460444
}
461-
auto output = SharedFD::Creat(output_path, 0600);
462-
auto beginning = builder.Beginning();
463-
if (!WriteBeginning(output, beginning)) {
464-
LOG(FATAL) << "Could not write GPT beginning to \"" << output_path
465-
<< "\": " << output->StrError();
466-
}
445+
446+
SharedFD output = SharedFD::Creat(output_path, 0600);
447+
CF_EXPECTF(output->IsOpen(), "{}", output->StrError());
448+
449+
GptBeginning beginning = CF_EXPECT(builder.Beginning());
450+
CF_EXPECTF(WriteBeginning(output, beginning),
451+
"Could not write GPT beginning to '{}': {}", output_path,
452+
output->StrError());
453+
467454
for (auto& disk : partitions) {
468-
auto disk_fd = SharedFD::Open(disk.image_file_path, O_RDONLY);
455+
SharedFD disk_fd = SharedFD::Open(disk.image_file_path, O_RDONLY);
456+
CF_EXPECTF(disk_fd->IsOpen(), "{}", disk_fd->StrError());
457+
469458
auto file_size = FileSize(disk.image_file_path);
470-
if (!output->CopyFrom(*disk_fd, file_size)) {
471-
LOG(FATAL) << "Could not copy from \"" << disk.image_file_path
472-
<< "\" to \"" << output_path << "\": " << output->StrError();
473-
}
459+
CF_EXPECTF(output->CopyFrom(*disk_fd, file_size),
460+
"Could not copy from '{}' to '{}': {}", disk.image_file_path,
461+
output_path, output->StrError());
474462
// Handle disk images that are not aligned to PARTITION_SIZE_SHIFT
475463
std::uint64_t padding = AlignToPartitionSize(file_size) - file_size;
476464
std::string padding_str;
477465
padding_str.resize(padding, '\0');
478-
if (WriteAll(output, padding_str) != padding_str.size()) {
479-
LOG(FATAL) << "Could not write partition padding to \"" << output_path
480-
<< "\": " << output->StrError();
481-
}
482-
}
483-
if (!WriteEnd(output, builder.End(beginning))) {
484-
LOG(FATAL) << "Could not write GPT end to \"" << output_path
485-
<< "\": " << output->StrError();
466+
467+
CF_EXPECTF(WriteAll(output, padding_str) != padding_str.size(),
468+
"Could not write partition padding to '{}': {}", output_path,
469+
output->StrError());
486470
}
471+
CF_EXPECTF(WriteEnd(output, builder.End(beginning)),
472+
"Could not write GPT end to '{}': {}", output_path,
473+
output->StrError());
474+
return {};
487475
};
488476

489-
void CreateCompositeDisk(std::vector<ImagePartition> partitions,
490-
const std::string& header_file,
491-
const std::string& footer_file,
492-
const std::string& output_composite_path,
493-
bool read_only) {
494-
DeAndroidSparse(partitions);
477+
Result<void> CreateCompositeDisk(std::vector<ImagePartition> partitions,
478+
const std::string& header_file,
479+
const std::string& footer_file,
480+
const std::string& output_composite_path,
481+
bool read_only) {
482+
CF_EXPECT(DeAndroidSparse(partitions));
495483

496484
CompositeDiskBuilder builder(read_only);
497485
for (auto& partition : partitions) {
498486
builder.AppendPartition(partition);
499487
}
500-
auto header = SharedFD::Creat(header_file, 0600);
501-
auto beginning = builder.Beginning();
502-
if (!WriteBeginning(header, beginning)) {
503-
LOG(FATAL) << "Could not write GPT beginning to \"" << header_file
504-
<< "\": " << header->StrError();
505-
}
506-
auto footer = SharedFD::Creat(footer_file, 0600);
507-
if (!WriteEnd(footer, builder.End(beginning))) {
508-
LOG(FATAL) << "Could not write GPT end to \"" << footer_file
509-
<< "\": " << footer->StrError();
510-
}
511-
auto composite_proto = builder.MakeCompositeDiskSpec(header_file, footer_file);
488+
SharedFD header = SharedFD::Creat(header_file, 0600);
489+
CF_EXPECTF(header->IsOpen(), "{}", header->StrError());
490+
491+
GptBeginning beginning = CF_EXPECT(builder.Beginning());
492+
CF_EXPECTF(WriteBeginning(header, beginning),
493+
"Could not write GPT beginning to '{}': {}", header_file,
494+
header->StrError());
495+
496+
SharedFD footer = SharedFD::Creat(footer_file, 0600);
497+
CF_EXPECTF(footer->IsOpen(), "{}", footer->StrError());
498+
499+
CF_EXPECTF(WriteEnd(footer, builder.End(beginning)),
500+
"Could not write GPT end to '{}': {}", footer_file,
501+
footer->StrError());
502+
CompositeDisk composite_proto =
503+
CF_EXPECT(builder.MakeCompositeDiskSpec(header_file, footer_file));
512504
std::ofstream composite(output_composite_path.c_str(),
513505
std::ios::binary | std::ios::trunc);
514506
composite << CDISK_MAGIC;
515507
composite_proto.SerializeToOstream(&composite);
516508
composite.flush();
509+
510+
return {};
517511
}
518512

519513
} // namespace cuttlefish

0 commit comments

Comments
 (0)