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 5925c8166fa1e40db71497bf9cbc67d313e5f808edSteven Morelandvoid Coordinator::addDefaultPackagePath(const std::string& root, const std::string& path) { 6025c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland if (std::find(mPackageRoots.begin(), mPackageRoots.end(), root) == mPackageRoots.end()) { 6125c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland mPackageRoots.push_back(root); 6225c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland mPackageRootPaths.push_back(path); 6325c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland } 6425c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland} 6525c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland 66c59326ec5bcae86051571a0824e39e01fc2c4053Steven MorelandAST* Coordinator::parse(const FQName& fqName, std::set<AST*>* parsedASTs, 67c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland Enforce enforcement) const { 6868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber CHECK(fqName.isFullyQualified()); 6968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 70d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland auto it = mCache.find(fqName); 71d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland if (it != mCache.end()) { 72d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland AST *ast = (*it).second; 735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 7439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (ast != nullptr && parsedASTs != nullptr) { 7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber parsedASTs->insert(ast); 7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 7739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 805345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 8168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Add this to the cache immediately, so we can discover circular imports. 82d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = nullptr; 8339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 8439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber AST *typesAST = nullptr; 8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (fqName.name() != "types") { 8768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Any interface file implicitly imports its package's types.hal. 88fece6ecab34d69d38f57419d2500017a7136083eYifan Hong FQName typesName = fqName.getTypesForPackage(); 89a407b7d4ce6cfa8385e30b8a7e7e06e92a1a3681Steven Moreland // Do not enforce on imports. Do not add imports' imports to this AST. 90a407b7d4ce6cfa8385e30b8a7e7e06e92a1a3681Steven Moreland typesAST = parse(typesName, nullptr, Enforce::NONE); 9168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 9268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // fall through. 9368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 9468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 95b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland std::string path = getAbsolutePackagePath(fqName); 96dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 9768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(fqName.name()); 9868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(".hal"); 995345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 1000d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber AST *ast = new AST(this, path); 10139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 10239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (typesAST != NULL) { 10339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // If types.hal for this AST's package existed, make it's defined 10439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // types available to the (about to be parsed) AST right away. 10539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast->addImportedAST(typesAST); 10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 10739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 1080d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber status_t err = parseFile(ast); 10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (err != OK) { 11168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber delete ast; 11239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 1135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 11439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 11568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 11668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->package().package() != fqName.package() 118a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber || ast->package().version() != fqName.version()) { 11970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 12070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not match expected package and/or " 1210d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "version.\n", 12270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str()); 123a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 124a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 125a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else { 12619f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland if (ast->isInterface()) { 127a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (fqName.name() == "types") { 12870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 12970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares an interface '%s' " 1300d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "instead of the expected types common to the package.\n", 13170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 13219f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland ast->getInterface()->localName().c_str()); 133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 134a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 13519f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland } else if (ast->getInterface()->localName() != fqName.name()) { 13670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 13770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not declare interface type " 1380d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "'%s'.\n", 13970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 14070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 141a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 142a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 143a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 144a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (fqName.name() != "types") { 14570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 14670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares types rather than the " 1470d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "expected interface type '%s'.\n", 14870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 14970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 150a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 151a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber } else if (ast->containsInterfaces()) { 1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber fprintf(stderr, 1547c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "ERROR: types.hal file at '%s' declares at least one " 1557c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "interface type.\n", 1567c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber path.c_str()); 1577c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber 1587c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber err = UNKNOWN_ERROR; 159a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 161a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (err != OK) { 163a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber delete ast; 16439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 165a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 167a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 168a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (parsedASTs != nullptr) { parsedASTs->insert(ast); } 17039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 171fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // put it into the cache now, so that enforceRestrictionsOnPackage can 172fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // parse fqName. 173d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = ast; 1745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 175c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland // For each .hal file that hidl-gen parses, the whole package will be checked. 176c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland err = enforceRestrictionsOnPackage(fqName, enforcement); 177c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland if (err != OK) { 178c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland mCache[fqName] = nullptr; 179c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland delete ast; 180c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland ast = nullptr; 181c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland return nullptr; 18278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 18378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 1845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 187dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator 188dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const { 1895345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.package().empty()); 1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 191dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Find the right package prefix and path for this FQName. For 192dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // example, if FQName is "android.hardware.nfc@1.0::INfc", and the 193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix:root is set to [ "android.hardware:hardware/interfaces", 194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "vendor.qcom.hardware:vendor/qcom"], then we will identify the 195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix "android.hardware" and the package root 196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "hardware/interfaces". 197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = mPackageRoots.begin(); 19962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland auto ret = mPackageRoots.end(); 200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber for (; it != mPackageRoots.end(); it++) { 20162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland if (!fqName.inPackage(*it)) { 20262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland continue; 203dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 20562709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret == mPackageRoots.end()) 20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << "Multiple package roots found for " << fqName.string() 20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << " (" << *it << " and " << *ret << ")"; 20862709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland ret = it; 210dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 21162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret != mPackageRoots.end()) 212401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber << "Unable to find package root for " << fqName.string(); 213dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 21462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland return ret; 215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 216dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 217b90d327e82303b3e7abaa5fca6a83e168598a162Steven Morelandstd::string Coordinator::getAbsolutePackagePath(const FQName& fqName) const { 218b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland const std::string packagePath = getPackagePath(fqName); 219b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland 220b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland if (StringHelper::StartsWith(packagePath, "/") || mRootPath.empty()) { 221b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland return packagePath; 222b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland } 223b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland 224b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland return StringHelper::RTrim(mRootPath, "/") + "/" + packagePath; 225b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland} 226b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland 227dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const { 228dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 229dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 230dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber return prefix; 231dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 232dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 2335bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const { 2345bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto it = findPackageRoot(fqName); 2355bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 2365bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev return root; 2375bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev} 2385bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev 239c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const { 240c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName); 241c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong} 242c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong 243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath( 24497288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong const FQName &fqName, bool relative, bool sanitized) const { 245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 250dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Make sure the prefix ends on a '.' and the root path on a '/' 251dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--prefix.end()) != '.') { 252dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber prefix += '.'; 253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 254dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 255dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--root.end()) != '/') { 256dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber root += '/'; 257dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 258dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 259dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix 260dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "android.hardware.", the suffix is "nfc@1.0::IFoo". 261dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::string packageSuffix = fqName.package().substr(prefix.length()); 2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 263881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber std::string packagePath; 264881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber if (!relative) { 265dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber packagePath = root; 266881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber } 2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t startPos = 0; 2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t dotPos; 2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) { 2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos, dotPos - startPos)); 2725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber startPos = dotPos + 1; 2755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 2765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK_LT(startPos + 1, packageSuffix.length()); 2775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos)); 2785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 28097288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version()); 2815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return packagePath; 2845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 2855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles( 287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> *fileNames) const { 289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->clear(); 2906cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 291b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland const std::string packagePath = getAbsolutePackagePath(package); 292d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber DIR *dir = opendir(packagePath.c_str()); 294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (dir == NULL) { 296028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland fprintf(stderr, 297028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland "ERROR: Could not open package path %s for package %s:\n%s\n", 298028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland getPackagePath(package).c_str(), 299028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland package.string().c_str(), 300028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland packagePath.c_str()); 301d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return -errno; 302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct dirent *ent; 305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((ent = readdir(dir)) != NULL) { 306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (ent->d_type != DT_REG) { 3076cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber continue; 3086cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber } 3096cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix = ".hal"; 311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix_len = std::strlen(suffix); 312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto d_namelen = strlen(ent->d_name); 313e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (d_namelen < suffix_len 315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) { 316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 317e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 318d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 319d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len)); 320e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 321e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 322d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber closedir(dir); 323d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber dir = NULL; 324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 3255e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev std::sort(fileNames->begin(), fileNames->end(), 3265e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev [](const std::string& lhs, const std::string& rhs) -> bool { 3275e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (lhs == "types") { 3285e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return true; 3295e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3305e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (rhs == "types") { 3315e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return false; 3325e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3335e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return lhs < rhs; 3345e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev }); 3355e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev 336e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber return OK; 337e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber} 338e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 339aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector( 340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<FQName> *packageInterfaces) const { 342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->clear(); 343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> fileNames; 345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber status_t err = getPackageInterfaceFiles(package, &fileNames); 346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (err != OK) { 348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return err; 349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber for (const auto &fileName : fileNames) { 352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber FQName subFQName( 35390ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong package.package() + package.atVersion() + "::" + fileName); 354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (!subFQName.isValid()) { 356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber LOG(WARNING) 357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "Whole-package import encountered invalid filename '" 358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << fileName 359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "' in package " 360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << package.package() 36190ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong << package.atVersion(); 362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->push_back(subFQName); 367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 368d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 369d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return OK; 370d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 371d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 372d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const { 373d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string packageRoot = getPackageRoot(fqName); 374d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 375d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (*(packageRoot.end()--) != '.') { 376d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageRoot += '.'; 377d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 378d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 379d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::replace(packageRoot.begin(), packageRoot.end(), '.', '/'); 380d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 381d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return packageRoot; // now converted to a path 382d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 383d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 384c59326ec5bcae86051571a0824e39e01fc2c4053Steven Morelandstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName& fqName, 385c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland Enforce enforcement) const { 386c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland CHECK(enforcement == Enforce::FULL || enforcement == Enforce::NO_HASH || 387c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland enforcement == Enforce::NONE); 38878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 38978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // need fqName to be something like android.hardware.foo@1.0. 39078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // name and valueName is ignored. 39178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (fqName.package().empty() || fqName.version().empty()) { 39278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string() 39378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": package or version is missing."; 39478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return BAD_VALUE; 39578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 396c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland 397c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland if (enforcement == Enforce::NONE) { 398c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland return OK; 399c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland } 400c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland 40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName package = fqName.getPackageAndVersion(); 40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // look up cache. 40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) { 40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // enforce all rules. 408218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err; 409218625af26dea71d188361598c1f8c273716830eSteven Moreland 410218625af26dea71d188361598c1f8c273716830eSteven Moreland err = enforceMinorVersionUprevs(package); 411218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 412218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 413218625af26dea71d188361598c1f8c273716830eSteven Moreland } 414218625af26dea71d188361598c1f8c273716830eSteven Moreland 415c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland if (enforcement != Enforce::NO_HASH) { 416c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland err = enforceHashes(package); 417c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland if (err != OK) { 418c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland return err; 419c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland } 42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // cache it so that it won't need to be enforced again. 42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong mPackagesEnforced.insert(package); 42478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 42728b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceMinorVersionUprevs(const FQName ¤tPackage) const { 42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if(!currentPackage.hasVersion()) { 42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": missing version."; 43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentPackage.getPackageMinorVersion() == 0) { 43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; // ignore for @x.0 43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong bool hasPrevPackage = false; 439ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland FQName prevPackage = currentPackage; 440ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland while (prevPackage.getPackageMinorVersion() > 0) { 441ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland prevPackage = prevPackage.downRev(); 442b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland if (existdir(getAbsolutePackagePath(prevPackage).c_str())) { 44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong hasPrevPackage = true; 44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong break; 44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (!hasPrevPackage) { 44878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // no @x.z, where z < y, exist. 44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 452ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland if (prevPackage != currentPackage.downRev()) { 45378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 454ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland << ": Found package " << prevPackage.string() << " but missing " 45578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << currentPackage.downRev().string() << "; you cannot skip a minor version."; 45678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 45778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 45878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 45978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong status_t err; 46078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong std::vector<FQName> packageInterfaces; 46178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 46278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (err != OK) { 46378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return err; 46478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 46578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 466fe07bffd9381605a6f96848a71489a4987363277Yifan Hong bool extendedInterface = false; 46778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong for (const FQName ¤tFQName : packageInterfaces) { 46878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentFQName.name() == "types") { 46978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; // ignore types.hal 47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 471ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong const Interface *iface = nullptr; 47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong AST *currentAST = parse(currentFQName); 47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentAST != nullptr) { 47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong iface = currentAST->getInterface(); 47678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 47778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface == nullptr) { 478fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (currentAST == nullptr) { 479fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 480fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because it could not be found or parsed" 481fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " or " << currentPackage.string() 482fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " doesn't pass all requirements."; 483fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } else { 484fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 485fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because the file might contain more than one interface."; 486fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 48878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 48978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface->superType() == nullptr) { 491ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland CHECK(iface->isIBase()); 49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 49378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 494ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 495ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland // Assume that currentFQName == android.hardware.foo@2.2::IFoo. 496ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland FQName lastFQName(prevPackage.package(), prevPackage.version(), 497ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland currentFQName.name()); 498ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland AST *lastAST = parse(lastFQName); 499ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 500ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland for (; lastFQName.getPackageMinorVersion() > 0 && 501ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland (lastAST == nullptr || lastAST->getInterface() == nullptr) 502ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland ; lastFQName = lastFQName.downRev(), lastAST = parse(lastFQName)) { 503ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland // nothing 504ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland } 505ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 506ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland // Then lastFQName == android.hardware.foo@2.1::IFoo or 507ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland // lastFQName == android.hardware.foo@2.0::IFoo if 2.1 doesn't exist. 508ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 509ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland bool lastFQNameExists = lastAST != nullptr && lastAST->getInterface() != nullptr; 510ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 511ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland if (iface->superType()->fqName() != lastFQName && lastFQNameExists) { 512ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 513ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland << ": " << iface->fqName().string() << " extends " 514ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland << iface->superType()->fqName().string() 515ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland << ", which is not allowed. It must extend " << lastFQName.string(); 516ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland return UNKNOWN_ERROR; 517ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland } 518ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland 519ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland // at least one interface must extend the previous version 520ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland if (lastFQName.getPackageAndVersion() == prevPackage.getPackageAndVersion()) { 521ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland extendedInterface = true; 52278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 52378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 52478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes."; 52578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 52678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 527fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (!extendedInterface) { 528fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // No interface extends the interface with the same name in @x.(y-1). 529fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. " 530fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << "Requires at least one interface to extend an interface with the same name " 531ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland << "from " << prevPackage.string() << "."; 532fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return UNKNOWN_ERROR; 533fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 534fe07bffd9381605a6f96848a71489a4987363277Yifan Hong 535fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return OK; 53678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 53778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 53828b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceHashes(const FQName ¤tPackage) const { 539218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err = OK; 540218625af26dea71d188361598c1f8c273716830eSteven Moreland std::vector<FQName> packageInterfaces; 541218625af26dea71d188361598c1f8c273716830eSteven Moreland err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 542218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 543218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 544218625af26dea71d188361598c1f8c273716830eSteven Moreland } 545218625af26dea71d188361598c1f8c273716830eSteven Moreland 546218625af26dea71d188361598c1f8c273716830eSteven Moreland for (const FQName ¤tFQName : packageInterfaces) { 547218625af26dea71d188361598c1f8c273716830eSteven Moreland AST *ast = parse(currentFQName); 548218625af26dea71d188361598c1f8c273716830eSteven Moreland 549218625af26dea71d188361598c1f8c273716830eSteven Moreland if (ast == nullptr) { 550218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 551218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 552218625af26dea71d188361598c1f8c273716830eSteven Moreland } 553218625af26dea71d188361598c1f8c273716830eSteven Moreland 5545bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt"; 555218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string error; 5565bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error); 557218625af26dea71d188361598c1f8c273716830eSteven Moreland 558218625af26dea71d188361598c1f8c273716830eSteven Moreland if (error.size() > 0) { 559218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << error; 560218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 561218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 562218625af26dea71d188361598c1f8c273716830eSteven Moreland } 563218625af26dea71d188361598c1f8c273716830eSteven Moreland 564218625af26dea71d188361598c1f8c273716830eSteven Moreland // hash not define, interface not frozen 565218625af26dea71d188361598c1f8c273716830eSteven Moreland if (frozen.size() == 0) { 566218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 567218625af26dea71d188361598c1f8c273716830eSteven Moreland } 568218625af26dea71d188361598c1f8c273716830eSteven Moreland 569218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string currentHash = Hash::getHash(ast->getFilename()).hexString(); 570218625af26dea71d188361598c1f8c273716830eSteven Moreland 571218625af26dea71d188361598c1f8c273716830eSteven Moreland if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) { 572218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << currentFQName.string() << " has hash " << currentHash 573218625af26dea71d188361598c1f8c273716830eSteven Moreland << " which does not match hash on record. This interface has " 574218625af26dea71d188361598c1f8c273716830eSteven Moreland << "been frozen. Do not change it!"; 575218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 576218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 577218625af26dea71d188361598c1f8c273716830eSteven Moreland } 578218625af26dea71d188361598c1f8c273716830eSteven Moreland } 579218625af26dea71d188361598c1f8c273716830eSteven Moreland 580218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 581218625af26dea71d188361598c1f8c273716830eSteven Moreland} 582218625af26dea71d188361598c1f8c273716830eSteven Moreland 583d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) { 584d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber static const mode_t kMode = 0755; 585d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 586d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t start = 1; // Ignore leading '/' 587d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t slashPos; 588d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((slashPos = path.find("/", start)) != std::string::npos) { 589d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string partial = path.substr(0, slashPos); 590d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 591d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct stat st; 592d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (stat(partial.c_str(), &st) < 0) { 593d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (errno != ENOENT) { 594d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 595d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 596d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 597d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber int res = mkdir(partial.c_str(), kMode); 598d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (res < 0) { 599d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 600d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 601d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } else if (!S_ISDIR(st.st_mode)) { 602d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 603d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 604d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 605d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber start = slashPos + 1; 606d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 607d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 608d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return true; 609d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 610d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 6115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} // namespace android 6125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 613