Coordinator.cpp revision 19f11b53241877c442d31d9dc6b372e294a500d0
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 6628b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven MorelandAST *Coordinator::parse(const FQName &fqName, std::set<AST *> *parsedASTs, bool enforce) const { 6768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber CHECK(fqName.isFullyQualified()); 6868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 69d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland auto it = mCache.find(fqName); 70d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland if (it != mCache.end()) { 71d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland AST *ast = (*it).second; 725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 7339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (ast != nullptr && parsedASTs != nullptr) { 7439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber parsedASTs->insert(ast); 7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 8068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Add this to the cache immediately, so we can discover circular imports. 81d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = nullptr; 8239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 8339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber AST *typesAST = nullptr; 8468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (fqName.name() != "types") { 8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Any interface file implicitly imports its package's types.hal. 87fece6ecab34d69d38f57419d2500017a7136083eYifan Hong FQName typesName = fqName.getTypesForPackage(); 88f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong // Do not enforce on imports. 89f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong typesAST = parse(typesName, parsedASTs, false /* enforce */); 9068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 9168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // fall through. 9268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 9368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 94f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland std::string path = mRootPath + getPackagePath(fqName); 95dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 9668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(fqName.name()); 9768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(".hal"); 985345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 990d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber AST *ast = new AST(this, path); 10039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 10139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (typesAST != NULL) { 10239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // If types.hal for this AST's package existed, make it's defined 10339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // types available to the (about to be parsed) AST right away. 10439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast->addImportedAST(typesAST); 10539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 1070d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber status_t err = parseFile(ast); 10868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (err != OK) { 11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber delete ast; 11139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 1125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 11339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 11468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 11568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 116a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->package().package() != fqName.package() 117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber || ast->package().version() != fqName.version()) { 11870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 11970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not match expected package and/or " 1200d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "version.\n", 12170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str()); 122a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 123a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 124a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else { 12519f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland if (ast->isInterface()) { 126a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (fqName.name() == "types") { 12770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 12870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares an interface '%s' " 1290d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "instead of the expected types common to the package.\n", 13070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 13119f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland ast->getInterface()->localName().c_str()); 132a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 13419f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland } else if (ast->getInterface()->localName() != fqName.name()) { 13570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 13670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not declare interface type " 1370d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "'%s'.\n", 13870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 13970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 140a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 141a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 142a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 143a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (fqName.name() != "types") { 14470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 14570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares types rather than the " 1460d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "expected interface type '%s'.\n", 14770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 14870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 149a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 150a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 1517c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber } else if (ast->containsInterfaces()) { 1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber fprintf(stderr, 1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "ERROR: types.hal file at '%s' declares at least one " 1547c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber "interface type.\n", 1557c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber path.c_str()); 1567c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber 1577c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber err = UNKNOWN_ERROR; 158a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 159a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 161a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (err != OK) { 162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber delete ast; 16339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 164a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 166a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 167a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 16839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (parsedASTs != nullptr) { parsedASTs->insert(ast); } 16939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 170fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // put it into the cache now, so that enforceRestrictionsOnPackage can 171fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // parse fqName. 172d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = ast; 1735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 174f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong if (enforce) { 175f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong // For each .hal file that hidl-gen parses, the whole package will be checked. 176f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong err = enforceRestrictionsOnPackage(fqName); 177f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong if (err != OK) { 178f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong mCache[fqName] = nullptr; 179f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong delete ast; 180f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong ast = nullptr; 181f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong return nullptr; 182f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong } 18378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 18478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 188dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator 189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const { 1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.package().empty()); 1915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.version().empty()); 1925345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Find the right package prefix and path for this FQName. For 194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // example, if FQName is "android.hardware.nfc@1.0::INfc", and the 195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix:root is set to [ "android.hardware:hardware/interfaces", 196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "vendor.qcom.hardware:vendor/qcom"], then we will identify the 197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix "android.hardware" and the package root 198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "hardware/interfaces". 199dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = mPackageRoots.begin(); 20162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland auto ret = mPackageRoots.end(); 202dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber for (; it != mPackageRoots.end(); it++) { 20362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland if (!fqName.inPackage(*it)) { 20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland continue; 205dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret == mPackageRoots.end()) 20862709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << "Multiple package roots found for " << fqName.string() 20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland << " (" << *it << " and " << *ret << ")"; 21062709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland 21162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland ret = it; 212dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 21362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland CHECK(ret != mPackageRoots.end()) 214401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber << "Unable to find package root for " << fqName.string(); 215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 21662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland return ret; 217dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 218dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 219dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const { 220dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 221dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 222dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber return prefix; 223dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 224dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 2255bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const { 2265bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto it = findPackageRoot(fqName); 2275bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 2285bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev return root; 2295bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev} 2305bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev 231c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const { 232c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName); 233c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong} 234c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong 235dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath( 23697288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong const FQName &fqName, bool relative, bool sanitized) const { 237dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 238dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 239dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 240dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 241dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 242dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Make sure the prefix ends on a '.' and the root path on a '/' 243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--prefix.end()) != '.') { 244dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber prefix += '.'; 245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--root.end()) != '/') { 248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber root += '/'; 249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 250dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 251dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix 252dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "android.hardware.", the suffix is "nfc@1.0::IFoo". 253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::string packageSuffix = fqName.package().substr(prefix.length()); 2545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 255881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber std::string packagePath; 256881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber if (!relative) { 257dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber packagePath = root; 258881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber } 2595345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t startPos = 0; 2615345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t dotPos; 2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) { 2635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos, dotPos - startPos)); 2645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2665345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber startPos = dotPos + 1; 2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 2685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK_LT(startPos + 1, packageSuffix.length()); 2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos)); 2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 27297288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version()); 2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return packagePath; 2765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 2775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 278d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles( 279d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> *fileNames) const { 281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->clear(); 2826cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 283f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland const std::string packagePath = mRootPath + getPackagePath(package); 284d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber DIR *dir = opendir(packagePath.c_str()); 286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (dir == NULL) { 288028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland fprintf(stderr, 289028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland "ERROR: Could not open package path %s for package %s:\n%s\n", 290028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland getPackagePath(package).c_str(), 291028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland package.string().c_str(), 292028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland packagePath.c_str()); 293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return -errno; 294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct dirent *ent; 297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((ent = readdir(dir)) != NULL) { 298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (ent->d_type != DT_REG) { 2996cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber continue; 3006cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber } 3016cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix = ".hal"; 303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix_len = std::strlen(suffix); 304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto d_namelen = strlen(ent->d_name); 305e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (d_namelen < suffix_len 307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) { 308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 309e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len)); 312e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 313e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber closedir(dir); 315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber dir = NULL; 316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 3175e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev std::sort(fileNames->begin(), fileNames->end(), 3185e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev [](const std::string& lhs, const std::string& rhs) -> bool { 3195e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (lhs == "types") { 3205e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return true; 3215e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3225e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (rhs == "types") { 3235e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return false; 3245e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 3255e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return lhs < rhs; 3265e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev }); 3275e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev 328e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber return OK; 329e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber} 330e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 331aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector( 332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<FQName> *packageInterfaces) const { 334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->clear(); 335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> fileNames; 337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber status_t err = getPackageInterfaceFiles(package, &fileNames); 338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (err != OK) { 340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return err; 341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber for (const auto &fileName : fileNames) { 344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber FQName subFQName( 34590ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong package.package() + package.atVersion() + "::" + fileName); 346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (!subFQName.isValid()) { 348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber LOG(WARNING) 349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "Whole-package import encountered invalid filename '" 350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << fileName 351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "' in package " 352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << package.package() 35390ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong << package.atVersion(); 354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->push_back(subFQName); 359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 361d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return OK; 362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const { 365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string packageRoot = getPackageRoot(fqName); 366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (*(packageRoot.end()--) != '.') { 368d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageRoot += '.'; 369d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 370d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 371d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::replace(packageRoot.begin(), packageRoot.end(), '.', '/'); 372d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 373d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return packageRoot; // now converted to a path 374d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 375d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 37678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 37728b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName &fqName) const { 37878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // need fqName to be something like android.hardware.foo@1.0. 37978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // name and valueName is ignored. 38078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (fqName.package().empty() || fqName.version().empty()) { 38178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string() 38278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": package or version is missing."; 38378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return BAD_VALUE; 38478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 38578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName package = fqName.getPackageAndVersion(); 38678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // look up cache. 38778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) { 38878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 38978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 39078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 39178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // enforce all rules. 392218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err; 393218625af26dea71d188361598c1f8c273716830eSteven Moreland 394218625af26dea71d188361598c1f8c273716830eSteven Moreland err = enforceMinorVersionUprevs(package); 395218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 396218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 397218625af26dea71d188361598c1f8c273716830eSteven Moreland } 398218625af26dea71d188361598c1f8c273716830eSteven Moreland 399218625af26dea71d188361598c1f8c273716830eSteven Moreland err = enforceHashes(package); 40078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (err != OK) { 40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return err; 40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // cache it so that it won't need to be enforced again. 40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong mPackagesEnforced.insert(package); 40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 40878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 40928b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceMinorVersionUprevs(const FQName ¤tPackage) const { 41078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if(!currentPackage.hasVersion()) { 41178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 41278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": missing version."; 41378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 41478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 41578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 41678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentPackage.getPackageMinorVersion() == 0) { 41778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; // ignore for @x.0 41878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 41978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong bool hasPrevPackage = false; 42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName prevPacakge = currentPackage; 42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong while (prevPacakge.getPackageMinorVersion() > 0) { 42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong prevPacakge = prevPacakge.downRev(); 424f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland if (existdir((mRootPath + getPackagePath(prevPacakge)).c_str())) { 42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong hasPrevPackage = true; 42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong break; 42778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (!hasPrevPackage) { 43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // no @x.z, where z < y, exist. 43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return OK; 43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (prevPacakge != currentPackage.downRev()) { 43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": Found package " << prevPacakge.string() << " but missing " 43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << currentPackage.downRev().string() << "; you cannot skip a minor version."; 43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 43978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 44078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 44178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong status_t err; 44278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong std::vector<FQName> packageInterfaces; 44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (err != OK) { 44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return err; 44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 448fe07bffd9381605a6f96848a71489a4987363277Yifan Hong bool extendedInterface = false; 44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong for (const FQName ¤tFQName : packageInterfaces) { 45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentFQName.name() == "types") { 45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; // ignore types.hal 45278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 45378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Assume that currentFQName == android.hardware.foo@2.2::IFoo. 45478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Then prevFQName == android.hardware.foo@2.1::IFoo. 45578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong const Interface *iface = nullptr; 45678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong AST *currentAST = parse(currentFQName); 45778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (currentAST != nullptr) { 45878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong iface = currentAST->getInterface(); 45978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 46078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface == nullptr) { 461fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (currentAST == nullptr) { 462fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 463fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because it could not be found or parsed" 464fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " or " << currentPackage.string() 465fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " doesn't pass all requirements."; 466fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } else { 467fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(WARNING) << "Warning: Skipping " << currentFQName.string() 468fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << " because the file might contain more than one interface."; 469fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 47178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // android.hardware.foo@2.2::IFoo exists. Now make sure 47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo extends @2.1::IFoo. If any interface IFoo in @2.2 47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // ensures this, @2.2 passes the enforcement. 47678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong FQName prevFQName(prevPacakge.package(), prevPacakge.version(), 47778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong currentFQName.name()); 47878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface->superType() == nullptr) { 47978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo doesn't extend anything. (This is probably IBase.) 48078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 48178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 48278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong if (iface->superType()->fqName() != prevFQName) { 48378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo doesn't extend @2.1::IFoo. 484fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (iface->superType()->fqName().getPackageAndVersion() == 485fe07bffd9381605a6f96848a71489a4987363277Yifan Hong prevPacakge.getPackageAndVersion()) { 48678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string() 48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << ": " << iface->fqName().string() << " extends " 48878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong << iface->superType()->fqName().string() << ", which is not allowed."; 48978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong return UNKNOWN_ERROR; 49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 49178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // @2.2::IFoo extends something from a package with a different package name. 49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong // Check the next interface. 49378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong continue; 49478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 49578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 496fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // @2.2::IFoo passes. Check next interface. 497fe07bffd9381605a6f96848a71489a4987363277Yifan Hong extendedInterface = true; 49878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes."; 49978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong } 50078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 501fe07bffd9381605a6f96848a71489a4987363277Yifan Hong if (!extendedInterface) { 502fe07bffd9381605a6f96848a71489a4987363277Yifan Hong // No interface extends the interface with the same name in @x.(y-1). 503fe07bffd9381605a6f96848a71489a4987363277Yifan Hong LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. " 504fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << "Requires at least one interface to extend an interface with the same name " 505fe07bffd9381605a6f96848a71489a4987363277Yifan Hong << "from " << prevPacakge.string() << "."; 506fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return UNKNOWN_ERROR; 507fe07bffd9381605a6f96848a71489a4987363277Yifan Hong } 508fe07bffd9381605a6f96848a71489a4987363277Yifan Hong 509fe07bffd9381605a6f96848a71489a4987363277Yifan Hong return OK; 51078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong} 51178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong 51228b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceHashes(const FQName ¤tPackage) const { 513218625af26dea71d188361598c1f8c273716830eSteven Moreland status_t err = OK; 514218625af26dea71d188361598c1f8c273716830eSteven Moreland std::vector<FQName> packageInterfaces; 515218625af26dea71d188361598c1f8c273716830eSteven Moreland err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces); 516218625af26dea71d188361598c1f8c273716830eSteven Moreland if (err != OK) { 517218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 518218625af26dea71d188361598c1f8c273716830eSteven Moreland } 519218625af26dea71d188361598c1f8c273716830eSteven Moreland 520218625af26dea71d188361598c1f8c273716830eSteven Moreland for (const FQName ¤tFQName : packageInterfaces) { 521218625af26dea71d188361598c1f8c273716830eSteven Moreland AST *ast = parse(currentFQName); 522218625af26dea71d188361598c1f8c273716830eSteven Moreland 523218625af26dea71d188361598c1f8c273716830eSteven Moreland if (ast == nullptr) { 524218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 525218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 526218625af26dea71d188361598c1f8c273716830eSteven Moreland } 527218625af26dea71d188361598c1f8c273716830eSteven Moreland 5285bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt"; 529218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string error; 5305bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error); 531218625af26dea71d188361598c1f8c273716830eSteven Moreland 532218625af26dea71d188361598c1f8c273716830eSteven Moreland if (error.size() > 0) { 533218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << error; 534218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 535218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 536218625af26dea71d188361598c1f8c273716830eSteven Moreland } 537218625af26dea71d188361598c1f8c273716830eSteven Moreland 538218625af26dea71d188361598c1f8c273716830eSteven Moreland // hash not define, interface not frozen 539218625af26dea71d188361598c1f8c273716830eSteven Moreland if (frozen.size() == 0) { 540218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 541218625af26dea71d188361598c1f8c273716830eSteven Moreland } 542218625af26dea71d188361598c1f8c273716830eSteven Moreland 543218625af26dea71d188361598c1f8c273716830eSteven Moreland std::string currentHash = Hash::getHash(ast->getFilename()).hexString(); 544218625af26dea71d188361598c1f8c273716830eSteven Moreland 545218625af26dea71d188361598c1f8c273716830eSteven Moreland if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) { 546218625af26dea71d188361598c1f8c273716830eSteven Moreland LOG(ERROR) << currentFQName.string() << " has hash " << currentHash 547218625af26dea71d188361598c1f8c273716830eSteven Moreland << " which does not match hash on record. This interface has " 548218625af26dea71d188361598c1f8c273716830eSteven Moreland << "been frozen. Do not change it!"; 549218625af26dea71d188361598c1f8c273716830eSteven Moreland err = UNKNOWN_ERROR; 550218625af26dea71d188361598c1f8c273716830eSteven Moreland continue; 551218625af26dea71d188361598c1f8c273716830eSteven Moreland } 552218625af26dea71d188361598c1f8c273716830eSteven Moreland } 553218625af26dea71d188361598c1f8c273716830eSteven Moreland 554218625af26dea71d188361598c1f8c273716830eSteven Moreland return err; 555218625af26dea71d188361598c1f8c273716830eSteven Moreland} 556218625af26dea71d188361598c1f8c273716830eSteven Moreland 557d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) { 558d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber static const mode_t kMode = 0755; 559d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 560d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t start = 1; // Ignore leading '/' 561d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t slashPos; 562d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((slashPos = path.find("/", start)) != std::string::npos) { 563d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string partial = path.substr(0, slashPos); 564d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 565d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct stat st; 566d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (stat(partial.c_str(), &st) < 0) { 567d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (errno != ENOENT) { 568d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 569d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 570d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 571d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber int res = mkdir(partial.c_str(), kMode); 572d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (res < 0) { 573d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 574d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 575d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } else if (!S_ISDIR(st.st_mode)) { 576d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 577d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 578d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 579d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber start = slashPos + 1; 580d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 581d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 582d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return true; 583d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 584d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 5855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} // namespace android 5865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 587