/** * When the framework is not found, display detailed error message * about available frameworks and installation of new framework. */ void handle_missing_framework_error(const pal::string_t& fx_name, const pal::string_t& fx_version, const pal::string_t& fx_dir) { pal::string_t fx_ver_dirs = get_directory(fx_dir); // Display the error message about missing FX. trace::error(_X("The specified framework '%s', version '%s' was not found."), fx_name.c_str(), fx_version.c_str()); trace::error(_X(" - Check application dependencies and target a framework version installed at:")); trace::error(_X(" %s"), fx_ver_dirs.c_str()); // Gather the list of versions installed at the shared FX location. bool is_print_header = true; std::vector<pal::string_t> versions; pal::readdir(fx_ver_dirs, &versions); for (const auto& ver : versions) { // Make sure we filter out any non-version folders at shared FX location. fx_ver_t parsed(-1, -1, -1); if (fx_ver_t::parse(ver, &parsed, false)) { // Print banner only once before printing the versions if (is_print_header) { trace::error(_X(" - The following versions are installed:")); is_print_header = false; } trace::error(_X(" %s"), ver.c_str()); } } trace::error(_X(" - Alternatively, install the framework version '%s'."), fx_version.c_str()); }
bool starts_with(const pal::string_t& value, const pal::string_t& prefix, bool match_case) { if (prefix.empty()) { // Cannot start with an empty string. return false; } auto cmp = match_case ? pal::strncmp : pal::strncasecmp; return (value.size() >= prefix.size()) && cmp(value.c_str(), prefix.c_str(), prefix.size()) == 0; }
bool pal::touch_file(const pal::string_t& path) { int fd = open(path.c_str(), (O_CREAT | O_EXCL), (S_IRUSR | S_IRGRP | S_IROTH)); if (fd == -1) { trace::warning(_X("open(%s) failed in %s"), path.c_str(), _STRINGIFY(__FUNCTION__)); return false; } (void) close(fd); return true; }
bool pal::pal_utf8string(const pal::string_t& str, std::vector<char>* out) { out->clear(); // Pass -1 as we want explicit null termination in the char buffer. size_t size = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, nullptr, 0, nullptr, nullptr); if (size == 0) { return false; } out->resize(size, '\0'); return ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, out->data(), out->size(), nullptr, nullptr) != 0; }
/** * Resolve the hostpolicy version from deps. * - Scan the deps file's libraries section and find the hostpolicy version in the file. */ pal::string_t resolve_hostpolicy_version_from_deps(const pal::string_t& deps_json) { trace::verbose(_X("--- Resolving %s version from deps json [%s]"), LIBHOSTPOLICY_NAME, deps_json.c_str()); pal::string_t retval; if (!pal::file_exists(deps_json)) { trace::verbose(_X("Dependency manifest [%s] does not exist"), deps_json.c_str()); return retval; } pal::ifstream_t file(deps_json); if (!file.good()) { trace::verbose(_X("Dependency manifest [%s] could not be opened"), deps_json.c_str()); return retval; } if (skip_utf8_bom(&file)) { trace::verbose(_X("UTF-8 BOM skipped while reading [%s]"), deps_json.c_str()); } try { const auto root = json_value::parse(file); const auto& json = root.as_object(); const auto& libraries = json.at(_X("libraries")).as_object(); // Look up the root package instead of the "runtime" package because we can't do a full rid resolution. // i.e., look for "Microsoft.NETCore.DotNetHostPolicy/" followed by version. pal::string_t prefix = _X("Microsoft.NETCore.DotNetHostPolicy/"); for (const auto& library : libraries) { if (starts_with(library.first, prefix, false)) { // Extract the version information that occurs after '/' retval = library.first.substr(prefix.size()); break; } } } catch (const std::exception& je) { pal::string_t jes; (void)pal::utf8_palstring(je.what(), &jes); trace::error(_X("A JSON parsing exception occurred in [%s]: %s"), deps_json.c_str(), jes.c_str()); } trace::verbose(_X("Resolved version %s from dependency manifest file [%s]"), retval.c_str(), deps_json.c_str()); return retval; }
int execute_app( const pal::string_t& impl_dll_dir, const corehost_init_t* init, const int argc, const pal::char_t* argv[]) { pal::dll_t corehost; corehost_main_fn host_main = nullptr; corehost_load_fn host_load = nullptr; corehost_unload_fn host_unload = nullptr; int code = load_host_library(impl_dll_dir, &corehost, &host_load, &host_main, &host_unload); if (code != StatusCode::Success) { trace::error(_X("Could not load host policy library [%s]"), impl_dll_dir.c_str()); return code; } if ((code = host_load(init)) == 0) { code = host_main(argc, argv); (void)host_unload(); } pal::unload_library(corehost); return code; }
int load_host_library_common( const pal::string_t& lib_dir, pal::string_t& host_path, pal::dll_t* h_host, corehost_load_fn* load_fn, corehost_unload_fn* unload_fn) { if (!library_exists_in_dir(lib_dir, LIBHOSTPOLICY_NAME, &host_path)) { return StatusCode::CoreHostLibMissingFailure; } // Load library if (!pal::load_library(&host_path, h_host)) { trace::info(_X("Load library of %s failed"), host_path.c_str()); return StatusCode::CoreHostLibLoadFailure; } // Obtain entrypoint symbols *load_fn = (corehost_load_fn)pal::get_symbol(*h_host, "corehost_load"); *unload_fn = (corehost_unload_fn)pal::get_symbol(*h_host, "corehost_unload"); return (*load_fn != nullptr) && (*unload_fn != nullptr) ? StatusCode::Success : StatusCode::CoreHostEntryPointFailure; }
/** * Given a directory and a version, find if the package relative * dir under the given directory contains hostpolicy.dll */ bool to_hostpolicy_package_dir(const pal::string_t& dir, const pal::string_t& version, pal::string_t* candidate) { assert(!version.empty()); candidate->clear(); // Ensure the relative dir contains platform directory separators. pal::string_t rel_dir = _STRINGIFY(HOST_POLICY_PKG_REL_DIR); if (DIR_SEPARATOR != '/') { replace_char(&rel_dir, '/', DIR_SEPARATOR); } // Construct the path to directory containing hostpolicy. pal::string_t path = dir; append_path(&path, _STRINGIFY(HOST_POLICY_PKG_NAME)); // package name append_path(&path, version.c_str()); // package version append_path(&path, rel_dir.c_str()); // relative dir containing hostpolicy library // Check if "path" contains the required library. if (!library_exists_in_dir(path, LIBHOSTPOLICY_NAME, nullptr)) { trace::verbose(_X("Did not find %s in directory %s"), LIBHOSTPOLICY_NAME, path.c_str()); return false; } // "path" contains the directory containing hostpolicy library. *candidate = path; trace::verbose(_X("Found %s in directory %s"), LIBHOSTPOLICY_NAME, path.c_str()); return true; }
// ----------------------------------------------------------------------------- // Load local assemblies by priority order of their file extensions and // unique-fied by their simple name. // void deps_resolver_t::get_dir_assemblies( const pal::string_t& dir, const pal::string_t& dir_name, dir_assemblies_t* dir_assemblies) { trace::verbose(_X("Adding files from %s dir %s"), dir_name.c_str(), dir.c_str()); // Managed extensions in priority order, pick DLL over EXE and NI over IL. const pal::string_t managed_ext[] = { _X(".ni.dll"), _X(".dll"), _X(".ni.exe"), _X(".exe") }; // List of files in the dir std::vector<pal::string_t> files; pal::readdir(dir, &files); for (const auto& ext : managed_ext) { for (const auto& file : files) { // Nothing to do if file length is smaller than expected ext. if (file.length() <= ext.length()) { continue; } auto file_name = file.substr(0, file.length() - ext.length()); auto file_ext = file.substr(file_name.length()); // Ext did not match expected ext, skip this file. if (pal::strcasecmp(file_ext.c_str(), ext.c_str())) { continue; } // Already added entry for this asset, by priority order skip this ext if (dir_assemblies->count(file_name)) { trace::verbose(_X("Skipping %s because the %s already exists in %s assemblies"), file.c_str(), dir_assemblies->find(file_name)->second.c_str(), dir_name.c_str()); continue; } // Add entry for this asset pal::string_t file_path = dir + DIR_SEPARATOR + file; trace::verbose(_X("Adding %s to %s assembly set from %s"), file_name.c_str(), dir_name.c_str(), file_path.c_str()); dir_assemblies->emplace(file_name, file_path); } } }
runtime_config_t::runtime_config_t(const pal::string_t& path) : m_fx_roll_fwd(true) , m_path(path) , m_portable(false) { m_valid = ensure_parsed(); trace::verbose(_X("Runtime config [%s] is valid=[%d]"), path.c_str(), m_valid); }
bool get_global_shared_store_dirs(std::vector<pal::string_t>* dirs, const pal::string_t& arch, const pal::string_t& tfm) { std::vector<pal::string_t> global_dirs; if (!pal::get_global_dotnet_dirs(&global_dirs)) { return false; } for (pal::string_t dir : global_dirs) { append_path(&dir, RUNTIME_STORE_DIRECTORY_NAME); append_path(&dir, arch.c_str()); append_path(&dir, tfm.c_str()); dirs->push_back(dir); } return true; }
// ----------------------------------------------------------------------------- // Load the deps file and parse its "entry" lines which contain the "fields" of // the entry. Populate an array of these entries. // bool deps_json_t::load(bool portable, const pal::string_t& deps_path, const rid_fallback_graph_t& rid_fallback_graph) { m_file_exists = pal::file_exists(deps_path); // If file doesn't exist, then assume parsed. if (!m_file_exists) { trace::verbose(_X("Could not locate the dependencies manifest file [%s]. Some libraries may fail to resolve."), deps_path.c_str()); return true; } // Somehow the file stream could not be opened. This is an error. pal::ifstream_t file(deps_path); if (!file.good()) { trace::error(_X("Could not open dependencies manifest file [%s]"), deps_path.c_str()); return false; } if (skip_utf8_bom(&file)) { trace::verbose(_X("UTF-8 BOM skipped while reading [%s]"), deps_path.c_str()); } try { const auto json = json_value::parse(file); const auto& runtime_target = json.at(_X("runtimeTarget")); const pal::string_t& name = runtime_target.is_string()? runtime_target.as_string(): runtime_target.at(_X("name")).as_string(); trace::verbose(_X("Loading deps file... %s as portable=[%d]"), deps_path.c_str(), portable); return (portable) ? load_portable(json, name, rid_fallback_graph) : load_standalone(json, name); } catch (const std::exception& je) { pal::string_t jes; (void) pal::utf8_palstring(je.what(), &jes); trace::error(_X("A JSON parsing exception occurred in [%s]: %s"), deps_path.c_str(), jes.c_str()); return false; } }
bool pal::file_exists(const pal::string_t& path) { if (path.empty()) { return false; } struct stat buffer; return (::stat(path.c_str(), &buffer) == 0); }
pal::string_t resolve_sdk_version(pal::string_t sdk_path) { trace::verbose(_X("--- Resolving SDK version from SDK dir [%s]"), sdk_path.c_str()); pal::string_t retval; std::vector<pal::string_t> versions; pal::readdir(sdk_path, &versions); fx_ver_t max_ver(-1, -1, -1); fx_ver_t max_pre(-1, -1, -1); for (const auto& version : versions) { trace::verbose(_X("Considering version... [%s]"), version.c_str()); fx_ver_t ver(-1, -1, -1); if (fx_ver_t::parse(version, &ver, true)) { max_ver = std::max(ver, max_ver); } if (fx_ver_t::parse(version, &ver, false)) { max_pre = std::max(ver, max_pre); } } // No production, use the max pre-release. if (max_ver == fx_ver_t(-1, -1, -1)) { trace::verbose(_X("No production version found, so using latest prerelease")); max_ver = max_pre; } pal::string_t max_ver_str = max_ver.as_str(); append_path(&sdk_path, max_ver_str.c_str()); trace::verbose(_X("Checking if resolved SDK dir [%s] exists"), sdk_path.c_str()); if (pal::directory_exists(sdk_path)) { retval = sdk_path; } trace::verbose(_X("Resolved SDK dir is [%s]"), retval.c_str()); return retval; }
void tpafile::add_from_local_dir(const pal::string_t& dir) { trace::verbose(_X("adding files from %s to TPA"), dir.c_str()); const pal::char_t * const tpa_extensions[] = { _X(".ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir _X(".dll"), _X(".ni.exe"), _X(".exe"), }; std::set<pal::string_t> added_assemblies; // Get directory entries auto files = pal::readdir(dir); for (auto ext : tpa_extensions) { auto len = pal::strlen(ext); for (auto file : files) { // Can't be a match if it's the same length as the extension :) if (file.length() > len) { // Extract the same amount of text from the end of file name auto file_ext = file.substr(file.length() - len, len); // Check if this file name matches if (pal::strcasecmp(ext, file_ext.c_str()) == 0) { // Get the assembly name by stripping the extension // and add it to the set so we can de-dupe auto asm_name = file.substr(0, file.length() - len); // TODO(anurse): Also check if already in TPA file if (added_assemblies.find(asm_name) == added_assemblies.end()) { added_assemblies.insert(asm_name); tpaentry_t entry; entry.asset_type = pal::string_t(_X("runtime")); entry.library_name = pal::string_t(asm_name); entry.library_version = pal::string_t(_X("")); pal::string_t relpath(dir); relpath.push_back(DIR_SEPARATOR); relpath.append(file); entry.relative_path = relpath; entry.asset_name = asm_name; trace::verbose(_X("adding %s to TPA list from %s"), asm_name.c_str(), relpath.c_str()); m_entries.push_back(entry); } } } } } }
/** * When the framework is referenced more than once in a non-compatible way, display detailed error message * about available frameworks and installation of new framework. */ void fx_resolver_t::display_incompatible_framework_error( const pal::string_t& higher, const fx_reference_t& lower) { trace::error(_X("The specified framework '%s', version '%s', apply_patches=%d, roll_forward=%s cannot roll-forward to the previously referenced version '%s'."), lower.get_fx_name().c_str(), lower.get_fx_version().c_str(), lower.get_apply_patches(), roll_forward_option_to_string(lower.get_roll_forward()).c_str(), higher.c_str()); }
static bool is_executable(const pal::string_t& file_path) { struct stat st; if (::stat(file_path.c_str(), &st) < 0) { return false; } return ((st.st_mode & S_IEXEC) != 0); }
/*static*/ bool framework_info::print_all_frameworks(const pal::string_t& own_dir, const pal::string_t& leading_whitespace) { std::vector<framework_info> framework_infos; get_all_framework_infos(own_dir, _X(""), &framework_infos); for (framework_info info : framework_infos) { trace::println(_X("%s%s %s [%s]"), leading_whitespace.c_str(), info.name.c_str(), info.version.as_str().c_str(), info.path.c_str()); } return framework_infos.size() > 0; }
bool pal::touch_file(const pal::string_t& path) { HANDLE hnd = ::CreateFileW(path.c_str(), 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hnd == INVALID_HANDLE_VALUE) { trace::verbose(_X("Failed to leave breadcrumb, HRESULT: 0x%X"), HRESULT_FROM_WIN32(GetLastError())); return false; } ::CloseHandle(hnd); return true; }
bool get_env_shared_store_dirs(std::vector<pal::string_t>* dirs, const pal::string_t& arch, const pal::string_t& tfm) { pal::string_t path; if (!pal::getenv(_X("DOTNET_SHARED_STORE"), &path)) { return false; } pal::string_t tok; pal::stringstream_t ss(path); while (std::getline(ss, tok, PATH_SEPARATOR)) { if (pal::realpath(&tok)) { append_path(&tok, arch.c_str()); append_path(&tok, tfm.c_str()); dirs->push_back(tok); } } return true; }
pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime_config_t* runtime) { trace::verbose(_X("--- Resolving FX directory from muxer dir [%s]"), muxer_dir.c_str()); const auto fx_name = runtime->get_fx_name(); const auto fx_ver = runtime->get_fx_version(); const auto roll_fwd = runtime->get_fx_roll_fwd(); fx_ver_t specified(-1, -1, -1); if (!fx_ver_t::parse(fx_ver, &specified, false)) { trace::error(_X("The specified runtimeconfig.json version [%s] could not be parsed"), fx_ver.c_str()); return pal::string_t(); } auto fx_dir = muxer_dir; append_path(&fx_dir, _X("shared")); append_path(&fx_dir, fx_name.c_str()); // If not roll forward or if pre-release, just return. if (!roll_fwd || specified.is_prerelease()) { trace::verbose(_X("Did not roll forward because rollfwd=%d and [%s] is prerelease=%d"), roll_fwd, fx_ver.c_str(), specified.is_prerelease()); append_path(&fx_dir, fx_ver.c_str()); } else { trace::verbose(_X("Attempting production FX roll forward starting from [%s]"), fx_ver.c_str()); std::vector<pal::string_t> list; pal::readdir(fx_dir, &list); fx_ver_t max_specified = specified; for (const auto& version : list) { trace::verbose(_X("Inspecting version... [%s]"), version.c_str()); fx_ver_t ver(-1, -1, -1); if (fx_ver_t::parse(version, &ver, true) && ver.get_major() == max_specified.get_major() && ver.get_minor() == max_specified.get_minor()) { max_specified.set_patch(std::max(ver.get_patch(), max_specified.get_patch())); } } pal::string_t max_specified_str = max_specified.as_str(); append_path(&fx_dir, max_specified_str.c_str()); } trace::verbose(_X("Chose FX version [%s]"), fx_dir.c_str()); return fx_dir; }
void fx_resolver_t::display_compatible_framework_trace( const pal::string_t& higher, const fx_reference_t& lower) { if (trace::is_enabled()) { trace::verbose(_X("--- The specified framework '%s', version '%s', apply_patches=%d, roll_forward=%s is compatible with the previously referenced version '%s'."), lower.get_fx_name().c_str(), lower.get_fx_version().c_str(), lower.get_apply_patches(), roll_forward_option_to_string(lower.get_roll_forward()).c_str(), higher.c_str()); } }
pal::string_t fx_muxer_t::resolve_cli_version(const pal::string_t& global_json) { trace::verbose(_X("--- Resolving CLI version from global json [%s]"), global_json.c_str()); pal::string_t retval; if (!pal::file_exists(global_json)) { trace::verbose(_X("[%s] does not exist"), global_json.c_str()); return retval; } pal::ifstream_t file(global_json); if (!file.good()) { trace::verbose(_X("[%s] could not be opened"), global_json.c_str()); return retval; } if (skip_utf8_bom(&file)) { trace::verbose(_X("UTF-8 BOM skipped while reading [%s]"), global_json.c_str()); } try { const auto root = json_value::parse(file); const auto& json = root.as_object(); const auto sdk_iter = json.find(_X("sdk")); if (sdk_iter == json.end() || sdk_iter->second.is_null()) { trace::verbose(_X("CLI '/sdk/version' field not present/null in [%s]"), global_json.c_str()); return retval; } const auto& sdk_obj = sdk_iter->second.as_object(); const auto ver_iter = sdk_obj.find(_X("version")); if (ver_iter == sdk_obj.end() || ver_iter->second.is_null()) { trace::verbose(_X("CLI 'sdk/version' field not present/null in [%s]"), global_json.c_str()); return retval; } retval = ver_iter->second.as_string(); } catch (const std::exception& je) { pal::string_t jes; (void) pal::utf8_palstring(je.what(), &jes); trace::error(_X("A JSON parsing exception occurred in [%s]: %s"), global_json.c_str(), jes.c_str()); } trace::verbose(_X("CLI version is [%s] in global json file [%s]"), retval.c_str(), global_json.c_str()); return retval; }
/** * When the framework is not found, display detailed error message * about available frameworks and installation of new framework. */ void fx_resolver_t::display_missing_framework_error( const pal::string_t& fx_name, const pal::string_t& fx_version, const pal::string_t& fx_dir, const pal::string_t& dotnet_root) { std::vector<framework_info> framework_infos; pal::string_t fx_ver_dirs; if (fx_dir.length()) { fx_ver_dirs = fx_dir; framework_info::get_all_framework_infos(get_directory(fx_dir), fx_name, &framework_infos); } else { fx_ver_dirs = dotnet_root; } framework_info::get_all_framework_infos(dotnet_root, fx_name, &framework_infos); // Display the error message about missing FX. if (fx_version.length()) { trace::error(_X("The specified framework '%s', version '%s' was not found."), fx_name.c_str(), fx_version.c_str()); } else { trace::error(_X("The specified framework '%s' was not found."), fx_name.c_str()); } if (framework_infos.size()) { trace::error(_X(" - The following frameworks were found:")); for (const framework_info& info : framework_infos) { trace::error(_X(" %s at [%s]"), info.version.as_str().c_str(), info.path.c_str()); } } else { trace::error(_X(" - No frameworks were found.")); } trace::error(_X("")); trace::error(_X("You can resolve the problem by installing the specified framework and/or SDK.")); trace::error(_X("")); trace::error(_X("The .NET Core frameworks can be found at:")); trace::error(_X(" - %s"), DOTNET_CORE_DOWNLOAD_URL); }
void pal::readdir(const pal::string_t& path, std::vector<pal::string_t>* list) { assert(list != nullptr); std::vector<pal::string_t>& files = *list; auto dir = opendir(path.c_str()); if (dir != nullptr) { struct dirent* entry = nullptr; while((entry = readdir(dir)) != nullptr) { // We are interested in files only switch (entry->d_type) { case DT_REG: break; // Handle symlinks and file systems that do not support d_type case DT_LNK: case DT_UNKNOWN: { std::string fullFilename; fullFilename.append(path); fullFilename.push_back(DIR_SEPARATOR); fullFilename.append(entry->d_name); struct stat sb; if (stat(fullFilename.c_str(), &sb) == -1) { continue; } if (!S_ISREG(sb.st_mode)) { continue; } } break; default: continue; } files.push_back(pal::string_t(entry->d_name)); } } }
bool library_exists_in_dir(const pal::string_t& lib_dir, const pal::string_t& lib_name, pal::string_t* p_lib_path) { pal::string_t lib_path = lib_dir; append_path(&lib_path, lib_name.c_str()); if (!pal::file_exists(lib_path)) { return false; } if (p_lib_path) { *p_lib_path = lib_path; } return true; }
static void readdir(const pal::string_t& path, const pal::string_t& pattern, bool onlydirectories, std::vector<pal::string_t>* list) { assert(list != nullptr); std::vector<pal::string_t>& files = *list; pal::string_t normalized_path(path); if (LongFile::ShouldNormalize(normalized_path)) { if (!pal::realpath(&normalized_path)) { return; } } pal::string_t search_string(normalized_path); append_path(&search_string, pattern.c_str()); WIN32_FIND_DATAW data = { 0 }; auto handle = ::FindFirstFileExW(search_string.c_str(), FindExInfoStandard, &data, FindExSearchNameMatch, NULL, 0); if (handle == INVALID_HANDLE_VALUE) { return; } do { if (!onlydirectories || (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { pal::string_t filepath(data.cFileName); if (filepath != _X(".") && filepath != _X("..")) { files.push_back(filepath); } } } while (::FindNextFileW(handle, &data)); ::FindClose(handle); }
bool report_missing_assembly_in_manifest(const deps_entry_t& entry, bool continueResolving = false) { bool showManifestListMessage = !entry.runtime_store_manifest_list.empty(); if (entry.asset_type == deps_entry_t::asset_types::resources) { // Treat missing resource assemblies as informational. continueResolving = true; trace::info(MissingAssemblyMessage.c_str(), _X("Info"), entry.deps_file.c_str(), entry.library_name.c_str(), entry.library_version.c_str(), entry.asset.relative_path.c_str()); if (showManifestListMessage) { trace::info(ManifestListMessage.c_str(), entry.runtime_store_manifest_list.c_str()); } } else if (continueResolving) { trace::warning(MissingAssemblyMessage.c_str(), _X("Warning"), entry.deps_file.c_str(), entry.library_name.c_str(), entry.library_version.c_str(), entry.asset.relative_path.c_str()); if (showManifestListMessage) { trace::warning(ManifestListMessage.c_str(), entry.runtime_store_manifest_list.c_str()); } } else { trace::error(MissingAssemblyMessage.c_str(), _X("Error"), entry.deps_file.c_str(), entry.library_name.c_str(), entry.library_version.c_str(), entry.asset.relative_path.c_str()); if (showManifestListMessage) { trace::error(ManifestListMessage.c_str(), entry.runtime_store_manifest_list.c_str()); } } return continueResolving; }
bool deps_resolver_t::try_roll_forward(const deps_entry_t& entry, const pal::string_t& probe_dir, bool patch_roll_fwd, bool prerelease_roll_fwd, pal::string_t* candidate) { trace::verbose(_X("Attempting a roll forward for [%s/%s/%s] in [%s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str(), probe_dir.c_str()); const pal::string_t& lib_ver = entry.library_version; fx_ver_t cur_ver(-1, -1, -1); if (!fx_ver_t::parse(lib_ver, &cur_ver, false)) { trace::verbose(_X("No roll forward as specified version [%s] could not be parsed"), lib_ver.c_str()); return false; } pal::string_t path = probe_dir; append_path(&path, entry.library_name.c_str()); pal::string_t max_str = lib_ver; if (cur_ver.is_prerelease() && prerelease_roll_fwd) { pal::string_t maj_min_pat_star = cur_ver.prerelease_glob(); pal::string_t cache_key = path; append_path(&cache_key, maj_min_pat_star.c_str()); if (m_prerelease_roll_forward_cache.count(cache_key)) { max_str = m_prerelease_roll_forward_cache[cache_key]; trace::verbose(_X("Found cached roll forward version [%s] -> [%s]"), lib_ver.c_str(), max_str.c_str()); } else { try_prerelease_roll_forward_in_dir(path, cur_ver, &max_str); m_prerelease_roll_forward_cache[cache_key] = max_str; } } if (!cur_ver.is_prerelease() && patch_roll_fwd) { // Extract glob string of the form: 1.0.* from the version 1.0.0-prerelease-00001. pal::string_t maj_min_star = cur_ver.patch_glob(); pal::string_t cache_key = path; append_path(&cache_key, maj_min_star.c_str()); if (m_patch_roll_forward_cache.count(cache_key)) { max_str = m_patch_roll_forward_cache[cache_key]; trace::verbose(_X("Found cached roll forward version [%s] -> [%s]"), lib_ver.c_str(), max_str.c_str()); } else { try_patch_roll_forward_in_dir(path, cur_ver, &max_str); m_patch_roll_forward_cache[cache_key] = max_str; } } append_path(&path, max_str.c_str()); return entry.to_rel_path(path, candidate); }
int execute_app( const pal::string_t& impl_dll_dir, corehost_init_t* init, const int argc, const pal::char_t* argv[]) { pal::dll_t corehost; corehost_main_fn host_main = nullptr; corehost_load_fn host_load = nullptr; corehost_unload_fn host_unload = nullptr; int code = load_host_library(impl_dll_dir, &corehost, &host_load, &host_main, &host_unload); if (code != StatusCode::Success) { trace::error(_X("An error occurred while loading required library %s from [%s]"), LIBHOSTPOLICY_NAME, impl_dll_dir.c_str()); return code; } // Previous hostfxr trace messages must be printed before calling trace::setup in hostpolicy trace::flush(); const host_interface_t& intf = init->get_host_init_data(); if ((code = host_load(&intf)) == 0) { code = host_main(argc, argv); (void)host_unload(); } pal::unload_library(corehost); return code; }