Coordinator.cpp revision f7fa068fe10f7ba5df8c4352686e906486ebec0f
11aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber/* 21aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Copyright (C) 2016 The Android Open Source Project 31aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * 41aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 51aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * you may not use this file except in compliance with the License. 61aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * You may obtain a copy of the License at 71aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * 81aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 91aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * 101aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Unless required by applicable law or agreed to in writing, software 111aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 121aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * See the License for the specific language governing permissions and 141aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * limitations under the License. 151aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber */ 161aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber 175345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "Coordinator.h" 185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 1978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <dirent.h> 2078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <sys/stat.h> 215345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 225e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev#include <algorithm> 2378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <iterator> 2478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h> 265bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland#include <hidl-hash/Hash.h> 275715fedbd05231bf845e3a120c83b931b7f53aa3Steven Moreland#include <hidl-util/StringHelper.h> 2878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 2978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include "AST.h" 3078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include "Interface.h" 315345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 320d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huberextern android::status_t parseFile(android::AST *ast); 335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 3478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatic bool existdir(const char *name) { 3578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong DIR *dir = opendir(name); 3678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (dir == NULL) { 3778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return false; 3878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 3978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong closedir(dir); 4078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return true; 4178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 4278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 435345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android { 445345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 45dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::Coordinator( 46dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::vector<std::string> &packageRootPaths, 47f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland const std::vector<std::string> &packageRoots, 48f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland const std::string &rootPath) 49dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber : mPackageRootPaths(packageRootPaths), 50f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland mPackageRoots(packageRoots), 51f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland mRootPath(rootPath) { 52dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // empty 53dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber} 54dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber 55dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::~Coordinator() { 56dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // empty 57dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 585345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 59f619fc7bef5a4af1c196e125d70293d4af85e396Yifan HongAST *Coordinator::parse(const FQName &fqName, std::set<AST *> *parsedASTs, bool enforce) { 6068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber CHECK(fqName.isFullyQualified()); 6168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 62d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland auto it = mCache.find(fqName); 63d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland if (it != mCache.end()) { 64d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland AST *ast = (*it).second; 655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 6639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (ast != nullptr && parsedASTs != nullptr) { 6739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber parsedASTs->insert(ast); 6839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 6939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 7368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Add this to the cache immediately, so we can discover circular imports. 74d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = nullptr; 7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber AST *typesAST = nullptr; 7768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 7868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (fqName.name() != "types") { 7968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Any interface file implicitly imports its package's types.hal. 80fece6ecab34d69d38f57419d2500017a7136083eYifan Hong FQName typesName = fqName.getTypesForPackage(); 81f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong // Do not enforce on imports. 82f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong typesAST = parse(typesName, parsedASTs, false /* enforce */); 8368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 8468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // fall through. 8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 87f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland std::string path = mRootPath + getPackagePath(fqName); 88dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 8968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(fqName.name()); 9068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(".hal"); 915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 920d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber AST *ast = new AST(this, path); 9339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 9439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (typesAST != NULL) { 9539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // If types.hal for this AST's package existed, make it's defined 9639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // types available to the (about to be parsed) AST right away. 9739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast->addImportedAST(typesAST); 9839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 9939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 1000d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber status_t err = parseFile(ast); 10168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 10268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (err != OK) { 1036e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber // LOG(ERROR) << "parsing '" << path << "' FAILED."; 1046e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber 10568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber delete ast; 10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 1075345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 10839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 111a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->package().package() != fqName.package() 112a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber || ast->package().version() != fqName.version()) { 11370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 11470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not match expected package and/or " 1150d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "version.\n", 11670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str()); 117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 118a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 119a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else { 120a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber std::string ifaceName; 121a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->isInterface(&ifaceName)) { 122a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (fqName.name() == "types") { 12370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 12470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares an interface '%s' " 1250d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "instead of the expected types common to the package.\n", 12670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 12770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber ifaceName.c_str()); 128a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 129a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 130a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (ifaceName != fqName.name()) { 13170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 13270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not declare interface type " 1330d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "'%s'.\n", 13470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 13570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 136a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 137a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 138a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 139a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (fqName.name() != "types") { 14070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 14170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares types rather than the " 1420d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "expected interface type '%s'.\n", 14370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 14470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 145a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 146a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 1477c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber } else if (ast->containsInterfaces()) { 1487c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber fprintf(stderr, 1497c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "ERROR: types.hal file at '%s' declares at least one " 1507c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "interface type.\n", 1517c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber path.c_str()); 1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber 1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber err = UNKNOWN_ERROR; 154a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 155a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 156a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 157a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (err != OK) { 158a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber delete ast; 15939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 163a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (parsedASTs != nullptr) { parsedASTs->insert(ast); } 16539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 166fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // put it into the cache now, so that enforceRestrictionsOnPackage can 167fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // parse fqName. 168d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = ast; 1695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 170f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong if (enforce) { 171f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong // For each .hal file that hidl-gen parses, the whole package will be checked. 172f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong err = enforceRestrictionsOnPackage(fqName); 173f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong if (err != OK) { 174f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong mCache[fqName] = nullptr; 175f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong delete ast; 176f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong ast = nullptr; 177f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong return nullptr; 178f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong } 17978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 18078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 1815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 1825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 1835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 184dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator 185dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const { 1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.package().empty()); 1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.version().empty()); 1885345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Find the right package prefix and path for this FQName. For 190dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // example, if FQName is "android.hardware.nfc@1.0::INfc", and the 191dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix:root is set to [ "android.hardware:hardware/interfaces", 192dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "vendor.qcom.hardware:vendor/qcom"], then we will identify the 193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix "android.hardware" and the package root 194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "hardware/interfaces". 195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = mPackageRoots.begin(); 19762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland auto ret = mPackageRoots.end(); 198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber for (; it != mPackageRoots.end(); it++) { 19962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland if (!fqName.inPackage(*it)) { 20062709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland continue; 201dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 20262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 20362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret == mPackageRoots.end()) 20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << "Multiple package roots found for " << fqName.string() 20562709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << " (" << *it << " and " << *ret << ")"; 20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland ret = it; 208dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret != mPackageRoots.end()) 210401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber << "Unable to find package root for " << fqName.string(); 211dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 21262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland return ret; 213dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 214dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const { 216dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 217dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 218dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber return prefix; 219dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 220dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 2215bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const { 2225bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto it = findPackageRoot(fqName); 2235bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 2245bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev return root; 2255bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev} 2265bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev 227c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const { 228c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName); 229c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong} 230c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong 231dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath( 23297288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong const FQName &fqName, bool relative, bool sanitized) const { 233dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 234dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 235dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 236dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 237dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 238dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Make sure the prefix ends on a '.' and the root path on a '/' 239dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--prefix.end()) != '.') { 240dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber prefix += '.'; 241dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 242dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--root.end()) != '/') { 244dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber root += '/'; 245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix 248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "android.hardware.", the suffix is "nfc@1.0::IFoo". 249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::string packageSuffix = fqName.package().substr(prefix.length()); 2505345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 251881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber std::string packagePath; 252881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber if (!relative) { 253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber packagePath = root; 254881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber } 2555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2565345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t startPos = 0; 2575345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t dotPos; 2585345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) { 2595345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos, dotPos - startPos)); 2605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2615345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber startPos = dotPos + 1; 2635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 2645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK_LT(startPos + 1, packageSuffix.length()); 2655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos)); 2665345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 26897288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version()); 2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return packagePath; 2725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 274d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles( 275d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 276d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> *fileNames) const { 277d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->clear(); 2786cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 279f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland const std::string packagePath = mRootPath + getPackagePath(package); 280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber DIR *dir = opendir(packagePath.c_str()); 282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 283d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (dir == NULL) { 284261370ae8d57b78b01e4168abcf54d506f946f24Steven Moreland LOG(ERROR) << "Could not open package path: " << packagePath; 285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return -errno; 286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct dirent *ent; 289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((ent = readdir(dir)) != NULL) { 290d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (ent->d_type != DT_REG) { 2916cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber continue; 2926cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber } 2936cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix = ".hal"; 295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix_len = std::strlen(suffix); 296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto d_namelen = strlen(ent->d_name); 297e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (d_namelen < suffix_len 299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) { 300d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 301e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len)); 304e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 305e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber closedir(dir); 307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber dir = NULL; 308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 3095e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev std::sort(fileNames->begin(), fileNames->end(), 3105e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev [](const std::string& lhs, const std::string& rhs) -> bool { 3115e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (lhs == "types") { 3125e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return true; 3135e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3145e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (rhs == "types") { 3155e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return false; 3165e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3175e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return lhs < rhs; 3185e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev }); 3195e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev 320e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber return OK; 321e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber} 322e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 323aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector( 324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 325d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<FQName> *packageInterfaces) const { 326d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->clear(); 327d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 328d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> fileNames; 329d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber status_t err = getPackageInterfaceFiles(package, &fileNames); 330d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 331d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (err != OK) { 332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return err; 333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber for (const auto &fileName : fileNames) { 336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber FQName subFQName( 33790ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong package.package() + package.atVersion() + "::" + fileName); 338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (!subFQName.isValid()) { 340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber LOG(WARNING) 341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "Whole-package import encountered invalid filename '" 342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << fileName 343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "' in package " 344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << package.package() 34590ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong << package.atVersion(); 346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->push_back(subFQName); 351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 353d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return OK; 354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const { 357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string packageRoot = getPackageRoot(fqName); 358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (*(packageRoot.end()--) != '.') { 360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageRoot += '.'; 361d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::replace(packageRoot.begin(), packageRoot.end(), '.', '/'); 364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return packageRoot; // now converted to a path 366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 36878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 36978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName &fqName) { 37078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // need fqName to be something like android.hardware.foo@1.0. 37178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // name and valueName is ignored. 37278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (fqName.package().empty() || fqName.version().empty()) { 37378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string() 37478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": package or version is missing."; 37578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return BAD_VALUE; 37678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 37778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName package = fqName.getPackageAndVersion(); 37878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // look up cache. 37978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) { 38078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 38178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 38278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 38378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // enforce all rules. 384218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err; 385218625af26dea71d188361598c1f8c273716830eSteven Moreland 386218625af26dea71d188361598c1f8c273716830eSteven Moreland err = enforceMinorVersionUprevs(package); 387218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 388218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 389218625af26dea71d188361598c1f8c273716830eSteven Moreland } 390218625af26dea71d188361598c1f8c273716830eSteven Moreland 391218625af26dea71d188361598c1f8c273716830eSteven Moreland err = enforceHashes(package); 39278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (err != OK) { 39378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return err; 39478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 39578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 39678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // cache it so that it won't need to be enforced again. 39778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong mPackagesEnforced.insert(package); 39878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 39978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 40078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatus_t Coordinator::enforceMinorVersionUprevs(const FQName ¤tPackage) { 40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if(!currentPackage.hasVersion()) { 40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": missing version."; 40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 40878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentPackage.getPackageMinorVersion() == 0) { 40978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; // ignore for @x.0 41078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 41178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 41278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong bool hasPrevPackage = false; 41378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName prevPacakge = currentPackage; 41478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong while (prevPacakge.getPackageMinorVersion() > 0) { 41578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong prevPacakge = prevPacakge.downRev(); 416f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland if (existdir((mRootPath + getPackagePath(prevPacakge)).c_str())) { 41778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong hasPrevPackage = true; 41878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong break; 41978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (!hasPrevPackage) { 42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // no @x.z, where z < y, exist. 42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 42478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (prevPacakge != currentPackage.downRev()) { 42778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": Found package " << prevPacakge.string() << " but missing " 42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << currentPackage.downRev().string() << "; you cannot skip a minor version."; 43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong status_t err; 43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong std::vector<FQName> packageInterfaces; 43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (err != OK) { 43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return err; 43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 43978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 440fe07bffd9381605a6f96848a71489a4987363277Yifan Hong bool extendedInterface = false; 44178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong for (const FQName ¤tFQName : packageInterfaces) { 44278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentFQName.name() == "types") { 44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; // ignore types.hal 44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Assume that currentFQName == android.hardware.foo@2.2::IFoo. 44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Then prevFQName == android.hardware.foo@2.1::IFoo. 44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong const Interface *iface = nullptr; 44878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong AST *currentAST = parse(currentFQName); 44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentAST != nullptr) { 45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong iface = currentAST->getInterface(); 45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 45278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface == nullptr) { 453fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (currentAST == nullptr) { 454fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 455fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because it could not be found or parsed" 456fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " or " << currentPackage.string() 457fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " doesn't pass all requirements."; 458fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } else { 459fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 460fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because the file might contain more than one interface."; 461fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 46278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 46378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 46478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 46578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // android.hardware.foo@2.2::IFoo exists. Now make sure 46678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo extends @2.1::IFoo. If any interface IFoo in @2.2 46778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // ensures this, @2.2 passes the enforcement. 46878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName prevFQName(prevPacakge.package(), prevPacakge.version(), 46978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong currentFQName.name()); 47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface->superType() == nullptr) { 47178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo doesn't extend anything. (This is probably IBase.) 47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface->superType()->fqName() != prevFQName) { 47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo doesn't extend @2.1::IFoo. 476fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (iface->superType()->fqName().getPackageAndVersion() == 477fe07bffd9381605a6f96848a71489a4987363277Yifan Hong prevPacakge.getPackageAndVersion()) { 47878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 47978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": " << iface->fqName().string() << " extends " 48078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << iface->superType()->fqName().string() << ", which is not allowed."; 48178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 48278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 48378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo extends something from a package with a different package name. 48478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Check the next interface. 48578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 48678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 488fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // @2.2::IFoo passes. Check next interface. 489fe07bffd9381605a6f96848a71489a4987363277Yifan Hong extendedInterface = true; 49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes."; 49178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 493fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (!extendedInterface) { 494fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // No interface extends the interface with the same name in @x.(y-1). 495fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. " 496fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << "Requires at least one interface to extend an interface with the same name " 497fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << "from " << prevPacakge.string() << "."; 498fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return UNKNOWN_ERROR; 499fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 500fe07bffd9381605a6f96848a71489a4987363277Yifan Hong 501fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return OK; 50278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 50378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 504218625af26dea71d188361598c1f8c273716830eSteven Morelandstatus_t Coordinator::enforceHashes(const FQName ¤tPackage) { 505218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err = OK; 506218625af26dea71d188361598c1f8c273716830eSteven Moreland std::vector<FQName> packageInterfaces; 507218625af26dea71d188361598c1f8c273716830eSteven Moreland err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 508218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 509218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 510218625af26dea71d188361598c1f8c273716830eSteven Moreland } 511218625af26dea71d188361598c1f8c273716830eSteven Moreland 512218625af26dea71d188361598c1f8c273716830eSteven Moreland for (const FQName ¤tFQName : packageInterfaces) { 513218625af26dea71d188361598c1f8c273716830eSteven Moreland AST *ast = parse(currentFQName); 514218625af26dea71d188361598c1f8c273716830eSteven Moreland 515218625af26dea71d188361598c1f8c273716830eSteven Moreland if (ast == nullptr) { 516218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 517218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 518218625af26dea71d188361598c1f8c273716830eSteven Moreland } 519218625af26dea71d188361598c1f8c273716830eSteven Moreland 5205bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt"; 521218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string error; 5225bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error); 523218625af26dea71d188361598c1f8c273716830eSteven Moreland 524218625af26dea71d188361598c1f8c273716830eSteven Moreland if (error.size() > 0) { 525218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << error; 526218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 527218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 528218625af26dea71d188361598c1f8c273716830eSteven Moreland } 529218625af26dea71d188361598c1f8c273716830eSteven Moreland 530218625af26dea71d188361598c1f8c273716830eSteven Moreland // hash not define, interface not frozen 531218625af26dea71d188361598c1f8c273716830eSteven Moreland if (frozen.size() == 0) { 532218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 533218625af26dea71d188361598c1f8c273716830eSteven Moreland } 534218625af26dea71d188361598c1f8c273716830eSteven Moreland 535218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string currentHash = Hash::getHash(ast->getFilename()).hexString(); 536218625af26dea71d188361598c1f8c273716830eSteven Moreland 537218625af26dea71d188361598c1f8c273716830eSteven Moreland if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) { 538218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << currentFQName.string() << " has hash " << currentHash 539218625af26dea71d188361598c1f8c273716830eSteven Moreland << " which does not match hash on record. This interface has " 540218625af26dea71d188361598c1f8c273716830eSteven Moreland << "been frozen. Do not change it!"; 541218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 542218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 543218625af26dea71d188361598c1f8c273716830eSteven Moreland } 544218625af26dea71d188361598c1f8c273716830eSteven Moreland } 545218625af26dea71d188361598c1f8c273716830eSteven Moreland 546218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 547218625af26dea71d188361598c1f8c273716830eSteven Moreland} 548218625af26dea71d188361598c1f8c273716830eSteven Moreland 549d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) { 550d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber static const mode_t kMode = 0755; 551d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 552d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t start = 1; // Ignore leading '/' 553d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t slashPos; 554d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((slashPos = path.find("/", start)) != std::string::npos) { 555d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string partial = path.substr(0, slashPos); 556d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 557d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct stat st; 558d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (stat(partial.c_str(), &st) < 0) { 559d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (errno != ENOENT) { 560d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 561d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 562d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 563d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber int res = mkdir(partial.c_str(), kMode); 564d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (res < 0) { 565d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 566d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 567d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } else if (!S_ISDIR(st.st_mode)) { 568d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 569d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 570d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 571d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber start = slashPos + 1; 572d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 573d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 574d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return true; 575d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 576d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 5775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} // namespace android 5785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 579