Merge "Use __VA_ARGS__ when in clang static analyzer."
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index aeb339b..a361a5d 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -82,7 +82,8 @@
// to do this when the data pointers are all in one place.
class SparseBuilder {
public:
- SparseBuilder(const LpMetadata& metadata, uint32_t block_size);
+ SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
+ const std::map<std::string, std::string>& images);
bool Build();
bool Export(const char* file);
@@ -90,6 +91,8 @@
private:
bool AddData(const std::string& blob, uint64_t sector);
+ bool AddPartitionImage(const LpMetadataPartition& partition, const std::string& file);
+ int OpenImageFile(const std::string& file);
bool SectorToBlock(uint64_t sector, uint32_t* block);
const LpMetadata& metadata_;
@@ -98,13 +101,17 @@
std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> file_;
std::string primary_blob_;
std::string backup_blob_;
+ std::map<std::string, std::string> images_;
+ std::vector<android::base::unique_fd> temp_fds_;
};
-SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size)
+SparseBuilder::SparseBuilder(const LpMetadata& metadata, uint32_t block_size,
+ const std::map<std::string, std::string>& images)
: metadata_(metadata),
geometry_(metadata.geometry),
block_size_(block_size),
- file_(sparse_file_new(block_size_, geometry_.block_device_size), sparse_file_destroy) {}
+ file_(sparse_file_new(block_size_, geometry_.block_device_size), sparse_file_destroy),
+ images_(images) {}
bool SparseBuilder::Export(const char* file) {
android::base::unique_fd fd(open(file, O_CREAT | O_RDWR | O_TRUNC, 0644));
@@ -168,6 +175,22 @@
return false;
}
+ for (const auto& partition : metadata_.partitions) {
+ auto iter = images_.find(GetPartitionName(partition));
+ if (iter == images_.end()) {
+ continue;
+ }
+ if (!AddPartitionImage(partition, iter->second)) {
+ return false;
+ }
+ images_.erase(iter);
+ }
+
+ if (!images_.empty()) {
+ LERROR << "Partition image was specified but no partition was found.";
+ return false;
+ }
+
// The backup area contains all metadata slots, and then geometry. Similar
// to before we write the metadata to every slot.
int64_t backup_offset = GetBackupMetadataOffset(geometry_, 0);
@@ -181,7 +204,126 @@
return true;
}
-bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size) {
+static inline bool HasFillValue(uint32_t* buffer, size_t count) {
+ uint32_t fill_value = buffer[0];
+ for (size_t i = 1; i < count; i++) {
+ if (fill_value != buffer[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool SparseBuilder::AddPartitionImage(const LpMetadataPartition& partition,
+ const std::string& file) {
+ if (partition.num_extents != 1) {
+ LERROR << "Partition for new tables should not have more than one extent: "
+ << GetPartitionName(partition);
+ return false;
+ }
+
+ const LpMetadataExtent& extent = metadata_.extents[partition.first_extent_index];
+ if (extent.target_type != LP_TARGET_TYPE_LINEAR) {
+ LERROR << "Partition should only have linear extents: " << GetPartitionName(partition);
+ return false;
+ }
+
+ int fd = OpenImageFile(file);
+ if (fd < 0) {
+ LERROR << "Could not open image for partition: " << GetPartitionName(partition);
+ return false;
+ }
+
+ // Make sure the image does not exceed the partition size.
+ uint64_t file_length;
+ if (!GetDescriptorSize(fd, &file_length)) {
+ LERROR << "Could not compute image size";
+ return false;
+ }
+ if (file_length > extent.num_sectors * LP_SECTOR_SIZE) {
+ LERROR << "Image for partition '" << GetPartitionName(partition)
+ << "' is greater than its size";
+ return false;
+ }
+ if (SeekFile64(fd, 0, SEEK_SET)) {
+ PERROR << "lseek failed";
+ return false;
+ }
+
+ uint32_t output_block;
+ if (!SectorToBlock(extent.target_data, &output_block)) {
+ return false;
+ }
+
+ uint64_t pos = 0;
+ uint64_t remaining = file_length;
+ while (remaining) {
+ uint32_t buffer[block_size_ / sizeof(uint32_t)];
+ size_t read_size = remaining >= sizeof(buffer) ? sizeof(buffer) : size_t(remaining);
+ if (!android::base::ReadFully(fd, buffer, sizeof(buffer))) {
+ PERROR << "read failed";
+ return false;
+ }
+ if (read_size != sizeof(buffer) || !HasFillValue(buffer, read_size / sizeof(uint32_t))) {
+ int rv = sparse_file_add_fd(file_.get(), fd, pos, read_size, output_block);
+ if (rv) {
+ LERROR << "sparse_file_add_fd failed with code: " << rv;
+ return false;
+ }
+ } else {
+ int rv = sparse_file_add_fill(file_.get(), buffer[0], read_size, output_block);
+ if (rv) {
+ LERROR << "sparse_file_add_fill failed with code: " << rv;
+ return false;
+ }
+ }
+ pos += read_size;
+ remaining -= read_size;
+ output_block++;
+ }
+
+ return true;
+}
+
+int SparseBuilder::OpenImageFile(const std::string& file) {
+ android::base::unique_fd source_fd(open(file.c_str(), O_RDONLY));
+ if (source_fd < 0) {
+ PERROR << "open image file failed: " << file;
+ return -1;
+ }
+
+ std::unique_ptr<sparse_file, decltype(&sparse_file_destroy)> source(
+ sparse_file_import(source_fd, true, true), sparse_file_destroy);
+ if (!source) {
+ int fd = source_fd.get();
+ temp_fds_.push_back(std::move(source_fd));
+ return fd;
+ }
+
+ char temp_file[PATH_MAX];
+ snprintf(temp_file, sizeof(temp_file), "%s/imageXXXXXX", P_tmpdir);
+ android::base::unique_fd temp_fd(mkstemp(temp_file));
+ if (temp_fd < 0) {
+ PERROR << "mkstemp failed";
+ return -1;
+ }
+ if (unlink(temp_file) < 0) {
+ PERROR << "unlink failed";
+ return -1;
+ }
+
+ // We temporarily unsparse the file, rather than try to merge its chunks.
+ int rv = sparse_file_write(source.get(), temp_fd, false, false, false);
+ if (rv) {
+ LERROR << "sparse_file_write failed with code: " << rv;
+ return -1;
+ }
+ temp_fds_.push_back(std::move(temp_fd));
+ return temp_fds_.back().get();
+}
+
+bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
+ const std::map<std::string, std::string>& images) {
if (block_size % LP_SECTOR_SIZE != 0) {
LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE;
return false;
@@ -198,7 +340,7 @@
return false;
}
- SparseBuilder builder(metadata, block_size);
+ SparseBuilder builder(metadata, block_size, images);
if (!builder.IsValid()) {
LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size;
return false;
@@ -206,7 +348,6 @@
if (!builder.Build()) {
return false;
}
-
return builder.Export(file);
}
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index a9f01c6..627aa8c 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -20,6 +20,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
#include <memory>
#include <string>
@@ -59,7 +60,8 @@
// Read/Write logical partition metadata to an image file, for diagnostics or
// flashing.
-bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size);
+bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
+ const std::map<std::string, std::string>& images);
bool WriteToImageFile(const char* file, const LpMetadata& metadata);
std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 6809445..b42a4c6 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -240,7 +240,8 @@
auto hardware = android::base::GetProperty("ro.hardware", "");
auto ueventd_configuration =
- ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", "/odm/ueventd.rc", hardware});
+ ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", "/odm/ueventd.rc",
+ "/ueventd." + hardware + ".rc"});
device_handler = DeviceHandler{std::move(ueventd_configuration.dev_permissions),
std::move(ueventd_configuration.sysfs_permissions),