1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #define LOG_TAG "libapexutil" 17 18 #include "apexutil.h" 19 20 #include <dirent.h> 21 22 #include <memory> 23 24 #include <android-base/file.h> 25 #include <android-base/logging.h> 26 #include <android-base/result.h> 27 #include <apex_manifest.pb.h> 28 29 using ::android::base::Error; 30 using ::android::base::ReadFileToString; 31 using ::android::base::Result; 32 using ::apex::proto::ApexManifest; 33 34 namespace { 35 36 Result<ApexManifest> ParseApexManifest(const std::string &manifest_path) { 37 std::string content; 38 if (!ReadFileToString(manifest_path, &content)) { 39 return Error() << "Failed to read manifest file: " << manifest_path; 40 } 41 ApexManifest manifest; 42 if (!manifest.ParseFromString(content)) { 43 return Error() << "Can't parse APEX manifest: " << manifest_path; 44 } 45 return manifest; 46 } 47 48 } // namespace 49 50 namespace android { 51 namespace apex { 52 53 std::map<std::string, ApexManifest> 54 GetActivePackages(const std::string &apex_root) { 55 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(apex_root.c_str()), 56 closedir); 57 if (!dir) { 58 return {}; 59 } 60 61 std::map<std::string, ApexManifest> apexes; 62 dirent *entry; 63 while ((entry = readdir(dir.get())) != nullptr) { 64 if (entry->d_name[0] == '.') 65 continue; 66 if (entry->d_type != DT_DIR) 67 continue; 68 if (strchr(entry->d_name, '@') != nullptr) 69 continue; 70 std::string apex_path = apex_root + "/" + entry->d_name; 71 auto manifest = ParseApexManifest(apex_path + "/apex_manifest.pb"); 72 if (manifest.ok()) { 73 apexes.emplace(std::move(apex_path), std::move(*manifest)); 74 } else { 75 LOG(WARNING) << manifest.error(); 76 } 77 } 78 return apexes; 79 } 80 81 } // namespace apex 82 } // namespace android 83