Ejemplo n.º 1
0
void deps_resolver_t::setup_probe_config(
    const corehost_init_t* init,
    const runtime_config_t& config,
    const arguments_t& args)
{
    if (pal::directory_exists(args.dotnet_extensions))
    {
        pal::string_t ext_ni = args.dotnet_extensions;
        append_path(&ext_ni, get_arch());
        if (pal::directory_exists(ext_ni))
        {
            // Servicing NI probe.
            m_probes.push_back(probe_config_t::svc_ni(ext_ni, config.get_patch_roll_fwd(), config.get_prerelease_roll_fwd()));
        }

        // Servicing normal probe.
        m_probes.push_back(probe_config_t::svc(args.dotnet_extensions, config.get_patch_roll_fwd(), config.get_prerelease_roll_fwd()));
    }

    if (pal::directory_exists(args.dotnet_packages_cache))
    {
        pal::string_t ni_packages_cache = args.dotnet_packages_cache;
        append_path(&ni_packages_cache, get_arch());
        if (pal::directory_exists(ni_packages_cache))
        {
            // Packages cache NI probe
            m_probes.push_back(probe_config_t::cache_ni(ni_packages_cache));
        }

        // Packages cache probe
        m_probes.push_back(probe_config_t::cache(args.dotnet_packages_cache));
    }

    if (pal::directory_exists(m_fx_dir))
    {
        // FX probe
        m_probes.push_back(probe_config_t::fx(m_fx_dir, m_fx_deps.get()));
    }

    for (const auto& probe : m_additional_probes)
    {
        // Additional paths
        bool patch_roll_fwd = config.get_patch_roll_fwd();
        bool prerelease_roll_fwd = config.get_prerelease_roll_fwd();
        m_probes.push_back(probe_config_t::additional(probe, patch_roll_fwd, prerelease_roll_fwd));
    }

    if (trace::is_enabled())
    {
        trace::verbose(_X("-- Listing probe configurations..."));
        for (const auto& pc : m_probes)
        {
            pc.print();
        }
    }
}
Ejemplo n.º 2
0
/**
 * Given FX location, app binary and specified --depsfile, return deps that contains hostpolicy.dll
 */
pal::string_t get_deps_file(
    const pal::string_t& fx_dir,
    const pal::string_t& app_candidate,
    const pal::string_t& specified_deps_file,
    const runtime_config_t& config)
{
    if (config.get_portable())
    {
        // Portable app's hostpolicy is resolved from FX deps
        return fx_dir + DIR_SEPARATOR + config.get_fx_name() + _X(".deps.json");
    }
    else
    {
        // Standalone app's hostpolicy is from specified deps or from app deps.
        return !specified_deps_file.empty() ? specified_deps_file : get_deps_from_app_binary(app_candidate);
    }
}
Ejemplo n.º 3
0
pal::string_t fx_muxer_t::resolve_fx_dir(host_mode_t mode, const pal::string_t& own_dir, const runtime_config_t& config, const pal::string_t& specified_fx_version)
{
    // No FX resolution for standalone apps.
    assert(mode != host_mode_t::standalone);

    // If invoking using FX dotnet.exe, use own directory.
    if (mode == host_mode_t::split_fx)
    {
        return own_dir;
    }
    assert(mode == host_mode_t::muxer);

    trace::verbose(_X("--- Resolving FX directory from muxer dir '%s', specified '%s'"), own_dir.c_str(), specified_fx_version.c_str());
    const auto fx_name = config.get_fx_name();
    const auto fx_ver = specified_fx_version.empty() ? config.get_fx_version() : specified_fx_version;

    fx_ver_t specified(-1, -1, -1);
    if (!fx_ver_t::parse(fx_ver, &specified, false))
    {
        trace::error(_X("The specified framework version '%s' could not be parsed"), fx_ver.c_str());
        return pal::string_t();
    }

    auto fx_dir = own_dir;
    append_path(&fx_dir, _X("shared"));
    append_path(&fx_dir, fx_name.c_str());

    bool do_roll_forward = false;
    if (specified_fx_version.empty())
    {
        if (!specified.is_prerelease())
        {
            // If production and no roll forward use given version.
            do_roll_forward = config.get_patch_roll_fwd();
        }
        else
        {
            // Prerelease, but roll forward only if version doesn't exist.
            pal::string_t ver_dir = fx_dir;
            append_path(&ver_dir, fx_ver.c_str());
            do_roll_forward = !pal::directory_exists(ver_dir);
        }
    }

    if (!do_roll_forward)
    {
        trace::verbose(_X("Did not roll forward because specified version='%s', patch_roll_fwd=%d, chose [%s]"), specified_fx_version.c_str(), config.get_patch_roll_fwd(), fx_ver.c_str());
        append_path(&fx_dir, fx_ver.c_str());
    }
    else
    {
        trace::verbose(_X("Attempting FX roll forward starting from [%s]"), fx_ver.c_str());

        std::vector<pal::string_t> list;
        pal::readdir(fx_dir, &list);
        fx_ver_t most_compatible = specified;
        for (const auto& version : list)
        {
            trace::verbose(_X("Inspecting version... [%s]"), version.c_str());
            fx_ver_t ver(-1, -1, -1);
            if (!specified.is_prerelease() && fx_ver_t::parse(version, &ver, true) && // true -- only prod. prevents roll forward to prerelease.
                ver.get_major() == specified.get_major() &&
                ver.get_minor() == specified.get_minor())
            {
                // Pick the greatest production that differs only in patch.
                most_compatible = std::max(ver, most_compatible);
            }
            if (specified.is_prerelease() && fx_ver_t::parse(version, &ver, false) && // false -- implies both production and prerelease.
                ver.is_prerelease() && // prevent roll forward to production.
                ver.get_major() == specified.get_major() &&
                ver.get_minor() == specified.get_minor() &&
                ver.get_patch() == specified.get_patch() &&
                ver > specified)
            {
                // Pick the smallest prerelease that is greater than specified.
                most_compatible = (most_compatible == specified) ? ver : std::min(ver, most_compatible);
            }
        }
        pal::string_t most_compatible_str = most_compatible.as_str();
        append_path(&fx_dir, most_compatible_str.c_str());
    }

    trace::verbose(_X("Chose FX version [%s]"), fx_dir.c_str());
    return fx_dir;
}
Ejemplo n.º 4
0
/**
 * Given own location, FX location, app binary and specified --depsfile and probe paths
 *     return location that is expected to contain hostpolicy
 */
