Esempio n. 1
0
/**
* 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);
}
Esempio n. 2
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]));
}
Esempio n. 3
0
void get_tpafile_path(const pal::string_t& app_base, const pal::string_t& app_name, pal::string_t& tpapath)
{
    tpapath.reserve(app_base.length() + app_name.length() + 5);

    tpapath.append(app_base);
    tpapath.push_back(DIR_SEPARATOR);

    // Remove the extension from the app_name
    auto ext_location = app_name.find_last_of('.');
    if (ext_location != std::string::npos)
    {
        tpapath.append(app_name.substr(0, ext_location));
    }
    else
    {
        tpapath.append(app_name);
    }
    tpapath.append(_X(".deps"));
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
bool deps_entry_t::to_path(const pal::string_t& base, bool look_in_base, pal::string_t* str) const
{
    pal::string_t& candidate = *str;

    candidate.clear();

    // Base directory must be present to obtain full path
    if (base.empty())
    {
        return false;
    }

    // Entry relative path contains '/' separator, sanitize it to use
    // platform separator. Perf: avoid extra copy if it matters.
    pal::string_t pal_relative_path = relative_path;
    if (_X('/') != DIR_SEPARATOR)
    {
        replace_char(&pal_relative_path, _X('/'), DIR_SEPARATOR);
    }

    // Reserve space for the path below
    candidate.reserve(base.length() +
        pal_relative_path.length() + 3);

    candidate.assign(base);
    pal::string_t sub_path = look_in_base ? get_filename(pal_relative_path) : pal_relative_path;
    append_path(&candidate, sub_path.c_str());

    bool exists = pal::file_exists(candidate);
    const pal::char_t* query_type = look_in_base ? _X("Local") : _X("Relative");
    if (!exists)
    {
        trace::verbose(_X("    %s path query did not exist %s"), query_type, candidate.c_str());
        candidate.clear();
    }
    else
    {
        trace::verbose(_X("    %s path query exists %s"), query_type, candidate.c_str());
    }
    return exists;
}
Esempio n. 8
0
// -----------------------------------------------------------------------------
// Given a "base" directory, yield the relative path of this file in the package
// layout if the entry hash matches the hash file in the "base" directory
//
// Parameters:
//    base - The base directory to look for the relative path of this entry and
//           the hash file.
//    str  - If the method returns true, contains the file path for this deps
//           entry relative to the "base" directory
//
// Description:
//    Looks for a file named "{PackageName}.{PackageVersion}.nupkg.{HashAlgorithm}"
//    If the deps entry's {HashAlgorithm}-{HashValue} matches the contents then
//    yields the relative path of this entry in the "base" dir.
//
// Returns:
//    If the file exists in the path relative to the "base" directory and there
//    was hash file match with this deps entry.
//
// See: to_full_path(base, str)
//
bool deps_entry_t::to_hash_matched_path(const pal::string_t& base, pal::string_t* str) const
{
    pal::string_t& candidate = *str;

    candidate.clear();

    // Base directory must be present to perform hash lookup.
    if (base.empty())
    {
        return false;
    }

    // First detect position of hyphen in [Algorithm]-[Hash] in the string.
    size_t pos = library_hash.find(_X("-"));
    if (pos == 0 || pos == pal::string_t::npos)
    {
        trace::verbose(_X("Invalid hash %s value for deps file entry: %s"), library_hash.c_str(), library_name.c_str());
        return false;
    }
    
    // Build the relative hash path (what is added to the package directory path).
    pal::string_t relative_hash_path;
    if (library_hash_path.empty())
    {
        // Reserve approx 8 char_t's for the algorithm name.
        relative_hash_path.reserve(library_name.length() + 1 + library_version.length() + 16);
        relative_hash_path.append(library_name);
        relative_hash_path.append(_X("."));
        relative_hash_path.append(library_version);
        relative_hash_path.append(_X(".nupkg."));
        relative_hash_path.append(library_hash.substr(0, pos));
    }
    else
    {
        relative_hash_path.assign(library_hash_path);
    }

    // Build the directory that contains the hash file.
    pal::string_t hash_file;
    if (library_path.empty())
    {
        hash_file.reserve(base.length() + 1 +
            library_name.length() + 1 + library_version.length() + 1 +
            relative_hash_path.length());
        hash_file.assign(base);

        append_path(&hash_file, library_name.c_str());
        append_path(&hash_file, library_version.c_str());
    }
    else
    {
        hash_file.reserve(base.length() + 1 +
            library_path.length() + 1 +
            relative_hash_path.length());
        hash_file.assign(base);

        append_path(&hash_file, library_path.c_str());
    }

    // Append the relative path to the hash file.
    append_path(&hash_file, relative_hash_path.c_str());
    
    // Read the contents of the hash file.
    pal::ifstream_t fstream(hash_file);
    if (!fstream.good())
    {
        trace::verbose(_X("The hash file is invalid [%s]"), hash_file.c_str());
        return false;
    }

    // Obtain the hash from the file.
    std::string hash;
    hash.assign(pal::istreambuf_iterator_t(fstream),
        pal::istreambuf_iterator_t());
    pal::string_t pal_hash;
    if (!pal::utf8_palstring(hash.c_str(), &pal_hash))
    {
        return false;
    }

    // Check if contents match deps entry.
    pal::string_t entry_hash = library_hash.substr(pos + 1);
    if (entry_hash != pal_hash)
    {
        trace::verbose(_X("The file hash [%s][%d] did not match entry hash [%s][%d]"),
            pal_hash.c_str(), pal_hash.length(), entry_hash.c_str(), entry_hash.length());
        return false;
    }

    // All good, just append the relative dir to base.
    return to_full_path(base, &candidate);
}
Esempio n. 9
0
bool ends_with(const pal::string_t& value, const pal::string_t& suffix)
{
    return suffix.length() <= value.length() &&
        (0 == value.compare(value.length() - suffix.length(), suffix.length(), suffix));
}
Esempio n. 10
0
/*static*/ void framework_info::get_all_framework_infos(
    const pal::string_t& own_dir,
    const pal::string_t& fx_name,
    std::vector<framework_info>* framework_infos)
{
    std::vector<pal::string_t> global_dirs;
    bool multilevel_lookup = multilevel_lookup_enabled();

    // own_dir contains DIR_SEPARATOR appended that we need to remove.
    pal::string_t own_dir_temp = own_dir;
    remove_trailing_dir_seperator(&own_dir_temp);

    std::vector<pal::string_t> hive_dir;
    hive_dir.push_back(own_dir_temp);

    if (multilevel_lookup && pal::get_global_dotnet_dirs(&global_dirs))
    {
        for (pal::string_t dir : global_dirs)
        {
            if (!pal::are_paths_equal_with_normalized_casing(dir, own_dir_temp))
            {
                hive_dir.push_back(dir);
            }
        }
    }

    for (pal::string_t dir : hive_dir)
    {
        auto fx_shared_dir = dir;
        append_path(&fx_shared_dir, _X("shared"));

        if (pal::directory_exists(fx_shared_dir))
        {
            std::vector<pal::string_t> fx_names;
            if (fx_name.length())
            {
                // Use the provided framework name
                fx_names.push_back(fx_name);
            }
            else
            {
                // Read all frameworks, including "Microsoft.NETCore.App"
                pal::readdir_onlydirectories(fx_shared_dir, &fx_names);
            }

            for (pal::string_t fx_name : fx_names)
            {
                auto fx_dir = fx_shared_dir;
                append_path(&fx_dir, fx_name.c_str());

                if (pal::directory_exists(fx_dir))
                {
                    trace::verbose(_X("Gathering FX locations in [%s]"), fx_dir.c_str());

                    std::vector<pal::string_t> versions;
                    pal::readdir_onlydirectories(fx_dir, &versions);
                    for (const auto& ver : versions)
                    {
                        // Make sure we filter out any non-version folders.
                        fx_ver_t parsed;
                        if (fx_ver_t::parse(ver, &parsed, false))
                        {
                            trace::verbose(_X("Found FX version [%s]"), ver.c_str());

                            framework_info info(fx_name, fx_dir, parsed);
                            framework_infos->push_back(info);
                        }
                    }
                }
            }
        }
    }

    std::sort(framework_infos->begin(), framework_infos->end(), compare_by_name_and_version);
}