-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
is_hdd update for windows and linux #4278
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,12 +38,13 @@ | |
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <sys/resource.h> | ||
#include <ustat.h> | ||
#include <sys/sysmacros.h> | ||
#include <unistd.h> | ||
#include <dirent.h> | ||
#include <string.h> | ||
#include <ctype.h> | ||
#include <string> | ||
#include <sstream> | ||
#endif | ||
|
||
#include "unbound.h" | ||
|
@@ -74,6 +75,11 @@ using namespace epee; | |
#include <boost/asio.hpp> | ||
#include <openssl/sha.h> | ||
|
||
#ifdef WIN32 | ||
#include <regex> | ||
#include <winioctl.h> | ||
#endif | ||
|
||
namespace tools | ||
{ | ||
std::function<void(int)> signal_handler::m_handler; | ||
|
@@ -733,63 +739,225 @@ std::string get_nix_version_display_string() | |
#endif | ||
} | ||
|
||
bool is_hdd(const char *path) | ||
#if defined(__GLIBC__) | ||
bool is_hdd_sysfs(const char *file_path, bool &result) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Somewhat quirky, but |
||
{ | ||
#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, "..")) | ||
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 false; | ||
} | ||
std::string attr_path = prefix + "/queue/rotational"; | ||
FILE *f = fopen(attr_path.c_str(), "r"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not |
||
if(f == nullptr) | ||
{ | ||
attr_path = prefix + "/../queue/rotational"; | ||
f = fopen(attr_path.c_str(), "r"); | ||
if(f == nullptr) | ||
{ | ||
return false; | ||
} | ||
} | ||
uint16_t val = 0xdead; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably best to make it a unsigned short if using %hu below. |
||
int r = fscanf(f, "%hu", &val); | ||
fclose(f); | ||
if(r == 1) | ||
{ | ||
result = val == 1; | ||
return true; | ||
} | ||
return false; | ||
} | ||
#elif defined(_WIN32) and (_WIN32_WINNT >= 0x0601) | ||
//file path to logical volume | ||
bool fp2lv(const char *fp, std::string &result) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be |
||
{ | ||
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[MAX_PATH + 1]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does |
||
DWORD r_size = GetFinalPathNameByHandleA( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this throws (it shouldn't really), then std::unique_ptr<void, close_handle> h{
CreateFile(...)
}; |
||
h, | ||
p, | ||
MAX_PATH, | ||
VOLUME_NAME_NT | FILE_NAME_NORMALIZED | ||
); | ||
CloseHandle(h); | ||
if(r_size > 0 and r_size <= MAX_PATH) | ||
{ | ||
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)) | ||
std::regex r("^\\\\Device\\\\([^\\\\]+).*$"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, let me walk through this logic, because this should be easy for a It looks like you want to grab all characters after #include <boost/range/iterator_range.hpp>
#include <boost/spirit/include/qi_char_.hpp>
#include <boost/spirit/include/qi_difference.hpp>
#include <boost/spirit/include/qi_kleene.hpp>
#include <boost/spirit/include/qi_lit.hpp>
#include <boost/spirit/include/qi_sequence.hpp>
namespace qi = boost::spirit::qi
boost::iterator_range<const char> match{};
if (qi::parse(p, p + strlen(p), (qi::lit("\\Device\\") >> *(qi::char_ - "\\")), match))
{
...
} This simply says match ... thoughts ? |
||
std::smatch m; | ||
std::string i = p; | ||
if(std::regex_match(i, m, r)) | ||
{ | ||
if (stat(resolved, &dst) == 0) | ||
if(m.size() == 2) | ||
{ | ||
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; | ||
} | ||
result = m[1].str(); | ||
return true; | ||
} | ||
} | ||
} | ||
} | ||
closedir(dir); | ||
return false; | ||
} | ||
|
||
if (device.empty()) | ||
return 0; | ||
//logical volume to physical volumes | ||
bool lv2pv(const char *lv, std::vector<std::string> &pvs) | ||
{ | ||
HANDLE h = INVALID_HANDLE_VALUE; | ||
std::string lv_path = "\\\\?\\"; | ||
lv_path += lv; | ||
h = CreateFile( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another |
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pop this before the loop, then do a |
||
ss << "PhysicalDrive" << r.Extents[i].DiskNumber; | ||
pvs.push_back(ss.str()); | ||
} | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
std::string sys_path = "/sys/block/" + device + "/queue/rotational"; | ||
FILE *f = fopen(sys_path.c_str(), "r"); | ||
if (!f) | ||
bool win_device_has_seek_penalny(const char *pv, bool &result) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. penalty |
||
{ | ||
HANDLE h = INVALID_HANDLE_VALUE; | ||
std::string pv_path = "\\\\?\\"; | ||
pv_path += pv; | ||
h = CreateFile( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another |
||
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 | ||
); | ||
if(success and r_size == sizeof(r)) | ||
{ | ||
result = r.IncursSeekPenalty; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That path seems to leak h. |
||
return true; | ||
} | ||
CloseHandle(h); | ||
} | ||
return false; | ||
} | ||
|
||
bool is_hdd_win_ioctl(const char *path, bool &result) | ||
{ | ||
std::string lv; | ||
bool lv_success = fp2lv(path, lv); | ||
if(not lv_success) | ||
{ | ||
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; | ||
} | ||
std::vector<std::string> pvs; | ||
bool pv_success = lv2pv(lv.c_str(), pvs); | ||
if(not pv_success) | ||
{ | ||
return false; | ||
} | ||
bool a_result = 0; | ||
bool a_success = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. false |
||
for(auto &v: pvs) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
bool q_result; | ||
bool q_success = win_device_has_seek_penalny(v.c_str(), q_result); | ||
a_success |= q_success; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is damn near obfuscation. Some early for (auto const& v : pvs)
{
const auto success = win_device_has_seek_penalty(v.c_str());
if (!success)
return boost::none;
if (success.value())
return true;
}
return false; Should this be inverted though? If any of the backing physical volumes isn't a local HDD, then LMDB may have a bad time. |
||
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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. false |
||
#endif | ||
} | ||
|
||
bool is_hdd(const char *path) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For right now, I recommend dropping this overload in favor of Also, hopefully in the not-too-distant future, this can be |
||
{ | ||
bool result; | ||
if(is_hdd(path, result)) | ||
{ | ||
return result; | ||
} | ||
else | ||
{ | ||
return 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. false |
||
} | ||
} | ||
|
||
namespace | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,6 +79,7 @@ target_link_libraries(cncrypto | |
epee | ||
${Boost_SYSTEM_LIBRARY} | ||
PRIVATE | ||
sodium | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this meant for another patch? |
||
${EXTRA_LIBRARIES}) | ||
|
||
if (ARM) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,6 +72,7 @@ set(unit_tests_sources | |
ringct.cpp | ||
output_selection.cpp | ||
vercmp.cpp | ||
test_a.cpp | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename to something sane |
||
ringdb.cpp) | ||
|
||
set(unit_tests_headers | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,7 @@ static crypto::chacha_key generate_chacha_key() | |
{ | ||
crypto::chacha_key chacha_key; | ||
uint64_t password = crypto::rand<uint64_t>(); | ||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this changed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is unrelated, fixed by #4272 |
||
return chacha_key; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include "common/util.h" | ||
#include <string> | ||
#include <gtest/gtest.h> | ||
|
||
#if defined(__GLIBC__) | ||
TEST(test_a, 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(test_a, 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(test_a, is_hdd_unknown_os) | ||
{ | ||
bool result; | ||
std::string path = ""; | ||
EXPECT_FALSE(tools::is_hdd(path.c_str(), result)); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we had problems with WIN32 before, and _WIN32 was the "best" one to use.