Example #1
0
/**
 * 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;
}
Example #2
0
/**
 * 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());
}
Example #3
0
void tpafile::write_tpa_list(pal::string_t& output)
{
	std::set<pal::string_t> items;
	for (auto entry : m_entries)
	{
		if (pal::strcmp(entry.asset_type.c_str(), _X("runtime")) == 0 && items.find(entry.asset_name) == items.end())
		{
			// Resolve the full path
			for (auto search_path : m_package_search_paths)
			{
				pal::string_t candidate;
				candidate.reserve(search_path.length() +
					entry.library_name.length() +
					entry.library_version.length() +
					entry.relative_path.length() + 3);
				candidate.append(search_path);

				append_path(candidate, entry.library_name.c_str());
				append_path(candidate, entry.library_version.c_str());
				append_path(candidate, entry.relative_path.c_str());
				if (pal::file_exists(candidate))
				{
					trace::verbose(_X("adding tpa entry: %s"), candidate.c_str());

					output.append(candidate);
					output.push_back(PATH_SEPARATOR);
					items.insert(entry.asset_name);
					break;
				}
			}
		}
	}
}
Example #4
0
bool pal::file_exists(const pal::string_t& path)
{
    if (path.empty())
    {
        return false;
    }
    struct stat buffer;
    return (::stat(path.c_str(), &buffer) == 0);
}
Example #5
0
pal::string_t get_directory(const pal::string_t& path)
{
    // Find the last dir separator
    auto path_sep = path.find_last_of(DIR_SEPARATOR);
    if (path_sep == pal::string_t::npos)
    {
        return pal::string_t(path);
    }

    return path.substr(0, path_sep);
}
Example #6
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;
}
Example #7
0
bool try_stou(const pal::string_t& str, unsigned* num)
{
    if (str.empty())
    {
        return false;
    }
    if (str.find_first_not_of(_X("0123456789")) != pal::string_t::npos)
    {
        return false;
    }
    *num = (unsigned) std::stoul(str);
    return true;
}
Example #8
0
pal::string_t get_filename_without_ext(const pal::string_t& path)
{
    if (path.empty())
    {
        return path;
    }

    size_t name_pos = path.find_last_of(_X("/\\"));
    size_t dot_pos = path.rfind(_X('.'));
    size_t start_pos = (name_pos == pal::string_t::npos) ? 0 : (name_pos + 1);
    size_t count = (dot_pos == pal::string_t::npos || dot_pos < start_pos) ? pal::string_t::npos : (dot_pos - start_pos);
    return path.substr(start_pos, count);
}
Example #9
0
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;
}
Example #10
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;
}
Example #11
0
pal::string_t strip_file_ext(const pal::string_t& path)
{
    if (path.empty())
    {
        return path;
    }
    size_t sep_pos = path.rfind(_X("/\\"));
    size_t dot_pos = path.rfind(_X('.'));
    if (sep_pos != pal::string_t::npos && sep_pos > dot_pos)
    {
        return path;
    }
    return path.substr(0, dot_pos);
}
/**
* 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);
}
Example #13
0
/**
* Given path to app binary, say app.dll or app.exe, retrieve the app.deps.json.
*/
pal::string_t get_deps_from_app_binary(const pal::string_t& app_base, const pal::string_t& app)
{
    pal::string_t deps_file;
    auto app_name = get_filename(app);
    deps_file.reserve(app_base.length() + 1 + app_name.length() + 5);
    deps_file.append(app_base);

    if (!app_base.empty() && app_base.back() != DIR_SEPARATOR)
    {
        deps_file.push_back(DIR_SEPARATOR);
    }
    deps_file.append(app_name, 0, app_name.find_last_of(_X(".")));
    deps_file.append(_X(".deps.json"));
    return deps_file;
}
Example #14
0
pal::string_t trim_quotes(pal::string_t stringToCleanup)
{
    pal::char_t quote_array[2] = {'\"', '\''};
    for(int index = 0; index < sizeof(quote_array)/sizeof(quote_array[0]); index++)
    {
        size_t pos = stringToCleanup.find(quote_array[index]);
        while(pos != std::string::npos)
        {
            stringToCleanup = stringToCleanup.erase(pos, 1);
            pos = stringToCleanup.find(quote_array[index]);
        }
    }

    return stringToCleanup;
}
Example #15
0
void append_path(pal::string_t& path1, const pal::char_t* path2)
{
    if (pal::is_path_rooted(path2))
    {
        path1.assign(path2);
    }
    else
    {
        if (path1.back() != DIR_SEPARATOR)
        {
            path1.push_back(DIR_SEPARATOR);
        }
        path1.append(path2);
    }
}
Example #16
0
pal::string_t get_filename(const pal::string_t& path)
{
    if (path.empty())
    {
        return path;
    }

    auto name_pos = path.find_last_of(DIR_SEPARATOR);
    if (name_pos == pal::string_t::npos)
    {
        return path;
    }

    return path.substr(name_pos + 1);
}
Example #17
0
bool read_field(pal::string_t line, int& offset, pal::string_t& value_recv)
{
	// The first character should be a '"'
	if (line[offset] != '"')
	{
		trace::error(_X("error reading TPA file"));
		return false;
	}
	offset++;

	// Set up destination buffer (it can't be bigger than the original line)
	pal::char_t buf[PATH_MAX];
	auto buf_offset = 0;

	// Iterate through characters in the string
	for (; offset < line.length(); offset++)
	{
		// Is this a '\'?
		if (line[offset] == '\\')
		{
			// Skip this character and read the next character into the buffer
			offset++;
			buf[buf_offset] = line[offset];
		}
		// Is this a '"'?
		else if (line[offset] == '\"')
		{
			// Done! Advance to the pointer after the input
			offset++;
			break;
		}
		else
		{
			// Take the character
			buf[buf_offset] = line[offset];
		}
		buf_offset++;
	}
	buf[buf_offset] = '\0';
	value_recv.assign(buf);

	// Consume the ',' if we have one
	if (line[offset] == ',')
	{
		offset++;
	}
	return true;
}
Example #18
0
bool LongFile::IsPathNotFullyQualified(const pal::string_t& path)
{
    if (path.length() < 2)
    {
        return true;  // It isn't fixed, it must be relative.  There is no way to specify a fixed path with one character (or less).
    }

    if (IsDirectorySeparator(path[0]))
    {
        return !IsDirectorySeparator(path[1]); // There is no valid way to specify a relative path with two initial slashes
    }

    return !((path.length() >= 3)           //The only way to specify a fixed path that doesn't begin with two slashes is the drive, colon, slash format- "i.e. C:\"
        && (path[1] == VolumeSeparatorChar)
        && IsDirectorySeparator(path[2]));
}
Example #19
0
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;
}
Example #20
0
// For some distros, we don't want to use the full version from VERSION_ID. One example is
// Red Hat Enterprise Linux, which includes a minor version in their VERSION_ID but minor
// versions are backwards compatable.
//
// In this case, we'll normalized RIDs like 'rhel.7.2' and 'rhel.7.3' to a generic
// 'rhel.7'. This brings RHEL in line with other distros like CentOS or Debian which
// don't put minor version numbers in their VERSION_ID fields because all minor versions
// are backwards compatible.
static
pal::string_t normalize_linux_rid(pal::string_t rid)
{
    pal::string_t rhelPrefix(_X("rhel."));

    if (rid.compare(0, rhelPrefix.length(), rhelPrefix) == 0)
    {
        size_t minorVersionSeparatorIndex = rid.find(_X("."), rhelPrefix.length());
        if (minorVersionSeparatorIndex != std::string::npos)
        {
            rid.erase(minorVersionSeparatorIndex, rid.length() - minorVersionSeparatorIndex);
        }
    }

    return rid;
}
Example #21
0
/**
 * Given a version and probing paths, find if package layout
 *    directory containing hostpolicy exists.
 */
