|  | /* | 
|  | * Copyright (C) 2020 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | #define LOG_TAG "libapexutil" | 
|  |  | 
|  | #include "apexutil.h" | 
|  |  | 
|  | #include <dirent.h> | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include <android-base/file.h> | 
|  | #include <android-base/logging.h> | 
|  | #include <android-base/result.h> | 
|  | #include <apex_manifest.pb.h> | 
|  |  | 
|  | using ::android::base::Error; | 
|  | using ::android::base::ReadFileToString; | 
|  | using ::android::base::Result; | 
|  | using ::apex::proto::ApexManifest; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | Result<ApexManifest> ParseApexManifest(const std::string &manifest_path) { | 
|  | std::string content; | 
|  | if (!ReadFileToString(manifest_path, &content)) { | 
|  | return Error() << "Failed to read manifest file: " << manifest_path; | 
|  | } | 
|  | ApexManifest manifest; | 
|  | if (!manifest.ParseFromString(content)) { | 
|  | return Error() << "Can't parse APEX manifest: " << manifest_path; | 
|  | } | 
|  | return manifest; | 
|  | } | 
|  |  | 
|  | } // namespace | 
|  |  | 
|  | namespace android { | 
|  | namespace apex { | 
|  |  | 
|  | std::map<std::string, ApexManifest> | 
|  | GetActivePackages(const std::string &apex_root) { | 
|  | std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(apex_root.c_str()), | 
|  | closedir); | 
|  | if (!dir) { | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | std::map<std::string, ApexManifest> apexes; | 
|  | dirent *entry; | 
|  | while ((entry = readdir(dir.get())) != nullptr) { | 
|  | if (entry->d_name[0] == '.') | 
|  | continue; | 
|  | if (entry->d_type != DT_DIR) | 
|  | continue; | 
|  | if (strchr(entry->d_name, '@') != nullptr) | 
|  | continue; | 
|  | std::string apex_path = apex_root + "/" + entry->d_name; | 
|  | auto manifest = ParseApexManifest(apex_path + "/apex_manifest.pb"); | 
|  | if (manifest.ok()) { | 
|  | apexes.emplace(std::move(apex_path), std::move(*manifest)); | 
|  | } else { | 
|  | LOG(WARNING) << manifest.error(); | 
|  | } | 
|  | } | 
|  | return apexes; | 
|  | } | 
|  |  | 
|  | } // namespace apex | 
|  | } // namespace android |