|
| 1 | +#include <sys/types.h> |
| 2 | +#include <dirent.h> |
| 3 | + |
| 4 | +#include <cerrno> |
1 | 5 | #include <cstdio> |
| 6 | +#include <cstring> |
2 | 7 |
|
3 | 8 | #include <coreclrhost.h> |
4 | 9 |
|
@@ -62,10 +67,98 @@ auto Host::zip_scan_callback (std::string_view const& apk_path, int apk_fd, dyna |
62 | 67 | return false; |
63 | 68 | } |
64 | 69 |
|
| 70 | +[[gnu::always_inline]] |
| 71 | +void Host::scan_filesystem_for_assemblies_and_libraries () noexcept |
| 72 | +{ |
| 73 | + std::string const& native_lib_dir = AndroidSystem::get_native_libraries_dir (); |
| 74 | + log_debug (LOG_ASSEMBLY, "Looking for assemblies in '{}'", native_lib_dir); |
| 75 | + |
| 76 | + DIR *lib_dir = opendir (native_lib_dir.c_str ()); |
| 77 | + if (lib_dir == nullptr) [[unlikely]] { |
| 78 | + Helpers::abort_application ( |
| 79 | + LOG_ASSEMBLY, |
| 80 | + std::format ( |
| 81 | + "Unable to open native library directory '{}'. {}", |
| 82 | + native_lib_dir, |
| 83 | + std::strerror (errno) |
| 84 | + ) |
| 85 | + ); |
| 86 | + } |
| 87 | + |
| 88 | + int dir_fd = dirfd (lib_dir); |
| 89 | + if (dir_fd < 0) [[unlikely]] { |
| 90 | + Helpers::abort_application ( |
| 91 | + LOG_ASSEMBLY, |
| 92 | + std::format ( |
| 93 | + "Unable to obtain file descriptor for opened directory '{}'. {}", |
| 94 | + native_lib_dir, |
| 95 | + std::strerror (errno) |
| 96 | + ) |
| 97 | + ); |
| 98 | + } |
| 99 | + |
| 100 | + do { |
| 101 | + errno = 0; |
| 102 | + dirent *cur = readdir (lib_dir); |
| 103 | + if (cur == nullptr) { |
| 104 | + if (errno != 0) { |
| 105 | + log_warn (LOG_ASSEMBLY, "Failed to open a directory entry from '{}': {}", native_lib_dir, std::strerror (errno)); |
| 106 | + continue; // No harm, keep going |
| 107 | + } |
| 108 | + break; // we're done |
| 109 | + } |
| 110 | + |
| 111 | + // We can ignore the obvious entries |
| 112 | + if (cur->d_name[0] == '.') { |
| 113 | + continue; |
| 114 | + } |
| 115 | + |
| 116 | + if (!found_assembly_store) { |
| 117 | + found_assembly_store = Constants::assembly_store_file_name.compare (cur->d_name) == 0; |
| 118 | + if (!found_assembly_store) { |
| 119 | + continue; |
| 120 | + } |
| 121 | + |
| 122 | + log_debug (LOG_ASSEMBLY, "Found assembly store in '{}/{}'", native_lib_dir, Constants::assembly_store_file_name); |
| 123 | + int store_fd = openat (dir_fd, cur->d_name, O_RDONLY); |
| 124 | + if (store_fd < 0) { |
| 125 | + Helpers::abort_application ( |
| 126 | + LOG_ASSEMBLY, |
| 127 | + std::format ( |
| 128 | + "Unable to open assembly store '{}/{}' for reading. {}", |
| 129 | + native_lib_dir, |
| 130 | + Constants::assembly_store_file_name, |
| 131 | + std::strerror (errno) |
| 132 | + ) |
| 133 | + ); |
| 134 | + } |
| 135 | + |
| 136 | + auto file_size = Util::get_file_size_at (dir_fd, cur->d_name); |
| 137 | + if (!file_size) { |
| 138 | + // get_file_size_at logged errno for us |
| 139 | + Helpers::abort_application ( |
| 140 | + LOG_ASSEMBLY, |
| 141 | + std::format ( |
| 142 | + "Unable to map assembly store '{}/{}'", |
| 143 | + native_lib_dir, |
| 144 | + Constants::assembly_store_file_name |
| 145 | + ) |
| 146 | + ); |
| 147 | + } |
| 148 | + |
| 149 | + AssemblyStore::map (store_fd, cur->d_name, 0, static_cast<uint32_t>(file_size.value ())); |
| 150 | + close (store_fd); |
| 151 | + break; // we've found all we need |
| 152 | + } |
| 153 | + } while (true); |
| 154 | + closedir (lib_dir); |
| 155 | +} |
| 156 | + |
65 | 157 | void Host::gather_assemblies_and_libraries (jstring_array_wrapper& runtimeApks, bool have_split_apks) |
66 | 158 | { |
67 | 159 | if (!AndroidSystem::is_embedded_dso_mode_enabled ()) { |
68 | | - Helpers::abort_application ("Filesystem mode not supported yet."); |
| 160 | + scan_filesystem_for_assemblies_and_libraries (); |
| 161 | + return; |
69 | 162 | } |
70 | 163 |
|
71 | 164 | int64_t apk_count = static_cast<int64_t>(runtimeApks.get_length ()); |
|
0 commit comments