aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaochu Liu <xiaochu@chromium.org>2018-07-23 11:54:02 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-08-01 00:05:33 -0700
commitd88bc3e668d298b215c48fd45cff96901cb6bd85 (patch)
tree6a63a817c581549143346d96551c45ac27f9a7bd
parenta722b427ac5223635eafde4551dbb2db749ce252 (diff)
downloadlibbrillo-d88bc3e668d298b215c48fd45cff96901cb6bd85.tar.gz
move manifest* from imageloader to libbrillo
We move them to libbrillo so it could be shared by imageloader&dlcservice. BUG=chromium:866203 TEST=unittest Change-Id: Id6e1f898d69c5cb1d4d291147482248ee3578f03 Reviewed-on: https://chromium-review.googlesource.com/1147249 Commit-Ready: Xiaochu Liu <xiaochu@chromium.org> Tested-by: Xiaochu Liu <xiaochu@chromium.org> Reviewed-by: Xiaochu Liu <xiaochu@chromium.org>
-rw-r--r--brillo/imageloader/manifest.cc188
-rw-r--r--brillo/imageloader/manifest.h52
-rw-r--r--brillo/imageloader/manifest_unittest.cc49
-rw-r--r--libbrillo.gypi2
4 files changed, 291 insertions, 0 deletions
diff --git a/brillo/imageloader/manifest.cc b/brillo/imageloader/manifest.cc
new file mode 100644
index 0000000..92789df
--- /dev/null
+++ b/brillo/imageloader/manifest.cc
@@ -0,0 +1,188 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <brillo/imageloader/manifest.h>
+
+#include <memory>
+#include <utility>
+
+#include <base/json/json_string_value_serializer.h>
+#include <base/strings/string_number_conversions.h>
+
+namespace brillo {
+namespace imageloader {
+
+namespace {
+// The current version of the manifest file.
+constexpr int kCurrentManifestVersion = 1;
+// The name of the version field in the manifest.
+constexpr char kManifestVersionField[] = "manifest-version";
+// The name of the component version field in the manifest.
+constexpr char kVersionField[] = "version";
+// The name of the field containing the image hash.
+constexpr char kImageHashField[] = "image-sha256-hash";
+// The name of the bool field indicating whether component is removable.
+constexpr char kIsRemovableField[] = "is-removable";
+// The name of the metadata field.
+constexpr char kMetadataField[] = "metadata";
+// The name of the field containing the table hash.
+constexpr char kTableHashField[] = "table-sha256-hash";
+// The name of the optional field containing the file system type.
+constexpr char kFSType[] = "fs-type";
+
+bool GetSHA256FromString(const std::string& hash_str,
+ std::vector<uint8_t>* bytes) {
+ if (!base::HexStringToBytes(hash_str, bytes))
+ return false;
+ return bytes->size() == 32;
+}
+
+// Ensure the metadata entry is a dictionary mapping strings to strings and
+// parse it into |out_metadata| and return true if so.
+bool ParseMetadata(const base::Value* metadata_element,
+ std::map<std::string, std::string>* out_metadata) {
+ DCHECK(out_metadata);
+
+ const base::DictionaryValue* metadata_dict = nullptr;
+ if (!metadata_element->GetAsDictionary(&metadata_dict))
+ return false;
+
+ base::DictionaryValue::Iterator it(*metadata_dict);
+ for (; !it.IsAtEnd(); it.Advance()) {
+ std::string parsed_value;
+ if (!it.value().GetAsString(&parsed_value)) {
+ LOG(ERROR) << "Key \"" << it.key() << "\" did not map to string value";
+ return false;
+ }
+
+ (*out_metadata)[it.key()] = std::move(parsed_value);
+ }
+
+ return true;
+}
+
+} // namespace
+
+Manifest::Manifest() {}
+
+bool Manifest::ParseManifest(const std::string& manifest_raw) {
+ // Now deserialize the manifest json and read out the rest of the component.
+ int error_code;
+ std::string error_message;
+ JSONStringValueDeserializer deserializer(manifest_raw);
+ std::unique_ptr<base::Value> value =
+ deserializer.Deserialize(&error_code, &error_message);
+
+ if (!value) {
+ LOG(ERROR) << "Could not deserialize the manifest file. Error "
+ << error_code << ": " << error_message;
+ return false;
+ }
+
+ base::DictionaryValue* manifest_dict = nullptr;
+ if (!value->GetAsDictionary(&manifest_dict)) {
+ LOG(ERROR) << "Could not parse manifest file as JSON.";
+ return false;
+ }
+
+ // This will have to be changed if the manifest version is bumped.
+ int version;
+ if (!manifest_dict->GetInteger(kManifestVersionField, &version)) {
+ LOG(ERROR) << "Could not parse manifest version field from manifest.";
+ return false;
+ }
+ if (version != kCurrentManifestVersion) {
+ LOG(ERROR) << "Unsupported version of the manifest.";
+ return false;
+ }
+ manifest_version_ = version;
+
+ std::string image_hash_str;
+ if (!manifest_dict->GetString(kImageHashField, &image_hash_str)) {
+ LOG(ERROR) << "Could not parse image hash from manifest.";
+ return false;
+ }
+
+ if (!GetSHA256FromString(image_hash_str, &(image_sha256_))) {
+ LOG(ERROR) << "Could not convert image hash to bytes.";
+ return false;
+ }
+
+ std::string table_hash_str;
+ if (!manifest_dict->GetString(kTableHashField, &table_hash_str)) {
+ LOG(ERROR) << "Could not parse table hash from manifest.";
+ return false;
+ }
+
+ if (!GetSHA256FromString(table_hash_str, &(table_sha256_))) {
+ LOG(ERROR) << "Could not convert table hash to bytes.";
+ return false;
+ }
+
+ if (!manifest_dict->GetString(kVersionField, &(version_))) {
+ LOG(ERROR) << "Could not parse component version from manifest.";
+ return false;
+ }
+
+ // The fs_type field is optional, and squashfs by default.
+ fs_type_ = FileSystem::kSquashFS;
+ std::string fs_type;
+ if (manifest_dict->GetString(kFSType, &fs_type)) {
+ if (fs_type == "ext4") {
+ fs_type_ = FileSystem::kExt4;
+ } else if (fs_type == "squashfs") {
+ fs_type_ = FileSystem::kSquashFS;
+ } else {
+ LOG(ERROR) << "Unsupported file system type: " << fs_type;
+ return false;
+ }
+ }
+
+ if (!manifest_dict->GetBoolean(kIsRemovableField, &(is_removable_))) {
+ // If is_removable field does not exist, by default it is false.
+ is_removable_ = false;
+ }
+
+ // Copy out the metadata, if it's there.
+ const base::Value* metadata = nullptr;
+ if (manifest_dict->Get(kMetadataField, &metadata)) {
+ if (!ParseMetadata(metadata, &(metadata_))) {
+ LOG(ERROR) << "Manifest metadata was malformed";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int Manifest::manifest_version() const {
+ return manifest_version_;
+}
+
+const std::vector<uint8_t>& Manifest::image_sha256() const {
+ return image_sha256_;
+}
+
+const std::vector<uint8_t>& Manifest::table_sha256() const {
+ return table_sha256_;
+}
+
+const std::string& Manifest::version() const {
+ return version_;
+}
+
+FileSystem Manifest::fs_type() const {
+ return fs_type_;
+}
+
+bool Manifest::is_removable() const {
+ return is_removable_;
+}
+
+const std::map<std::string, std::string> Manifest::metadata() const {
+ return metadata_;
+}
+
+} // namespace imageloader
+} // namespace brillo
diff --git a/brillo/imageloader/manifest.h b/brillo/imageloader/manifest.h
new file mode 100644
index 0000000..cfd7c3a
--- /dev/null
+++ b/brillo/imageloader/manifest.h
@@ -0,0 +1,52 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBBRILLO_BRILLO_IMAGELOADER_MANIFEST_H_
+#define LIBBRILLO_BRILLO_IMAGELOADER_MANIFEST_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+#include <brillo/brillo_export.h>
+
+namespace brillo {
+namespace imageloader {
+
+// The supported file systems for images.
+enum class FileSystem { kExt4, kSquashFS };
+
+// A class to parse and store imageloader.json manifest.
+class BRILLO_EXPORT Manifest {
+ public:
+ Manifest();
+ // Parse the manifest raw string. Return true if successful.
+ bool ParseManifest(const std::string& manifest_raw);
+ // Getters for manifest fields:
+ int manifest_version() const;
+ const std::vector<uint8_t>& image_sha256() const;
+ const std::vector<uint8_t>& table_sha256() const;
+ const std::string& version() const;
+ FileSystem fs_type() const;
+ bool is_removable() const;
+ const std::map<std::string, std::string> metadata() const;
+
+ private:
+ // Manifest fields:
+ int manifest_version_;
+ std::vector<uint8_t> image_sha256_;
+ std::vector<uint8_t> table_sha256_;
+ std::string version_;
+ FileSystem fs_type_;
+ bool is_removable_;
+ std::map<std::string, std::string> metadata_;
+
+ DISALLOW_COPY_AND_ASSIGN(Manifest);
+};
+
+} // namespace imageloader
+} // namespace brillo
+
+#endif // LIBBRILLO_BRILLO_IMAGELOADER_MANIFEST_H_
diff --git a/brillo/imageloader/manifest_unittest.cc b/brillo/imageloader/manifest_unittest.cc
new file mode 100644
index 0000000..bca7e8b
--- /dev/null
+++ b/brillo/imageloader/manifest_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+
+#include <brillo/imageloader/manifest.h>
+
+namespace brillo {
+namespace imageloader {
+
+class ManifestTest : public testing::Test {};
+
+TEST_F(ManifestTest, ParseManifest) {
+ const std::string fs_type = R"("ext4")";
+ const std::string is_removable = R"(true)";
+ const std::string image_sha256_hash =
+ R"("4CF41BD11362CCB4707FB93939DBB5AC48745EDFC9DC8D7702852FFAA81B3B3F")";
+ const std::string table_sha256_hash =
+ R"("0E11DA3D7140C6B95496787F50D15152434EBA22B60443BFA7E054FF4C799276")";
+ const std::string version = R"("9824.0.4")";
+ const std::string manifest_version = R"(1)";
+ const std::string manifest_raw = std::string() + R"(
+ {
+ "fs-type":)" + fs_type + R"(,
+ "is-removable":)" + is_removable +
+ R"(,
+ "image-sha256-hash":)" + image_sha256_hash +
+ R"(,
+ "table-sha256-hash":)" + table_sha256_hash +
+ R"(,
+ "version":)" + version + R"(,
+ "manifest-version":)" + manifest_version +
+ R"(
+ }
+ )";
+ brillo::imageloader::Manifest manifest;
+ // Parse the manifest raw string.
+ ASSERT_TRUE(manifest.ParseManifest(manifest_raw));
+ EXPECT_EQ(manifest.fs_type(), FileSystem::kExt4);
+ EXPECT_EQ(manifest.is_removable(), true);
+ EXPECT_NE(manifest.image_sha256().size(), 0);
+ EXPECT_NE(manifest.table_sha256().size(), 0);
+ EXPECT_NE(manifest.version().size(), 0);
+ EXPECT_EQ(manifest.manifest_version(), 1);
+}
+
+} // namespace imageloader
+} // namespace brillo
diff --git a/libbrillo.gypi b/libbrillo.gypi
index ed63e64..05d95e6 100644
--- a/libbrillo.gypi
+++ b/libbrillo.gypi
@@ -65,6 +65,7 @@
'brillo/errors/error_codes.cc',
'brillo/file_utils.cc',
'brillo/flag_helper.cc',
+ 'brillo/imageloader/manifest.cc',
'brillo/key_value_store.cc',
'brillo/message_loops/base_message_loop.cc',
'brillo/message_loops/message_loop.cc',
@@ -381,6 +382,7 @@
'brillo/http/http_request_unittest.cc',
'brillo/http/http_transport_curl_unittest.cc',
'brillo/http/http_utils_unittest.cc',
+ 'brillo/imageloader/manifest_unittest.cc',
'brillo/key_value_store_unittest.cc',
'brillo/map_utils_unittest.cc',
'brillo/message_loops/base_message_loop_unittest.cc',