bool resolve_hostpolicy_dir_from_probe_paths(const pal::string_t& version, const std::vector<pal::string_t>& probe_realpaths, pal::string_t* candidate)
{
    if (probe_realpaths.empty() || version.empty())
    {
        return false;
    }

    // Check if the package relative directory containing hostpolicy exists.
    for (const auto& probe_path : probe_realpaths)
    {
        trace::verbose(_X("Considering %s to probe for %s"), probe_path.c_str(), LIBHOSTPOLICY_NAME);
        if (to_hostpolicy_package_dir(probe_path, version, candidate))
        {
            return true;
        }
    }

    // Print detailed message about the file not found in the probe paths.
    trace::error(_X("Could not find required library %s in %d probing paths:"),
        LIBHOSTPOLICY_NAME, probe_realpaths.size());
    for (const auto& path : probe_realpaths)
    {
        trace::error(_X("  %s"), path.c_str());
    }
    return false;
}
Example #22
0
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;
}
Example #23
0
void get_framework_and_sdk_locations(const pal::string_t& dotnet_dir, std::vector<pal::string_t>* locations)
{
    bool multilevel_lookup = multilevel_lookup_enabled();

    // Multi-level lookup will look for the most appropriate version in several locations
    // by following the priority rank below:
    //  .exe directory
    //  Global .NET directories
    // If it is not activated, then only .exe directory will be considered

    pal::string_t dotnet_dir_temp;
    if (!dotnet_dir.empty())
    {
        // own_dir contains DIR_SEPARATOR appended that we need to remove.
        dotnet_dir_temp = dotnet_dir;
        remove_trailing_dir_seperator(&dotnet_dir_temp);

        locations->push_back(dotnet_dir_temp);
    }

    std::vector<pal::string_t> global_dirs;
    if (multilevel_lookup && pal::get_global_dotnet_dirs(&global_dirs))
    {
        for (pal::string_t dir : global_dirs)
        {
            // avoid duplicate paths
            if (!pal::are_paths_equal_with_normalized_casing(dir, dotnet_dir_temp))
            {
                locations->push_back(dir);
            }
        }
    }
}
Example #24
0
// -----------------------------------------------------------------------------
// 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);
        }
    }
}
Example #25
0
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);
} 
Example #26
0
// -----------------------------------------------------------------------------
// 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;
    }
}
Example #27
0
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;
}
Example #28
0
void tpafile::write_native_paths(pal::string_t& output)
{
	std::set<pal::string_t> items;
	for (auto search_path : m_native_search_paths)
	{
		if (items.find(search_path) == items.end())
		{
			trace::verbose(_X("adding native search path: %s"), search_path.c_str());
			output.append(search_path);
			output.push_back(PATH_SEPARATOR);
			items.insert(search_path);
		}
	}

	for (auto entry : m_entries)
	{
		auto dir = entry.relative_path.substr(0, entry.relative_path.find_last_of(DIR_SEPARATOR));
		if (pal::strcmp(entry.asset_type.c_str(), _X("native")) == 0 && items.find(dir) == items.end())
		{
			// Resolve the full path
			for (auto search_path : m_package_search_paths)
			{
				pal::string_t candidate;
				candidate.reserve(search_path.length() +
					entry.library_name.length() +
					entry.library_version.length() +
					dir.length() + 3);
				candidate.append(search_path);

				append_path(candidate, entry.library_name.c_str());
				append_path(candidate, entry.library_version.c_str());
				append_path(candidate, get_directory(entry.relative_path).c_str());

				if (pal::file_exists(candidate))
				{
					trace::verbose(_X("adding native search path: %s"), candidate.c_str());
					output.append(candidate);
					output.push_back(PATH_SEPARATOR);
					items.insert(dir);
					break;
				}
			}
		}
	}
}
Example #29
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;
}
Example #30
0
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);
					}
				}
			}
		}
	}
}