diff options
| author | Ben Hilburn <ben.hilburn@ettus.com> | 2015-01-27 16:07:43 -0800 | 
|---|---|---|
| committer | Ben Hilburn <ben.hilburn@ettus.com> | 2015-01-27 16:07:43 -0800 | 
| commit | 75d519706b9b0956307a6a4bdc53c36376f19f03 (patch) | |
| tree | b2d2144c31c3ea04167ef7e3d1b14f7477c158cf /host/lib/utils | |
| parent | 8d0d0d01c0a2a5ed1a01da4360226a64ab8117bc (diff) | |
| download | uhd-75d519706b9b0956307a6a4bdc53c36376f19f03.tar.gz uhd-75d519706b9b0956307a6a4bdc53c36376f19f03.tar.bz2 uhd-75d519706b9b0956307a6a4bdc53c36376f19f03.zip  | |
Merging new UHD_IMAGES_DIR utilities and bug fixes.
Also includes NI-USRP Windows Registry Key fixes.
Diffstat (limited to 'host/lib/utils')
| -rw-r--r-- | host/lib/utils/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | host/lib/utils/images.cpp | 54 | ||||
| -rw-r--r-- | host/lib/utils/load_modules.cpp | 5 | ||||
| -rw-r--r-- | host/lib/utils/paths.cpp | 306 | 
4 files changed, 272 insertions, 94 deletions
diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index 106e2b650..369920ac1 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -132,7 +132,6 @@ SET_SOURCE_FILES_PROPERTIES(  LIBUHD_APPEND_SOURCES(      ${CMAKE_CURRENT_SOURCE_DIR}/csv.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/gain_group.cpp -    ${CMAKE_CURRENT_SOURCE_DIR}/images.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/load_modules.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp      ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp diff --git a/host/lib/utils/images.cpp b/host/lib/utils/images.cpp deleted file mode 100644 index 1ba2f81e6..000000000 --- a/host/lib/utils/images.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// Copyright 2010-2012 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#include <uhd/utils/images.hpp> -#include <uhd/exception.hpp> -#include <uhd/utils/paths.hpp> -#include <boost/foreach.hpp> -#include <boost/filesystem.hpp> -#include <vector> -#include <iostream> - -namespace fs = boost::filesystem; - -std::vector<fs::path> get_image_paths(void); //defined in paths.cpp - -/*********************************************************************** - * Find an image in the image paths - **********************************************************************/ -std::string uhd::find_image_path(const std::string &image_name){ -    if (fs::exists(image_name)){ -        return fs::system_complete(image_name).string(); -    } -    BOOST_FOREACH(const fs::path &path, get_image_paths()){ -        fs::path image_path = path / image_name; -        if (fs::exists(image_path)) return image_path.string(); -    } -    throw uhd::io_error("Could not find path for image: " + image_name + "\n\n" + uhd::print_images_error()); -} - -std::string uhd::find_images_downloader(void){ -    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / "uhd_images_downloader.py").string(); -} - -std::string uhd::print_images_error(void){ -    #ifdef UHD_PLATFORM_WIN32 -    return "As an Administrator, please run:\n\n\"" + find_images_downloader() + "\""; -    #else -    return "Please run:\n\nsudo \"" + find_images_downloader() + "\""; -    #endif -} diff --git a/host/lib/utils/load_modules.cpp b/host/lib/utils/load_modules.cpp index bee0d5304..aba3adeed 100644 --- a/host/lib/utils/load_modules.cpp +++ b/host/lib/utils/load_modules.cpp @@ -15,6 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include <uhd/utils/paths.hpp>  #include <uhd/utils/static.hpp>  #include <uhd/exception.hpp>  #include <boost/format.hpp> @@ -97,13 +98,11 @@ static void load_module_path(const fs::path &path){      }  } -std::vector<fs::path> get_module_paths(void); //defined in paths.cpp -  /*!   * Load all the modules given in the module paths.   */  UHD_STATIC_BLOCK(load_modules){ -    BOOST_FOREACH(const fs::path &path, get_module_paths()){ +    BOOST_FOREACH(const fs::path &path, uhd::get_module_paths()){          load_module_path(path);      }  } diff --git a/host/lib/utils/paths.cpp b/host/lib/utils/paths.cpp index 3e2bea1c6..e304555bd 100644 --- a/host/lib/utils/paths.cpp +++ b/host/lib/utils/paths.cpp @@ -16,37 +16,77 @@  //  #include <uhd/config.hpp> +#include <uhd/exception.hpp> +#include <uhd/transport/nirio/nifpga_lvbitx.h>  #include <uhd/utils/paths.hpp> -#include <boost/tokenizer.hpp> + +#include <boost/algorithm/string.hpp> +#include <boost/bind.hpp>  #include <boost/filesystem.hpp>  #include <boost/foreach.hpp> -#include <boost/bind.hpp> +#include <boost/format.hpp> +#include <boost/regex.hpp> +#include <boost/tokenizer.hpp> + +#include <cstdio>  #include <cstdlib> +#include <fstream> +#include <iostream> +#include <streambuf>  #include <string>  #include <vector> -#include <cstdlib> //getenv -#include <cstdio>  //P_tmpdir +  #ifdef BOOST_MSVC  #define USE_GET_TEMP_PATH  #include <windows.h> //GetTempPath  #endif +#ifdef USE_NIUSRP_WINREG_KEY +#define NIUSRP_WINREG_KEY "[HKLM\\Software\\National Instruments\\NI-USRP\\DriverBitfilesDir]" +#endif +  namespace fs = boost::filesystem; -/*********************************************************************** - * Get a list of paths for an environment variable - **********************************************************************/ -static std::string get_env_var(const std::string &var_name, const std::string &def_val = ""){ -    const char *var_value_ptr = std::getenv(var_name.c_str()); -    return (var_value_ptr == NULL)? def_val : var_value_ptr; -} +/*! 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. + */ +static std::string get_env_var(const std::string &var_name, +        const std::string &default_val = "") { -static std::vector<fs::path> get_env_paths(const std::string &var_name){ +    std::string env_result = default_val; +    char *env_var_str = NULL; -/*********************************************************************** - * Determine the paths separator - **********************************************************************/ +    /* 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()); +    if((not err) and (env_var_str != NULL)) +        env_result = std::string(env_var_str); +    free(env_var_str); +#else +    env_var_str = std::getenv(var_name.c_str()); +    if(env_var_str != NULL) +        env_result = std::string(env_var_str); +#endif +    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. + */ +static std::vector<std::string> get_env_paths(const std::string &var_name){  #ifdef UHD_PLATFORM_WIN32      static const std::string env_path_sep = ";";  #else @@ -59,40 +99,45 @@ static std::vector<fs::path> get_env_paths(const std::string &var_name){      std::string var_value = get_env_var(var_name); -    //convert to filesystem path, filter blank paths -    std::vector<fs::path> paths; -    if (var_value.empty()) return paths; //FIXME boost tokenizer throws w/ blank strings on some platforms +    std::vector<std::string> paths; + +    //convert to full filesystem path, filter blank paths +    if (var_value.empty()) return paths;      BOOST_FOREACH(const std::string &path_string, path_tokenizer(var_value)){          if (path_string.empty()) continue; -        paths.push_back(fs::system_complete(path_string)); +        paths.push_back(fs::system_complete(path_string).string());      } +      return paths;  } -/*********************************************************************** - * Get a list of special purpose paths - **********************************************************************/ -std::string uhd::get_pkg_path(void) -{ -    return get_env_var("UHD_PKG_PATH", UHD_PKG_PATH); -} +/*! 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. + */ +static std::string expand_home_directory(std::string path) { +    boost::trim(path); -std::vector<fs::path> get_image_paths(void){ -    std::vector<fs::path> paths = get_env_paths("UHD_IMAGE_PATH"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "images"); -    return paths; -} +    if(path.empty() || (path[0] != '~')) { +        return path; +    } -std::vector<fs::path> get_module_paths(void){ -    std::vector<fs::path> paths = get_env_paths("UHD_MODULE_PATH"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules"); -    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules"); -    return paths; +    std::string user_home_path = get_env_var("HOME"); +    path.replace(0, 1, user_home_path); + +    return path;  }  /***********************************************************************   * Implement the functions in paths.hpp   **********************************************************************/ + +  std::string uhd::get_tmp_path(void){      const char *tmp_path = NULL; @@ -136,3 +181,192 @@ std::string uhd::get_app_path(void){      return uhd::get_tmp_path();  } + +std::string uhd::get_pkg_path(void) { +    return get_env_var("UHD_PKG_PATH", UHD_PKG_PATH); +} + +std::vector<fs::path> uhd::get_module_paths(void){ +    std::vector<fs::path> paths; + +    std::vector<std::string> env_paths = get_env_paths("UHD_MODULE_PATH"); +    BOOST_FOREACH(std::string &str_path, env_paths) { +        paths.push_back(str_path); +    } + +    paths.push_back(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "modules"); +    paths.push_back(fs::path(uhd::get_pkg_path()) / "share" / "uhd" / "modules"); + +    return paths; +} + +#ifdef UHD_PLATFORM_WIN32 +#include <windows.h> +/*! + * 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. + */ +std::string _get_images_path_from_registry(const std::string& registry_key_path) { +    boost::smatch reg_key_match; +    //If a substring in the search path is enclosed in [] (square brackets) then it is interpreted as a registry path +    if (not boost::regex_search(registry_key_path, reg_key_match, boost::regex("\\[(.+)\\](.*)", boost::regex::icase))) +        return std::string(); +    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); + +    //Split the registry path into parent, key-path and value. +    boost::smatch reg_parent_match; +    if (not boost::regex_search(reg_key_path, reg_parent_match, boost::regex("^(.+?)\\\\(.+)\\\\(.+)$", boost::regex::icase))) +        return std::string(); +    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); + +    HKEY hkey_parent = HKEY_LOCAL_MACHINE; +    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; + +    TCHAR value_buff[1024]; +    DWORD value_buff_size = 1024*sizeof(TCHAR); + +    //Get a handle to the key location +    HKEY hkey_location; +    if (RegOpenKeyExA(hkey_parent, reg_path.c_str(), NULL, KEY_QUERY_VALUE, &hkey_location) != ERROR_SUCCESS) +        return std::string(); + +    //Query key value +    DWORD dw_type = REG_SZ; +    if(RegQueryValueExA(hkey_location, reg_val_name.c_str(), NULL, &dw_type, (LPBYTE)value_buff, &value_buff_size) == ERROR_SUCCESS) { +        RegCloseKey(hkey_location); +        if (value_buff_size >= 1024*sizeof(TCHAR)) { +            return std::string(); +        } else { +            std::string return_value(value_buff, value_buff_size-1); //value_buff_size includes the null terminator +            return_value += path_suffix; +            return return_value; +        } +    } else { +        return std::string(); +    } +} +#endif  /*UHD_PLATFORM_WIN32*/ + +std::string uhd::get_images_dir(const std::string search_paths) { + +    /*   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"); +    BOOST_FOREACH(possible_dir, env_paths) { +        if (fs::is_directory(fs::path(possible_dir))) { +                return possible_dir; +        } +    } + +    /* 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; + +#ifdef USE_NIUSRP_WINREG_KEY +    _search_paths = std::string(NIUSRP_WINREG_KEY) + "," + search_paths; +#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(",;")); +        BOOST_FOREACH(std::string& search_path, search_paths_vector) { + +            boost::algorithm::trim(search_path); +            if (search_path.empty()) continue; + +#ifdef UHD_PLATFORM_WIN32 +            possible_dir = _get_images_path_from_registry(search_path); +            if (possible_dir.empty()) { +                //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. +                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(""); +    } +} + +std::string uhd::find_image_path(const std::string &image_name, const std::string search_paths){ +    /* If a path was provided on the command-line or as a hint from the caller, +     * we default to that. */ +    if (fs::exists(image_name)){ +        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 { +            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."); +        } +    } + +    /* If we made it this far, then we didn't find anything. */ +    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")); +} + +std::string uhd::find_utility(std::string name) { +    return fs::path(fs::path(uhd::get_pkg_path()) / UHD_LIB_DIR / "uhd" / "utils" / name) +        .string(); +} + +std::string uhd::print_utility_error(std::string name){ +    #ifdef UHD_PLATFORM_WIN32 +    return "As an Administrator, please run:\n\n\"" + find_utility(name) + "\""; +    #else +    return "Please run:\n\n \"" + find_utility(name) + "\""; +    #endif +}  | 