bool fx_muxer_t::resolve_hostpolicy_dir(host_mode_t mode,
    const pal::string_t& own_dir,
    const pal::string_t& fx_dir,
    const pal::string_t& app_candidate,
    const pal::string_t& specified_deps_file,
    const pal::string_t& specified_fx_version,
    const std::vector<pal::string_t>& probe_realpaths,
    const runtime_config_t& config,
    pal::string_t* impl_dir)
{
    // Obtain deps file for the given configuration.
    pal::string_t resolved_deps = get_deps_file(fx_dir, app_candidate, specified_deps_file, config);

    // Resolve hostpolicy version out of the deps file.
    pal::string_t version = resolve_hostpolicy_version_from_deps(resolved_deps);
    if (trace::is_enabled() && version.empty() && pal::file_exists(resolved_deps))
    {
        trace::warning(_X("Dependency manifest %s does not contain an entry for %s"), resolved_deps.c_str(), _STRINGIFY(HOST_POLICY_PKG_NAME));
    }

    // Check if the given version of the hostpolicy exists in servicing.
    if (hostpolicy_exists_in_svc(version, impl_dir))
    {
        return true;
    }

    // Get the expected directory that would contain hostpolicy.
    pal::string_t expected;
    if (config.get_portable())
    {
        if (!pal::directory_exists(fx_dir))
        {
            pal::string_t fx_version = specified_fx_version.empty() ? config.get_fx_version() : specified_fx_version;
            handle_missing_framework_error(config.get_fx_name(), fx_version, fx_dir);
            return false;
        }
        
        expected = fx_dir;
    }
    else
    {
        // Standalone apps can be activated by muxer or by standalone host or "corehost"
        // 1. When activated with dotnet.exe or corehost.exe, check for hostpolicy in the deps dir or
        //    app dir.
        // 2. When activated with app.exe, the standalone host, check own directory.
        assert(mode == host_mode_t::muxer || mode == host_mode_t::standalone || mode == host_mode_t::split_fx);
        expected = (mode == host_mode_t::standalone)
            ? own_dir
            : get_directory(specified_deps_file.empty() ? app_candidate : specified_deps_file);
    }

    // Check if hostpolicy exists in "expected" directory.
    trace::verbose(_X("The expected %s directory is [%s]"), LIBHOSTPOLICY_NAME, expected.c_str());
    if (library_exists_in_dir(expected, LIBHOSTPOLICY_NAME, nullptr))
    {
        impl_dir->assign(expected);
        return true;
    }

    trace::verbose(_X("The %s was not found in [%s]"), LIBHOSTPOLICY_NAME, expected.c_str());

    // Start probing for hostpolicy in the specified probe paths.
    pal::string_t candidate;
    if (resolve_hostpolicy_dir_from_probe_paths(version, probe_realpaths, &candidate))
    {
        impl_dir->assign(candidate);
        return true;
    }

    // If it still couldn't be found, somebody upstack messed up. Flag an error for the "expected" location.
    trace::error(_X("A fatal error was encountered. The library '%s' required to execute the application was not found in '%s'."), LIBHOSTPOLICY_NAME, expected.c_str());
    return false;
}