1 /* 2 * Copyright (C) 2019 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 17 #include "linkerconfig/librarylistloader.h" 18 19 #include <android-base/result.h> 20 #include <android-base/strings.h> 21 #include <algorithm> 22 #include <fstream> 23 #include <iterator> 24 #include <set> 25 #include <sstream> 26 #include <unordered_map> 27 28 #include "linkerconfig/environment.h" 29 #include "linkerconfig/log.h" 30 31 using LibraryList = std::set<std::string>; 32 33 using android::base::Result; 34 35 namespace { 36 std::unordered_map<std::string, LibraryList> library_file_cache; 37 Result<LibraryList> GetLibrariesFromFile(std::string file_path) { 38 auto cached_data = library_file_cache.find(file_path); 39 if (cached_data != library_file_cache.end()) { 40 return cached_data->second; 41 } 42 43 std::string library_name; 44 LibraryList library_list; 45 std::ifstream library_file(file_path.c_str(), std::ifstream::in); 46 47 if (!library_file) { 48 return ErrnoErrorf("Failed to open file {}", file_path); 49 } 50 51 while (std::getline(library_file, library_name)) { 52 library_name = android::base::Trim(library_name); 53 if (!library_name.empty()) { 54 library_list.insert(library_name); 55 } 56 } 57 58 library_file_cache.insert({file_path, library_list}); 59 60 return library_list; 61 } 62 } // namespace 63 64 namespace android { 65 namespace linkerconfig { 66 namespace generator { 67 std::string GetLibrariesString(const std::string& library_file_path) { 68 auto library_list_result = GetLibrariesFromFile(library_file_path); 69 if (library_list_result.ok()) { 70 return android::base::Join(*library_list_result, ':'); 71 } else { 72 // Consider unavailable library file as empty 73 LOG(WARNING) << library_list_result.error(); 74 return ""; 75 } 76 } 77 78 std::string GetPublicLibrariesString( 79 const std::string& library_file_path, 80 const std::string& private_library_file_path) { 81 auto library_list = GetLibrariesFromFile(library_file_path); 82 auto private_library_list = GetLibrariesFromFile(private_library_file_path); 83 84 if (!library_list.ok()) { 85 // Consider unavailable library file as empty 86 LOG(WARNING) << library_list.error(); 87 return ""; 88 } 89 90 if (!private_library_list.ok()) { 91 // No private library found. All libraries are public 92 LOG(WARNING) << private_library_list.error(); 93 return android::base::Join(*library_list, ':'); 94 } 95 96 LibraryList public_library_list; 97 98 std::set_difference( 99 library_list->begin(), 100 library_list->end(), 101 private_library_list->begin(), 102 private_library_list->end(), 103 std::inserter(public_library_list, public_library_list.begin())); 104 105 return android::base::Join(public_library_list, ':'); 106 } 107 108 std::string GetPrivateLibrariesString( 109 const std::string& library_file_path, 110 const std::string& private_library_file_path) { 111 auto library_list = GetLibrariesFromFile(library_file_path); 112 auto private_library_list = GetLibrariesFromFile(private_library_file_path); 113 114 if (!library_list.ok()) { 115 // Consider unavailable library file as empty 116 LOG(WARNING) << library_list.error(); 117 return ""; 118 } 119 120 if (!private_library_list.ok()) { 121 // No private library found. All libraries are public 122 LOG(WARNING) << private_library_list.error(); 123 return ""; 124 } 125 126 LibraryList private_only_library_list; 127 128 std::set_intersection(library_list->begin(), 129 library_list->end(), 130 private_library_list->begin(), 131 private_library_list->end(), 132 std::inserter(private_only_library_list, 133 private_only_library_list.begin())); 134 135 return android::base::Join(private_only_library_list, ':'); 136 } 137 } // namespace generator 138 } // namespace linkerconfig 139 } // namespace android 140