Coordinator.cpp revision aa1868371f36507ff8f6337ec0e6bb02b2620981
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 195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "AST.h" 205345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 215e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev#include <algorithm> 225345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h> 23dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber#include <iterator> 24a72e0d2be173cebf62f728b9d215808bd862f219Iliyan Malchev#include <dirent.h> 25d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber#include <sys/stat.h> 265345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 270d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huberextern android::status_t parseFile(android::AST *ast); 285345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 295345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android { 305345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 31dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::Coordinator( 32dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::vector<std::string> &packageRootPaths, 33dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::vector<std::string> &packageRoots) 34dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber : mPackageRootPaths(packageRootPaths), 35dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber mPackageRoots(packageRoots) { 36dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // empty 37dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber} 38dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber 39dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::~Coordinator() { 40dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // empty 41dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 425345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 4339fa71827738f6c1340e4523946fe9bf704eef3aAndreas HuberAST *Coordinator::parse(const FQName &fqName, std::set<AST *> *parsedASTs) { 4468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber CHECK(fqName.isFullyQualified()); 4568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 46d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland auto it = mCache.find(fqName); 47d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland if (it != mCache.end()) { 48d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland AST *ast = (*it).second; 495345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 5039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (ast != nullptr && parsedASTs != nullptr) { 5139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber parsedASTs->insert(ast); 5239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 5339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 565345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 5768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Add this to the cache immediately, so we can discover circular imports. 58d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = nullptr; 5939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 6039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber AST *typesAST = nullptr; 6168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 6268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (fqName.name() != "types") { 6368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // Any interface file implicitly imports its package's types.hal. 6468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber FQName typesName(fqName.package(), fqName.version(), "types"); 6539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber typesAST = parse(typesName, parsedASTs); 6668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 6768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber // fall through. 6868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 6968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 70dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber std::string path = getPackagePath(fqName); 71dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 7268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(fqName.name()); 7368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber path.append(".hal"); 745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 750d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber AST *ast = new AST(this, path); 7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 7739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (typesAST != NULL) { 7839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // If types.hal for this AST's package existed, make it's defined 7939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber // types available to the (about to be parsed) AST right away. 8039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast->addImportedAST(typesAST); 8139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber } 8239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 830d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber status_t err = parseFile(ast); 8468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber if (err != OK) { 866e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber // LOG(ERROR) << "parsing '" << path << "' FAILED."; 876e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber 8868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber delete ast; 8939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 9139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 9268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber } 9368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber 94a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->package().package() != fqName.package() 95a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber || ast->package().version() != fqName.version()) { 9670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 9770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not match expected package and/or " 980d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "version.\n", 9970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str()); 100a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 101a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 102a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else { 103a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber std::string ifaceName; 104a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (ast->isInterface(&ifaceName)) { 105a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (fqName.name() == "types") { 10670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 10770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares an interface '%s' " 1080d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "instead of the expected types common to the package.\n", 10970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 11070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber ifaceName.c_str()); 111a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 112a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 113a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (ifaceName != fqName.name()) { 11470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 11570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' does not declare interface type " 1160d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "'%s'.\n", 11770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 11870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 119a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 120a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 121a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 122a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } else if (fqName.name() != "types") { 12370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fprintf(stderr, 12470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber "ERROR: File at '%s' declares types rather than the " 1250d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber "expected interface type '%s'.\n", 12670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber path.c_str(), 12770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber fqName.name().c_str()); 128a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 129a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber err = UNKNOWN_ERROR; 130a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 131a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 132a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber if (err != OK) { 134a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber delete ast; 13539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber ast = nullptr; 136a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 13739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber return nullptr; 138a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber } 139a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber 14039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber if (parsedASTs != nullptr) { parsedASTs->insert(ast); } 14139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber 142d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland mCache[fqName] = ast; 1435345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 1445345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return ast; 1455345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 1465345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 147dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator 148dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const { 1495345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.package().empty()); 1505345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK(!fqName.version().empty()); 1515345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 152dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Find the right package prefix and path for this FQName. For 153dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // example, if FQName is "android.hardware.nfc@1.0::INfc", and the 154dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix:root is set to [ "android.hardware:hardware/interfaces", 155dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "vendor.qcom.hardware:vendor/qcom"], then we will identify the 156dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // prefix "android.hardware" and the package root 157dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "hardware/interfaces". 158dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 159dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // TODO: This now returns on the first match. Throw an error if 160dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // there are multiple hits. 161dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = mPackageRoots.begin(); 162dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber for (; it != mPackageRoots.end(); it++) { 163dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if (fqName.package().find(*it) != std::string::npos) { 164dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber break; 165dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 166dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 167401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber CHECK(it != mPackageRoots.end()) 168401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber << "Unable to find package root for " << fqName.string(); 169dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 170dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber return it; 171dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 172dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 173dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const { 174dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 175dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 176dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber return prefix; 177dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber} 178dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 1795bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const { 1805bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto it = findPackageRoot(fqName); 1815bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 1825bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev return root; 1835bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev} 1845bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev 185dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath( 186dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const FQName &fqName, bool relative) const { 187dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 188dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto it = findPackageRoot(fqName); 189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto prefix = *it; 190dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)]; 191dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 192dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Make sure the prefix ends on a '.' and the root path on a '/' 193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--prefix.end()) != '.') { 194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber prefix += '.'; 195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber if ((*--root.end()) != '/') { 198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber root += '/'; 199dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber } 200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber 201dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix 202dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber // "android.hardware.", the suffix is "nfc@1.0::IFoo". 203dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber const std::string packageSuffix = fqName.package().substr(prefix.length()); 2045345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 205881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber std::string packagePath; 206881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber if (!relative) { 207dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber packagePath = root; 208881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber } 2095345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2105345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t startPos = 0; 2115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber size_t dotPos; 2125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) { 2135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos, dotPos - startPos)); 2145345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2155345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2165345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber startPos = dotPos + 1; 2175345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber } 2185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK_LT(startPos + 1, packageSuffix.length()); 2195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(packageSuffix.substr(startPos)); 2205345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2215345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2225345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber CHECK_EQ(fqName.version().find('@'), 0u); 2235345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append(fqName.version().substr(1)); 2245345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber packagePath.append("/"); 2255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 2265345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber return packagePath; 2275345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} 2285345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 229d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles( 230d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 231d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> *fileNames) const { 232d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->clear(); 2336cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 234d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const std::string packagePath = getPackagePath(package); 235d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 236d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber DIR *dir = opendir(packagePath.c_str()); 237d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 238d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (dir == NULL) { 239261370ae8d57b78b01e4168abcf54d506f946f24Steven Moreland LOG(ERROR) << "Could not open package path: " << packagePath; 240d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return -errno; 241d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 242d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 243d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct dirent *ent; 244d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((ent = readdir(dir)) != NULL) { 245d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (ent->d_type != DT_REG) { 2466cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber continue; 2476cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber } 2486cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber 249d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix = ".hal"; 250d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto suffix_len = std::strlen(suffix); 251d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const auto d_namelen = strlen(ent->d_name); 252e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 253d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (d_namelen < suffix_len 254d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) { 255d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 256e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 257d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 258d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len)); 259e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber } 260e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 261d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber closedir(dir); 262d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber dir = NULL; 263d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 2645e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev std::sort(fileNames->begin(), fileNames->end(), 2655e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev [](const std::string& lhs, const std::string& rhs) -> bool { 2665e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (lhs == "types") { 2675e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return true; 2685e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 2695e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev if (rhs == "types") { 2705e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return false; 2715e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev } 2725e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev return lhs < rhs; 2735e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev }); 2745e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev 275e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber return OK; 276e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber} 277e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber 278aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector( 279d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber const FQName &package, 280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<FQName> *packageInterfaces) const { 281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->clear(); 282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 283d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::vector<std::string> fileNames; 284d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber status_t err = getPackageInterfaceFiles(package, &fileNames); 285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (err != OK) { 287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return err; 288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 290d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber for (const auto &fileName : fileNames) { 291d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber FQName subFQName( 292d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber package.package() + package.version() + "::" + fileName); 293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (!subFQName.isValid()) { 295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber LOG(WARNING) 296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "Whole-package import encountered invalid filename '" 297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << fileName 298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << "' in package " 299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << package.package() 300d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber << package.version(); 301d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber continue; 303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageInterfaces->push_back(subFQName); 306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return OK; 309d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const { 312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string packageRoot = getPackageRoot(fqName); 313d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (*(packageRoot.end()--) != '.') { 315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber packageRoot += '.'; 316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 317d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 318d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::replace(packageRoot.begin(), packageRoot.end(), '.', '/'); 319d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 320d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return packageRoot; // now converted to a path 321d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 322d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 323d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber// static 324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) { 325d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber static const mode_t kMode = 0755; 326d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 327d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t start = 1; // Ignore leading '/' 328d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber size_t slashPos; 329d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber while ((slashPos = path.find("/", start)) != std::string::npos) { 330d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber std::string partial = path.substr(0, slashPos); 331d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber struct stat st; 333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (stat(partial.c_str(), &st) < 0) { 334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (errno != ENOENT) { 335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber int res = mkdir(partial.c_str(), kMode); 339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber if (res < 0) { 340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } else if (!S_ISDIR(st.st_mode)) { 343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return false; 344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber start = slashPos + 1; 347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber } 348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber return true; 350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber} 351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber 3525345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber} // namespace android 3535345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber 354