diff --git a/CMakeLists.txt b/CMakeLists.txt index cab85358180..9943a40bf01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,6 +524,8 @@ else() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,10485760") if(NOT BUILD_64) add_definitions(-DWINVER=0x0501 -D_WIN32_WINNT=0x0501) + else() + add_definitions(-DWINVER=0x0601 -D_WIN32_WINNT=0x0601) endif() endif() set(C_WARNINGS "-Waggregate-return -Wnested-externs -Wold-style-definition -Wstrict-prototypes") @@ -566,11 +568,13 @@ else() add_c_flag_if_supported(-Wformat-security C_SECURITY_FLAGS) add_cxx_flag_if_supported(-Wformat-security CXX_SECURITY_FLAGS) + if(0) # -fstack-protector add_c_flag_if_supported(-fstack-protector C_SECURITY_FLAGS) add_cxx_flag_if_supported(-fstack-protector CXX_SECURITY_FLAGS) add_c_flag_if_supported(-fstack-protector-strong C_SECURITY_FLAGS) add_cxx_flag_if_supported(-fstack-protector-strong CXX_SECURITY_FLAGS) + endif() # linker if (NOT WIN32) @@ -814,7 +818,7 @@ endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) if(MINGW) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj") - set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi) + set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;bcrypt) set(ICU_LIBRARIES ${Boost_LOCALE_LIBRARY} icuio icuin icuuc icudt icutu iconv) elseif(APPLE OR OPENBSD OR ANDROID) set(EXTRA_LIBRARIES "") diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 627038ca766..d308d11060b 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -37,6 +37,7 @@ #include "string_tools.h" #include "file_io_utils.h" #include "common/util.h" +#include "common/is_hdd.h" #include "cryptonote_basic/cryptonote_format_utils.h" #include "crypto/crypto.h" #include "profile_tools.h" diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index f0df05b0d27..1ca7bd33707 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -38,7 +38,8 @@ set(common_sources password.cpp perf_timer.cpp threadpool.cpp - updates.cpp) + updates.cpp + is_hdd.cpp) if (STACK_TRACE) list(APPEND common_sources stack_trace.cpp) @@ -67,7 +68,8 @@ set(common_private_headers perf_timer.h stack_trace.h threadpool.h - updates.h) + updates.h + is_hdd.h) monero_private_headers(common ${common_private_headers}) diff --git a/src/common/is_hdd.cpp b/src/common/is_hdd.cpp new file mode 100644 index 00000000000..4bcf3712a77 --- /dev/null +++ b/src/common/is_hdd.cpp @@ -0,0 +1,282 @@ +// Copyright (c) 2014-2018, 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 "is_hdd.h" +#include +#if defined(__GLIBC__) + #include + #include + #include +#elif defined(_WIN32) and (_WIN32_WINNT >= 0x0601) + #include + #include + #include +#endif + +namespace tools +{ +#if defined(__GLIBC__) + bool is_hdd_sysfs(const char *file_path, bool &result) + { + struct stat st; + std::string prefix; + if(stat(file_path, &st) == 0) + { + std::ostringstream s; + s << "/sys/dev/block/" << major(st.st_dev) << ":" << minor(st.st_dev); + prefix = s.str(); + } + else + { + return 0; + } + std::string attr_path = prefix + "/queue/rotational"; + FILE *f = fopen(attr_path.c_str(), "r"); + if(f == nullptr) + { + attr_path = prefix + "/../queue/rotational"; + f = fopen(attr_path.c_str(), "r"); + if(f == nullptr) + { + return 0; + } + } + unsigned short val = 0xdead; + int r = fscanf(f, "%hu", &val); + fclose(f); + if(r == 1) + { + result = (val == 1); + return 1; + } + return 0; + } +#elif defined(_WIN32) and (_WIN32_WINNT >= 0x0601) + //file path to logical volume + bool fp2lv(const char *fp, std::string &result) + { + HANDLE h = INVALID_HANDLE_VALUE; + h = CreateFile( + fp, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + nullptr + ); + if(h != INVALID_HANDLE_VALUE) + { + char * p; + DWORD p_len = GetFinalPathNameByHandleA( + h, + nullptr, + 0, + VOLUME_NAME_NT | FILE_NAME_NORMALIZED + ); + p = new char[p_len + 1]; + DWORD r_size = GetFinalPathNameByHandleA( + h, + p, + p_len + 1, + VOLUME_NAME_NT | FILE_NAME_NORMALIZED + ); + CloseHandle(h); + p[p_len] = 0; + std::regex r("^\\\\Device\\\\([^\\\\]+).*$"); + std::smatch m; + std::string i = p; + if(std::regex_match(i, m, r)) + { + delete[] p; + if(m.size() == 2) + { + result = m[1].str(); + return 1; + } + } + else + { + delete[] p; + } + } + return 0; + } + + //logical volume to physical volumes + bool lv2pv(const char *lv, std::vector &pvs) + { + HANDLE h = INVALID_HANDLE_VALUE; + std::string lv_path = "\\\\?\\"; + lv_path += lv; + h = CreateFile( + lv_path.c_str(), + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr + ); + if(h != INVALID_HANDLE_VALUE) + { + VOLUME_DISK_EXTENTS r; + DWORD r_size = 0; + BOOL success = DeviceIoControl( + h, + IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, + nullptr, + 0, + &r, + sizeof(r), + &r_size, + nullptr + ); + CloseHandle(h); + if(success and r_size == sizeof(r)) + { + for(uint32_t i = 0; i < r.NumberOfDiskExtents; ++i) + { + std::ostringstream ss; + ss << "PhysicalDrive" << r.Extents[i].DiskNumber; + pvs.push_back(ss.str()); + } + return 1; + } + } + else + { + CloseHandle(h); + } + return 0; + } + + bool win_device_has_seek_penalty(const char *pv, bool &result) + { + HANDLE h = INVALID_HANDLE_VALUE; + std::string pv_path = "\\\\?\\"; + pv_path += pv; + h = CreateFile( + pv_path.c_str(), + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr + ); + if(h != INVALID_HANDLE_VALUE) + { + STORAGE_PROPERTY_QUERY q = { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery + }; + DEVICE_SEEK_PENALTY_DESCRIPTOR r; + DWORD r_size = 0; + BOOL success = DeviceIoControl( + h, + IOCTL_STORAGE_QUERY_PROPERTY, + &q, + sizeof(q), + &r, + sizeof(r), + &r_size, + nullptr + ); + CloseHandle(h); + if(success and r_size == sizeof(r)) + { + result = r.IncursSeekPenalty; + return 1; + } + } + else + { + CloseHandle(h); + } + return 0; + } + + bool is_hdd_win_ioctl(const char *path, bool &result) + { + std::string lv; + bool lv_success = fp2lv(path, lv); + if(not lv_success) + { + return 0; + } + std::vector pvs; + bool pv_success = lv2pv(lv.c_str(), pvs); + if(not pv_success) + { + return 0; + } + bool a_result = 0; + bool a_success = 0; + for(auto &v: pvs) + { + bool q_result; + bool q_success = win_device_has_seek_penalty(v.c_str(), q_result); + a_success |= q_success; + if(q_success) + { + a_result |= q_result; + } + } + if(a_success) + { + result = a_result; + } + return a_success; + } +#endif + bool is_hdd(const char *path, bool &result) + { + #if defined(_WIN32) and (_WIN32_WINNT >= 0x0601) + return is_hdd_win_ioctl(path, result); + #elif defined(__GLIBC__) + return is_hdd_sysfs(path, result); + #else + return 0; + #endif + } + + bool is_hdd(const char *path) + { + bool result; + if(is_hdd(path, result)) + { + return result; + } + else + { + return 0; + } + } +} diff --git a/src/common/is_hdd.h b/src/common/is_hdd.h new file mode 100644 index 00000000000..d294b88b06c --- /dev/null +++ b/src/common/is_hdd.h @@ -0,0 +1,35 @@ +// Copyright (c) 2014-2018, 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 +#pragma once +namespace tools +{ + bool is_hdd(const char *path, bool &result); + bool is_hdd(const char *path); +} diff --git a/src/common/util.cpp b/src/common/util.cpp index 5e0d2726e83..8d710fe947e 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -733,65 +732,6 @@ std::string get_nix_version_display_string() #endif } - bool is_hdd(const char *path) - { -#ifdef __GLIBC__ - std::string device = ""; - struct stat st, dst; - if (stat(path, &st) < 0) - return 0; - - DIR *dir = opendir("/dev/block"); - if (!dir) - return 0; - struct dirent *de; - while ((de = readdir(dir))) - { - if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) - { - std::string dev_path = std::string("/dev/block/") + de->d_name; - char resolved[PATH_MAX]; - if (realpath(dev_path.c_str(), resolved) && !strncmp(resolved, "/dev/", 5)) - { - if (stat(resolved, &dst) == 0) - { - if (dst.st_rdev == st.st_dev) - { - // take out trailing digits (eg, sda1 -> sda) - char *ptr = resolved; - while (*ptr) - ++ptr; - while (ptr > resolved && isdigit(*--ptr)) - *ptr = 0; - device = resolved + 5; - break; - } - } - } - } - } - closedir(dir); - - if (device.empty()) - return 0; - - std::string sys_path = "/sys/block/" + device + "/queue/rotational"; - FILE *f = fopen(sys_path.c_str(), "r"); - if (!f) - return false; - char s[8]; - char *ptr = fgets(s, sizeof(s), f); - fclose(f); - if (!ptr) - return 0; - s[sizeof(s) - 1] = 0; - int n = atoi(s); // returns 0 on parse error - return n == 1; -#else - return 0; -#endif - } - namespace { boost::mutex max_concurrency_lock; diff --git a/src/common/util.h b/src/common/util.h index 8815232e28d..388f34480d1 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -230,8 +230,6 @@ namespace tools bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash); bool sha256sum(const std::string &filename, crypto::hash &hash); - bool is_hdd(const char *path); - boost::optional> parse_subaddress_lookahead(const std::string& str); std::string glob_to_regex(const std::string &val); diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt index 71dcedcab32..94c5d97d120 100644 --- a/src/crypto/CMakeLists.txt +++ b/src/crypto/CMakeLists.txt @@ -79,6 +79,7 @@ target_link_libraries(cncrypto epee ${Boost_SYSTEM_LIBRARY} PRIVATE + sodium ${EXTRA_LIBRARIES}) if (ARM) diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 3c7414640ba..454b317cd88 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -72,6 +72,7 @@ set(unit_tests_sources ringct.cpp output_selection.cpp vercmp.cpp + is_hdd.cpp ringdb.cpp) set(unit_tests_headers diff --git a/tests/unit_tests/is_hdd.cpp b/tests/unit_tests/is_hdd.cpp new file mode 100644 index 00000000000..0f7f7095171 --- /dev/null +++ b/tests/unit_tests/is_hdd.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2014-2018, 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 "common/is_hdd.h" +#include +#include + +#if defined(__GLIBC__) +TEST(is_hdd, linux_os_root) +{ + bool result; + std::string path = "/"; + EXPECT_TRUE(tools::is_hdd(path.c_str(), result)); +} +#elif defined(_WIN32) and (_WIN32_WINNT >= 0x0601) +TEST(is_hdd, win_os_c) +{ + bool result; + std::string path = "\\\\?\\C:\\Windows\\System32\\cmd.exe"; + EXPECT_TRUE(tools::is_hdd(path.c_str(), result)); + path = "\\\\?\\C:\\"; + EXPECT_TRUE(tools::is_hdd(path.c_str(), result)); + path = "C:\\"; + EXPECT_TRUE(tools::is_hdd(path.c_str(), result)); +} +#else +TEST(is_hdd, unknown_os) +{ + bool result; + std::string path = ""; + EXPECT_FALSE(tools::is_hdd(path.c_str(), result)); +} +#endif diff --git a/tests/unit_tests/ringdb.cpp b/tests/unit_tests/ringdb.cpp index 8b0ea10d416..9b842569a8f 100644 --- a/tests/unit_tests/ringdb.cpp +++ b/tests/unit_tests/ringdb.cpp @@ -47,7 +47,7 @@ static crypto::chacha_key generate_chacha_key() { crypto::chacha_key chacha_key; uint64_t password = crypto::rand(); - crypto::generate_chacha_key(std::string((const char*)&password, sizeof(password)), chacha_key); + crypto::generate_chacha_key(std::string((const char*)&password, sizeof(password)), chacha_key, 1); return chacha_key; }