2010-08-09 18:24:08 +00:00
|
|
|
//
|
2015-07-24 14:27:24 +00:00
|
|
|
// Copyright 2010-2012,2015 Ettus Research LLC
|
2018-02-19 23:30:32 +00:00
|
|
|
// Copyright 2018 Ettus Research, a National Instruments Company
|
2010-08-09 18:24:08 +00:00
|
|
|
//
|
2018-02-19 23:30:32 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
2010-08-09 18:24:08 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include <uhd/config.hpp>
|
2015-01-28 00:07:43 +00:00
|
|
|
#include <uhd/exception.hpp>
|
2011-11-11 04:22:54 +00:00
|
|
|
#include <uhd/utils/paths.hpp>
|
2020-03-05 20:08:56 +00:00
|
|
|
#include <uhd/utils/log.hpp>
|
2018-02-17 02:21:44 +00:00
|
|
|
#include <uhdlib/utils/paths.hpp>
|
2015-01-28 00:07:43 +00:00
|
|
|
#include <boost/algorithm/string.hpp>
|
2019-10-29 21:13:58 +00:00
|
|
|
#include <boost/version.hpp>
|
2020-03-02 23:25:13 +00:00
|
|
|
#include <functional>
|
2019-10-29 21:13:58 +00:00
|
|
|
#if BOOST_VERSION >= 106100
|
2020-03-02 23:25:13 +00:00
|
|
|
# include <boost/dll/runtime_symbol_info.hpp>
|
2019-10-29 21:13:58 +00:00
|
|
|
#endif
|
2010-08-09 18:24:08 +00:00
|
|
|
#include <boost/filesystem.hpp>
|
2015-01-28 00:07:43 +00:00
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
#include <boost/tokenizer.hpp>
|
|
|
|
|
#include <cstdio>
|
2011-04-19 00:17:32 +00:00
|
|
|
#include <cstdlib>
|
2015-01-28 00:07:43 +00:00
|
|
|
#include <fstream>
|
|
|
|
|
#include <iostream>
|
2020-03-02 23:25:13 +00:00
|
|
|
#include <regex>
|
2015-01-28 00:07:43 +00:00
|
|
|
#include <streambuf>
|
2010-08-09 18:24:08 +00:00
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
2015-01-28 00:07:43 +00:00
|
|
|
|
2012-05-15 18:11:35 +00:00
|
|
|
#ifdef BOOST_MSVC
|
2020-03-02 23:25:13 +00:00
|
|
|
# define USE_GET_TEMP_PATH
|
|
|
|
|
# include <windows.h> //GetTempPath
|
2012-05-15 18:11:35 +00:00
|
|
|
#endif
|
2010-08-09 18:24:08 +00:00
|
|
|
|
|
|
|
|
namespace fs = boost::filesystem;
|
|
|
|
|
|
2020-03-06 00:23:07 +00:00
|
|
|
static constexpr char UHD_CAL_DATA_PATH_VAR[] = "UHD_CAL_DATA_PATH";
|
|
|
|
|
|
2015-01-28 00:07:43 +00:00
|
|
|
/*! Get the value of an environment variable.
|
|
|
|
|
*
|
|
|
|
|
* The returned std::string is the full environment variable string, and thus
|
|
|
|
|
* may actually contain multiple fields in the string with delimiters.
|
|
|
|
|
*
|
|
|
|
|
* \param var_name The name of the variable to search for.
|
|
|
|
|
* \param default_val A default string value to use if the path isn't found.
|
|
|
|
|
* \returns The string value of the environment variable.
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
static std::string get_env_var(
|
|
|
|
|
const std::string& var_name, const std::string& default_val = "")
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
std::string env_result = default_val;
|
2020-03-02 23:25:13 +00:00
|
|
|
char* env_var_str = NULL;
|
2013-10-29 00:58:46 +00:00
|
|
|
|
2015-01-28 00:07:43 +00:00
|
|
|
/* Some versions of MinGW don't expose `_dupenv_s` */
|
|
|
|
|
#if defined(UHD_PLATFORM_WIN32) && !defined(__MINGW32__)
|
|
|
|
|
size_t len;
|
|
|
|
|
errno_t err = _dupenv_s(&env_var_str, &len, var_name.c_str());
|
2020-03-02 23:25:13 +00:00
|
|
|
if ((not err) and (env_var_str != NULL))
|
2015-01-28 00:07:43 +00:00
|
|
|
env_result = std::string(env_var_str);
|
|
|
|
|
free(env_var_str);
|
|
|
|
|
#else
|
|
|
|
|
env_var_str = std::getenv(var_name.c_str());
|
2020-03-02 23:25:13 +00:00
|
|
|
if (env_var_str != NULL)
|
2015-01-28 00:07:43 +00:00
|
|
|
env_result = std::string(env_var_str);
|
|
|
|
|
#endif
|
2013-10-29 00:58:46 +00:00
|
|
|
|
2015-01-28 00:07:43 +00:00
|
|
|
return env_result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*! Get a vector of paths from an environment variable.
|
|
|
|
|
*
|
|
|
|
|
* Reads an environment variable, which should contain a list of paths, and
|
|
|
|
|
* returns a vector of those paths in the form of strings.
|
|
|
|
|
*
|
|
|
|
|
* \param var_name The environment variable name to read.
|
|
|
|
|
* \returns The vector of paths from the environment variable.
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
static std::vector<std::string> get_env_paths(const std::string& var_name)
|
|
|
|
|
{
|
2010-08-09 18:24:08 +00:00
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
static const std::string env_path_sep = ";";
|
|
|
|
|
#else
|
|
|
|
|
static const std::string env_path_sep = ":";
|
|
|
|
|
#endif /*UHD_PLATFORM_WIN32*/
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
#define path_tokenizer(inp) \
|
|
|
|
|
boost::tokenizer<boost::char_separator<char>>( \
|
|
|
|
|
inp, boost::char_separator<char>(env_path_sep.c_str()))
|
2011-01-06 23:38:56 +00:00
|
|
|
|
2011-04-19 00:17:32 +00:00
|
|
|
std::string var_value = get_env_var(var_name);
|
2010-08-09 18:24:08 +00:00
|
|
|
|
2015-01-28 00:07:43 +00:00
|
|
|
std::vector<std::string> paths;
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// convert to full filesystem path, filter blank paths
|
|
|
|
|
if (var_value.empty())
|
|
|
|
|
return paths;
|
|
|
|
|
for (const std::string& path_string : path_tokenizer(var_value)) {
|
|
|
|
|
if (path_string.empty())
|
|
|
|
|
continue;
|
2015-01-28 00:07:43 +00:00
|
|
|
paths.push_back(fs::system_complete(path_string).string());
|
2010-08-09 18:24:08 +00:00
|
|
|
}
|
2015-01-28 00:07:43 +00:00
|
|
|
|
2010-08-09 18:24:08 +00:00
|
|
|
return paths;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-24 14:27:24 +00:00
|
|
|
#ifndef UHD_PLATFORM_WIN32
|
2018-02-17 02:21:44 +00:00
|
|
|
// NOTE: This could be replaced by path_expandvars()
|
2015-01-28 00:07:43 +00:00
|
|
|
/*! Expand a tilde character to the $HOME path.
|
|
|
|
|
*
|
|
|
|
|
* The path passed to this function must start with the tilde character in order
|
|
|
|
|
* for this function to work properly. If it does not, it will simply return the
|
|
|
|
|
* original path. The $HOME environment variable must exist.
|
|
|
|
|
*
|
|
|
|
|
* \param path The path starting with the tilde character
|
|
|
|
|
* \returns The same path with the tilde expanded to contents of $HOME.
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
static std::string expand_home_directory(std::string path)
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
boost::trim(path);
|
2011-04-19 00:17:32 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
if (path.empty() || (path[0] != '~')) {
|
2015-01-28 00:07:43 +00:00
|
|
|
return path;
|
|
|
|
|
}
|
2010-08-09 18:24:08 +00:00
|
|
|
|
2015-01-28 00:07:43 +00:00
|
|
|
std::string user_home_path = get_env_var("HOME");
|
|
|
|
|
path.replace(0, 1, user_home_path);
|
|
|
|
|
|
|
|
|
|
return path;
|
2010-08-09 18:24:08 +00:00
|
|
|
}
|
2015-07-24 14:27:24 +00:00
|
|
|
#endif
|
2011-11-11 04:22:54 +00:00
|
|
|
|
2020-03-06 00:23:07 +00:00
|
|
|
fs::path uhd::get_xdg_data_home()
|
|
|
|
|
{
|
|
|
|
|
std::string xdg_data_home_str = get_env_var("XDG_DATA_HOME", "");
|
|
|
|
|
fs::path xdg_data_home(xdg_data_home_str);
|
|
|
|
|
if (!xdg_data_home_str.empty()) {
|
|
|
|
|
return fs::path(xdg_data_home_str);
|
|
|
|
|
}
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
const std::string localappdata = get_env_var("LOCALAPPDATA", "");
|
|
|
|
|
if (!localappdata.empty()) {
|
|
|
|
|
return fs::path(localappdata);
|
|
|
|
|
}
|
|
|
|
|
const std::string appdata = get_env_var("APPDATA", "");
|
|
|
|
|
if (!appdata.empty()) {
|
|
|
|
|
return fs::path(appdata);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
const std::string home = get_env_var("HOME", "");
|
|
|
|
|
if (home.empty()) {
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
const std::string err_msg =
|
|
|
|
|
"get_xdg_data_home(): Unable to find \%HOME\%, \%XDG_DATA_HOME\%, "
|
|
|
|
|
"\%LOCALAPPDATA\% or \%APPDATA\%.";
|
|
|
|
|
#else
|
|
|
|
|
const std::string err_msg =
|
|
|
|
|
"get_xdg_data_home(): Unable to find $HOME or $XDG_DATA_HOME.";
|
|
|
|
|
#endif
|
|
|
|
|
throw uhd::runtime_error(err_msg);
|
|
|
|
|
}
|
|
|
|
|
return fs::path(home) / ".local" / "share";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs::path uhd::get_xdg_config_home()
|
|
|
|
|
{
|
|
|
|
|
std::string xdg_config_home_str = get_env_var("XDG_CONFIG_HOME", "");
|
|
|
|
|
fs::path xdg_config_home(xdg_config_home_str);
|
|
|
|
|
if (!xdg_config_home_str.empty()) {
|
|
|
|
|
return fs::path(xdg_config_home_str);
|
|
|
|
|
}
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
const std::string localappdata = get_env_var("LOCALAPPDATA", "");
|
|
|
|
|
if (!localappdata.empty()) {
|
|
|
|
|
return fs::path(localappdata);
|
|
|
|
|
}
|
|
|
|
|
const std::string appdata = get_env_var("APPDATA", "");
|
|
|
|
|
if (!appdata.empty()) {
|
|
|
|
|
return fs::path(appdata);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
const std::string home = get_env_var("HOME", "");
|
|
|
|
|
if (home.empty()) {
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
const std::string err_msg =
|
|
|
|
|
"get_xdg_config_home(): Unable to find \%HOME\%, \%XDG_CONFIG_HOME\%, "
|
|
|
|
|
"\%LOCALAPPDATA\% or \%APPDATA\%.";
|
|
|
|
|
#else
|
|
|
|
|
const std::string err_msg =
|
|
|
|
|
"get_xdg_config_home(): Unable to find $HOME or $XDG_CONFIG_HOME.";
|
|
|
|
|
#endif
|
|
|
|
|
throw uhd::runtime_error(err_msg);
|
|
|
|
|
}
|
|
|
|
|
return fs::path(home) / ".config";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs::path uhd::get_legacy_config_home()
|
|
|
|
|
{
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
const std::string localappdata = get_env_var("LOCALAPPDATA", "");
|
|
|
|
|
if (!localappdata.empty()) {
|
|
|
|
|
return fs::path(localappdata) / ".uhd";
|
|
|
|
|
}
|
|
|
|
|
const std::string appdata = get_env_var("APPDATA", "");
|
|
|
|
|
if (!appdata.empty()) {
|
|
|
|
|
return fs::path(appdata) / ".uhd";
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
const std::string home = get_env_var("HOME", "");
|
|
|
|
|
if (home.empty()) {
|
|
|
|
|
throw uhd::runtime_error("Unable to find $HOME.");
|
|
|
|
|
}
|
|
|
|
|
return fs::path(home) / ".uhd";
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-11 04:22:54 +00:00
|
|
|
/***********************************************************************
|
|
|
|
|
* Implement the functions in paths.hpp
|
|
|
|
|
**********************************************************************/
|
2015-01-28 00:07:43 +00:00
|
|
|
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_tmp_path(void)
|
|
|
|
|
{
|
|
|
|
|
const char* tmp_path = NULL;
|
2012-05-15 18:11:35 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// try the official uhd temp path environment variable
|
2012-05-15 18:11:35 +00:00
|
|
|
tmp_path = std::getenv("UHD_TEMP_PATH");
|
2020-03-02 23:25:13 +00:00
|
|
|
if (tmp_path != NULL)
|
|
|
|
|
return tmp_path;
|
2012-05-15 18:11:35 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// try the windows function if available
|
|
|
|
|
#ifdef USE_GET_TEMP_PATH
|
2012-05-15 18:11:35 +00:00
|
|
|
char lpBuffer[2048];
|
2020-03-02 23:25:13 +00:00
|
|
|
if (GetTempPath(sizeof(lpBuffer), lpBuffer))
|
|
|
|
|
return lpBuffer;
|
|
|
|
|
#endif
|
2012-05-15 18:11:35 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// try windows environment variables
|
2012-05-15 18:11:35 +00:00
|
|
|
tmp_path = std::getenv("TMP");
|
2020-03-02 23:25:13 +00:00
|
|
|
if (tmp_path != NULL)
|
|
|
|
|
return tmp_path;
|
2011-11-11 04:22:54 +00:00
|
|
|
|
2012-05-15 18:11:35 +00:00
|
|
|
tmp_path = std::getenv("TEMP");
|
2020-03-02 23:25:13 +00:00
|
|
|
if (tmp_path != NULL)
|
|
|
|
|
return tmp_path;
|
2012-05-15 18:11:35 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// try the stdio define if available
|
|
|
|
|
#ifdef P_tmpdir
|
2013-11-27 20:11:23 +00:00
|
|
|
return P_tmpdir;
|
2020-03-02 23:25:13 +00:00
|
|
|
#else
|
2011-11-11 04:22:54 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// try unix environment variables
|
2012-05-15 18:11:35 +00:00
|
|
|
tmp_path = std::getenv("TMPDIR");
|
2020-03-02 23:25:13 +00:00
|
|
|
if (tmp_path != NULL)
|
|
|
|
|
return tmp_path;
|
2012-05-15 18:11:35 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// give up and use the unix default
|
2011-11-11 04:22:54 +00:00
|
|
|
return "/tmp";
|
2020-03-02 23:25:13 +00:00
|
|
|
#endif
|
2011-11-11 04:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-05 20:08:56 +00:00
|
|
|
// Only used for deprecated CSV file loader. Delete this once CSV support is
|
|
|
|
|
// removed.
|
|
|
|
|
std::string uhd::get_appdata_path(void)
|
|
|
|
|
{
|
|
|
|
|
const std::string uhdcalib_path = get_env_var("UHD_CONFIG_DIR");
|
|
|
|
|
if (not uhdcalib_path.empty()) {
|
|
|
|
|
UHD_LOG_WARNING("UHD",
|
|
|
|
|
"The environment variable UHD_CONFIG_DIR is deprecated. Refer to "
|
|
|
|
|
"https://files.ettus.com/manual/page_calibration.html for how to store "
|
|
|
|
|
"calibration data.");
|
|
|
|
|
return uhdcalib_path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string appdata_path = get_env_var("APPDATA");
|
|
|
|
|
if (not appdata_path.empty())
|
|
|
|
|
return appdata_path;
|
|
|
|
|
|
|
|
|
|
const std::string home_path = get_env_var("HOME");
|
|
|
|
|
if (not home_path.empty())
|
|
|
|
|
return home_path;
|
|
|
|
|
|
|
|
|
|
return uhd::get_tmp_path();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-10-29 21:13:58 +00:00
|
|
|
#if BOOST_VERSION >= 106100
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_pkg_path(void)
|
|
|
|
|
{
|
2019-10-29 21:13:58 +00:00
|
|
|
fs::path pkg_path = fs::path(uhd::get_lib_path()).parent_path().lexically_normal();
|
|
|
|
|
return get_env_var("UHD_PKG_PATH", pkg_path.string());
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_lib_path(void)
|
|
|
|
|
{
|
2019-10-29 21:13:58 +00:00
|
|
|
fs::path runtime_libfile_path = boost::dll::this_line_location();
|
2020-07-08 19:02:44 +00:00
|
|
|
//Normalize before decomposing path so result is reliable
|
|
|
|
|
fs::path lib_path = runtime_libfile_path.lexically_normal().parent_path();
|
|
|
|
|
return lib_path.string();
|
2019-10-29 21:13:58 +00:00
|
|
|
}
|
|
|
|
|
#else
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_pkg_path(void)
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
return get_env_var("UHD_PKG_PATH", UHD_PKG_PATH);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_lib_path(void)
|
|
|
|
|
{
|
2019-10-29 21:13:58 +00:00
|
|
|
fs::path lib_path = fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR;
|
|
|
|
|
return lib_path.string();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-03-04 23:23:28 +00:00
|
|
|
std::string uhd::get_cal_data_path(void)
|
|
|
|
|
{
|
2020-03-06 00:23:07 +00:00
|
|
|
// The easy case: User has set the environment variable
|
|
|
|
|
const std::string uhdcalib_path = get_env_var(UHD_CAL_DATA_PATH_VAR);
|
2020-03-04 23:23:28 +00:00
|
|
|
if (not uhdcalib_path.empty()) {
|
|
|
|
|
return uhdcalib_path;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 00:23:07 +00:00
|
|
|
// If not, we use the default location
|
|
|
|
|
const fs::path cal_data_path = get_xdg_data_home() / "uhd" / "cal";
|
2020-03-04 23:23:28 +00:00
|
|
|
return cal_data_path.string();
|
|
|
|
|
}
|
2019-10-29 21:13:58 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::vector<fs::path> uhd::get_module_paths(void)
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
std::vector<fs::path> paths;
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> env_paths = get_env_paths("UHD_MODULE_PATH");
|
2020-03-02 23:25:13 +00:00
|
|
|
for (std::string& str_path : env_paths) {
|
2015-01-28 00:07:43 +00:00
|
|
|
paths.push_back(str_path);
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-29 21:13:58 +00:00
|
|
|
paths.push_back(fs::path(uhd::get_lib_path()) / "uhd" / "modules");
|
2015-01-28 00:07:43 +00:00
|
|
|
paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules");
|
|
|
|
|
|
|
|
|
|
return paths;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
2020-03-02 23:25:13 +00:00
|
|
|
# include <windows.h>
|
2015-01-28 00:07:43 +00:00
|
|
|
/*!
|
|
|
|
|
* On Windows, query the system registry for the UHD images install path.
|
|
|
|
|
* If the key isn't found in the registry, an empty string is returned.
|
|
|
|
|
* \param registry_key_path The registry key to look for.
|
|
|
|
|
* \return The images path, formatted for windows.
|
|
|
|
|
*/
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string _get_images_path_from_registry(const std::string& registry_key_path)
|
|
|
|
|
{
|
2019-09-28 11:13:41 +00:00
|
|
|
std::smatch reg_key_match;
|
2020-03-02 23:25:13 +00:00
|
|
|
// If a substring in the search path is enclosed in [] (square brackets) then it is
|
|
|
|
|
// interpreted as a registry path
|
|
|
|
|
if (not std::regex_search(registry_key_path,
|
|
|
|
|
reg_key_match,
|
|
|
|
|
std::regex("\\[(.+)\\](.*)", std::regex::icase)))
|
2015-01-28 00:07:43 +00:00
|
|
|
return std::string();
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string reg_key_path =
|
|
|
|
|
std::string(reg_key_match[1].first, reg_key_match[1].second);
|
|
|
|
|
std::string path_suffix =
|
|
|
|
|
std::string(reg_key_match[2].first, reg_key_match[2].second);
|
2015-01-28 00:07:43 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// Split the registry path into parent, key-path and value.
|
2019-09-28 11:13:41 +00:00
|
|
|
std::smatch reg_parent_match;
|
2020-03-02 23:25:13 +00:00
|
|
|
if (not std::regex_search(reg_key_path,
|
|
|
|
|
reg_parent_match,
|
|
|
|
|
std::regex("^(.+?)\\\\(.+)\\\\(.+)$", std::regex::icase)))
|
2015-01-28 00:07:43 +00:00
|
|
|
return std::string();
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string reg_parent =
|
|
|
|
|
std::string(reg_parent_match[1].first, reg_parent_match[1].second);
|
|
|
|
|
std::string reg_path =
|
|
|
|
|
std::string(reg_parent_match[2].first, reg_parent_match[2].second);
|
|
|
|
|
std::string reg_val_name =
|
|
|
|
|
std::string(reg_parent_match[3].first, reg_parent_match[3].second);
|
2015-01-28 00:07:43 +00:00
|
|
|
|
|
|
|
|
HKEY hkey_parent = HKEY_LOCAL_MACHINE;
|
2020-03-02 23:25:13 +00:00
|
|
|
if (reg_parent == "HKEY_LOCAL_MACHINE")
|
|
|
|
|
hkey_parent = HKEY_LOCAL_MACHINE;
|
|
|
|
|
else if (reg_parent == "HKEY_CURRENT_USER")
|
|
|
|
|
hkey_parent = HKEY_CURRENT_USER;
|
|
|
|
|
else if (reg_parent == "HKEY_CLASSES_ROOT")
|
|
|
|
|
hkey_parent = HKEY_CLASSES_ROOT;
|
|
|
|
|
else if (reg_parent == "HKEY_CURRENT_CONFIG")
|
|
|
|
|
hkey_parent = HKEY_CURRENT_CONFIG;
|
|
|
|
|
else if (reg_parent == "HKEY_USERS")
|
|
|
|
|
hkey_parent = HKEY_CURRENT_USER;
|
2015-01-28 00:07:43 +00:00
|
|
|
|
|
|
|
|
TCHAR value_buff[1024];
|
2020-03-02 23:25:13 +00:00
|
|
|
DWORD value_buff_size = 1024 * sizeof(TCHAR);
|
2015-01-28 00:07:43 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// Get a handle to the key location
|
2015-01-28 00:07:43 +00:00
|
|
|
HKEY hkey_location;
|
2020-03-02 23:25:13 +00:00
|
|
|
if (RegOpenKeyExA(hkey_parent, reg_path.c_str(), 0, KEY_QUERY_VALUE, &hkey_location)
|
|
|
|
|
!= ERROR_SUCCESS)
|
2015-01-28 00:07:43 +00:00
|
|
|
return std::string();
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
// Query key value
|
2015-01-28 00:07:43 +00:00
|
|
|
DWORD dw_type = REG_SZ;
|
2020-03-02 23:25:13 +00:00
|
|
|
if (RegQueryValueExA(hkey_location,
|
|
|
|
|
reg_val_name.c_str(),
|
|
|
|
|
NULL,
|
|
|
|
|
&dw_type,
|
|
|
|
|
(LPBYTE)value_buff,
|
|
|
|
|
&value_buff_size)
|
|
|
|
|
== ERROR_SUCCESS) {
|
2015-01-28 00:07:43 +00:00
|
|
|
RegCloseKey(hkey_location);
|
2020-03-02 23:25:13 +00:00
|
|
|
if (value_buff_size >= 1024 * sizeof(TCHAR)) {
|
2015-01-28 00:07:43 +00:00
|
|
|
return std::string();
|
|
|
|
|
} else {
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string return_value(value_buff,
|
|
|
|
|
value_buff_size - 1); // value_buff_size includes the null terminator
|
2015-01-28 00:07:43 +00:00
|
|
|
return_value += path_suffix;
|
|
|
|
|
return return_value;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return std::string();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-02 23:25:13 +00:00
|
|
|
#endif /*UHD_PLATFORM_WIN32*/
|
2015-01-28 00:07:43 +00:00
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::get_images_dir(const std::string& search_paths)
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
/* This function will check for the existence of directories in this
|
|
|
|
|
* order:
|
|
|
|
|
*
|
|
|
|
|
* 1) `UHD_IMAGES_DIR` environment variable
|
|
|
|
|
* 2) Any paths passed to this function via `search_paths' (may contain
|
|
|
|
|
* Windows registry keys)
|
|
|
|
|
* 3) `UHD package path` / share / uhd / images
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
std::string possible_dir;
|
|
|
|
|
|
|
|
|
|
/* We will start by looking for a path indicated by the `UHD_IMAGES_DIR`
|
|
|
|
|
* environment variable. */
|
|
|
|
|
std::vector<std::string> env_paths = get_env_paths("UHD_IMAGES_DIR");
|
2020-03-02 23:25:13 +00:00
|
|
|
for (auto possible_dir : env_paths) {
|
2015-01-28 00:07:43 +00:00
|
|
|
if (fs::is_directory(fs::path(possible_dir))) {
|
2020-03-02 23:25:13 +00:00
|
|
|
return possible_dir;
|
2015-01-28 00:07:43 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* On Windows systems, we may need to modify the `search_paths` parameter
|
|
|
|
|
* (see below). Making a local copy for const correctness. */
|
|
|
|
|
std::string _search_paths = search_paths;
|
|
|
|
|
|
2016-01-15 23:19:47 +00:00
|
|
|
#ifdef UHD_IMAGES_DIR_WINREG_KEY
|
2016-02-10 19:16:08 +00:00
|
|
|
_search_paths = std::string(STR(UHD_IMAGES_DIR_WINREG_KEY)) + "," + search_paths;
|
2015-01-28 00:07:43 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Now we will parse and attempt to qualify the paths in the `search_paths`
|
|
|
|
|
* parameter. If this is Windows, we will check the system registry for
|
|
|
|
|
* these strings. */
|
|
|
|
|
if (!_search_paths.empty()) {
|
|
|
|
|
std::vector<std::string> search_paths_vector;
|
|
|
|
|
|
|
|
|
|
boost::split(search_paths_vector, _search_paths, boost::is_any_of(",;"));
|
2020-03-02 23:25:13 +00:00
|
|
|
for (std::string& search_path : search_paths_vector) {
|
2015-01-28 00:07:43 +00:00
|
|
|
boost::algorithm::trim(search_path);
|
2020-03-02 23:25:13 +00:00
|
|
|
if (search_path.empty())
|
|
|
|
|
continue;
|
2015-01-28 00:07:43 +00:00
|
|
|
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
possible_dir = _get_images_path_from_registry(search_path);
|
|
|
|
|
if (possible_dir.empty()) {
|
2020-03-02 23:25:13 +00:00
|
|
|
// Could not read from the registry due to missing key, invalid
|
|
|
|
|
// values, etc Just use the search path. The is_directory check
|
|
|
|
|
// will fail if this is a registry path and we will move on to
|
|
|
|
|
// the next item in the list.
|
2015-01-28 00:07:43 +00:00
|
|
|
possible_dir = search_path;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
possible_dir = expand_home_directory(search_path);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (fs::is_directory(fs::path(possible_dir))) {
|
|
|
|
|
return possible_dir;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finally, check for the default UHD images installation path. */
|
|
|
|
|
fs::path pkg_path = fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images";
|
|
|
|
|
if (fs::is_directory(pkg_path)) {
|
|
|
|
|
return pkg_path.string();
|
|
|
|
|
} else {
|
|
|
|
|
/* No luck. Return an empty string. */
|
|
|
|
|
return std::string("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::find_image_path(
|
|
|
|
|
const std::string& image_name, const std::string& search_paths)
|
|
|
|
|
{
|
2015-01-28 00:07:43 +00:00
|
|
|
/* If a path was provided on the command-line or as a hint from the caller,
|
|
|
|
|
* we default to that. */
|
2020-03-02 23:25:13 +00:00
|
|
|
if (fs::exists(image_name)) {
|
2015-01-28 00:07:43 +00:00
|
|
|
return fs::system_complete(image_name).string();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise, look for the image in the images directory. */
|
|
|
|
|
std::string images_dir = get_images_dir(search_paths);
|
|
|
|
|
if (!images_dir.empty()) {
|
|
|
|
|
fs::path image_path = fs::path(images_dir) / image_name;
|
|
|
|
|
if (fs::exists(image_path)) {
|
|
|
|
|
return image_path.string();
|
|
|
|
|
} else {
|
2020-03-02 23:25:13 +00:00
|
|
|
throw uhd::io_error("Could not find the image '" + image_name
|
|
|
|
|
+ "' in the image directory " + images_dir
|
|
|
|
|
+ "\nFor more information regarding image paths, please "
|
|
|
|
|
"refer to the UHD manual.");
|
2015-01-28 00:07:43 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we made it this far, then we didn't find anything. */
|
2015-02-10 00:25:45 +00:00
|
|
|
images_dir = "<no images directory located>";
|
2020-03-02 23:25:13 +00:00
|
|
|
throw uhd::io_error("Could not find path for image: " + image_name + "\n\n"
|
|
|
|
|
+ "Using images directory: " + images_dir + "\n\n"
|
|
|
|
|
+ "Set the environment variable 'UHD_IMAGES_DIR' appropriately or"
|
|
|
|
|
+ " follow the below instructions to download the images package."
|
|
|
|
|
+ "\n\n" + uhd::print_utility_error("uhd_images_downloader.py"));
|
2015-01-28 00:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::find_utility(const std::string& name)
|
|
|
|
|
{
|
|
|
|
|
return fs::path(fs::path(uhd::get_lib_path()) / "uhd" / "utils" / name).string();
|
2015-01-28 00:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
2020-03-02 23:25:13 +00:00
|
|
|
std::string uhd::print_utility_error(const std::string& name, const std::string& args)
|
|
|
|
|
{
|
|
|
|
|
#ifdef UHD_PLATFORM_WIN32
|
|
|
|
|
return "As an Administrator, please run:\n\n\"" + find_utility(name) + args + "\"";
|
|
|
|
|
#else
|
|
|
|
|
return "Please run:\n\n \"" + find_utility(name) + (args.empty() ? "" : (" " + args))
|
|
|
|
|
+ "\"";
|
|
|
|
|
#endif
|
2015-01-28 00:07:43 +00:00
|
|
|
}
|