^C while in manual refresh will cancel the refresh, since that's often an annoying thing to have to wait for. Also, a manual refresh command will interrupt any running background refresh and take over, rather than wait for the background refresh to be done, and look to be hanging.
412 lines
14 KiB
C++
412 lines
14 KiB
C++
// Copyright (c) 2014-2015, The Monero Project
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without modification, are
|
|
// permitted provided that the following conditions are met:
|
|
//
|
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
// conditions and the following disclaimer.
|
|
//
|
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
// of conditions and the following disclaimer in the documentation and/or other
|
|
// materials provided with the distribution.
|
|
//
|
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
// used to endorse or promote products derived from this software without specific
|
|
// prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
|
|
|
#include <cstdio>
|
|
|
|
#include "include_base_utils.h"
|
|
using namespace epee;
|
|
|
|
#include "util.h"
|
|
#include "cryptonote_config.h"
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#include <strsafe.h>
|
|
#else
|
|
#include <sys/utsname.h>
|
|
#endif
|
|
#include <boost/filesystem.hpp>
|
|
|
|
|
|
namespace tools
|
|
{
|
|
std::function<void(int)> signal_handler::m_handler;
|
|
|
|
#ifdef WIN32
|
|
std::string get_windows_version_display_string()
|
|
{
|
|
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
|
|
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);
|
|
#define BUFSIZE 10000
|
|
|
|
char pszOS[BUFSIZE] = {0};
|
|
OSVERSIONINFOEX osvi;
|
|
SYSTEM_INFO si;
|
|
PGNSI pGNSI;
|
|
PGPI pGPI;
|
|
BOOL bOsVersionInfoEx;
|
|
DWORD dwType;
|
|
|
|
ZeroMemory(&si, sizeof(SYSTEM_INFO));
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);
|
|
|
|
if(!bOsVersionInfoEx) return pszOS;
|
|
|
|
// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
|
|
|
|
pGNSI = (PGNSI) GetProcAddress(
|
|
GetModuleHandle(TEXT("kernel32.dll")),
|
|
"GetNativeSystemInfo");
|
|
if(NULL != pGNSI)
|
|
pGNSI(&si);
|
|
else GetSystemInfo(&si);
|
|
|
|
if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId &&
|
|
osvi.dwMajorVersion > 4 )
|
|
{
|
|
StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));
|
|
|
|
// Test for the specific product.
|
|
|
|
if ( osvi.dwMajorVersion == 6 )
|
|
{
|
|
if( osvi.dwMinorVersion == 0 )
|
|
{
|
|
if( osvi.wProductType == VER_NT_WORKSTATION )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
|
|
}
|
|
|
|
if ( osvi.dwMinorVersion == 1 )
|
|
{
|
|
if( osvi.wProductType == VER_NT_WORKSTATION )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
|
|
}
|
|
|
|
pGPI = (PGPI) GetProcAddress(
|
|
GetModuleHandle(TEXT("kernel32.dll")),
|
|
"GetProductInfo");
|
|
|
|
pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);
|
|
|
|
switch( dwType )
|
|
{
|
|
case PRODUCT_ULTIMATE:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
|
|
break;
|
|
case PRODUCT_PROFESSIONAL:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
|
|
break;
|
|
case PRODUCT_HOME_PREMIUM:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
|
|
break;
|
|
case PRODUCT_HOME_BASIC:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
|
|
break;
|
|
case PRODUCT_ENTERPRISE:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
|
|
break;
|
|
case PRODUCT_BUSINESS:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
|
|
break;
|
|
case PRODUCT_STARTER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
|
|
break;
|
|
case PRODUCT_CLUSTER_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
|
|
break;
|
|
case PRODUCT_DATACENTER_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
|
|
break;
|
|
case PRODUCT_DATACENTER_SERVER_CORE:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
|
|
break;
|
|
case PRODUCT_ENTERPRISE_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
|
|
break;
|
|
case PRODUCT_ENTERPRISE_SERVER_CORE:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
|
|
break;
|
|
case PRODUCT_ENTERPRISE_SERVER_IA64:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
|
|
break;
|
|
case PRODUCT_SMALLBUSINESS_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
|
|
break;
|
|
case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
|
|
break;
|
|
case PRODUCT_STANDARD_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
|
|
break;
|
|
case PRODUCT_STANDARD_SERVER_CORE:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
|
|
break;
|
|
case PRODUCT_WEB_SERVER:
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
|
|
{
|
|
if( GetSystemMetrics(SM_SERVERR2) )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
|
|
else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
|
|
else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
|
|
else if( osvi.wProductType == VER_NT_WORKSTATION &&
|
|
si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
|
|
{
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
|
|
}
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));
|
|
|
|
// Test for the server type.
|
|
if ( osvi.wProductType != VER_NT_WORKSTATION )
|
|
{
|
|
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
|
|
}
|
|
|
|
else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
|
|
}
|
|
|
|
else
|
|
{
|
|
if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
|
|
else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
|
|
else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
|
|
{
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
|
|
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
|
|
}
|
|
|
|
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
|
|
{
|
|
StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));
|
|
|
|
if ( osvi.wProductType == VER_NT_WORKSTATION )
|
|
{
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
|
|
}
|
|
else
|
|
{
|
|
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
|
|
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
|
|
else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
|
|
}
|
|
}
|
|
|
|
// Include service pack (if any) and build number.
|
|
|
|
if( strlen(osvi.szCSDVersion) > 0 )
|
|
{
|
|
StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
|
|
StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
|
|
}
|
|
|
|
TCHAR buf[80];
|
|
|
|
StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
|
|
StringCchCat(pszOS, BUFSIZE, buf);
|
|
|
|
if ( osvi.dwMajorVersion >= 6 )
|
|
{
|
|
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
|
|
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
|
|
StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
|
|
}
|
|
|
|
return pszOS;
|
|
}
|
|
else
|
|
{
|
|
printf( "This sample does not support this version of Windows.\n");
|
|
return pszOS;
|
|
}
|
|
}
|
|
#else
|
|
std::string get_nix_version_display_string()
|
|
{
|
|
utsname un;
|
|
|
|
if(uname(&un) < 0)
|
|
return std::string("*nix: failed to get os version");
|
|
return std::string() + un.sysname + " " + un.version + " " + un.release;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
std::string get_os_version_string()
|
|
{
|
|
#ifdef WIN32
|
|
return get_windows_version_display_string();
|
|
#else
|
|
return get_nix_version_display_string();
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
std::string get_special_folder_path(int nfolder, bool iscreate)
|
|
{
|
|
namespace fs = boost::filesystem;
|
|
char psz_path[MAX_PATH] = "";
|
|
|
|
if(SHGetSpecialFolderPathA(NULL, psz_path, nfolder, iscreate))
|
|
{
|
|
return psz_path;
|
|
}
|
|
|
|
LOG_ERROR("SHGetSpecialFolderPathA() failed, could not obtain requested path.");
|
|
return "";
|
|
}
|
|
#endif
|
|
|
|
std::string get_default_data_dir()
|
|
{
|
|
/* Please for the love of god refactor the ifdefs out of this */
|
|
|
|
// namespace fs = boost::filesystem;
|
|
// Windows < Vista: C:\Documents and Settings\Username\Application Data\CRYPTONOTE_NAME
|
|
// Windows >= Vista: C:\Users\Username\AppData\Roaming\CRYPTONOTE_NAME
|
|
// Mac: ~/Library/Application Support/CRYPTONOTE_NAME
|
|
// Unix: ~/.CRYPTONOTE_NAME
|
|
std::string config_folder;
|
|
|
|
#ifdef WIN32
|
|
config_folder = get_special_folder_path(CSIDL_COMMON_APPDATA, true) + "\\" + CRYPTONOTE_NAME;
|
|
#else
|
|
std::string pathRet;
|
|
char* pszHome = getenv("HOME");
|
|
if (pszHome == NULL || strlen(pszHome) == 0)
|
|
pathRet = "/";
|
|
else
|
|
pathRet = pszHome;
|
|
#ifdef MAC_OSX
|
|
// Mac
|
|
pathRet /= "Library/Application Support";
|
|
config_folder = (pathRet + "/" + CRYPTONOTE_NAME);
|
|
#else
|
|
// Unix
|
|
config_folder = (pathRet + "/." + CRYPTONOTE_NAME);
|
|
#endif
|
|
#endif
|
|
|
|
return config_folder;
|
|
}
|
|
|
|
bool create_directories_if_necessary(const std::string& path)
|
|
{
|
|
namespace fs = boost::filesystem;
|
|
boost::system::error_code ec;
|
|
fs::path fs_path(path);
|
|
if (fs::is_directory(fs_path, ec))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool res = fs::create_directories(fs_path, ec);
|
|
if (res)
|
|
{
|
|
LOG_PRINT_L2("Created directory: " << path);
|
|
}
|
|
else
|
|
{
|
|
LOG_PRINT_L2("Can't create directory: " << path << ", err: "<< ec.message());
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
std::error_code replace_file(const std::string& replacement_name, const std::string& replaced_name)
|
|
{
|
|
int code;
|
|
#if defined(WIN32)
|
|
// Maximizing chances for success
|
|
DWORD attributes = ::GetFileAttributes(replaced_name.c_str());
|
|
if (INVALID_FILE_ATTRIBUTES != attributes)
|
|
{
|
|
::SetFileAttributes(replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY));
|
|
}
|
|
|
|
bool ok = 0 != ::MoveFileEx(replacement_name.c_str(), replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING);
|
|
code = ok ? 0 : static_cast<int>(::GetLastError());
|
|
#else
|
|
bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str());
|
|
code = ok ? 0 : errno;
|
|
#endif
|
|
return std::error_code(code, std::system_category());
|
|
}
|
|
|
|
bool sanitize_locale()
|
|
{
|
|
// boost::filesystem throws for "invalid" locales, such as en_US.UTF-8, or kjsdkfs,
|
|
// so reset it here before any calls to it
|
|
try
|
|
{
|
|
boost::filesystem::path p {std::string("test")};
|
|
p /= std::string("test");
|
|
}
|
|
catch (...)
|
|
{
|
|
setenv("LC_ALL", "C", 1);
|
|
setenv("LANG", "C", 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|