mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-28 14:45:51 +00:00
Implemented most build settings as constexpr functions and ported most of macro-based conditional compilation to if constexpr(); this significantly improves code quality and the chance of build success on different platforms and build configurations.
More code modernization.
This commit is contained in:
Vendored
+4
-2
@@ -30,8 +30,10 @@ target_compile_definitions(app_gtkmm_interface
|
||||
ENABLE_GLIB=1
|
||||
ENABLE_GLIBMM=1
|
||||
# For porting to GTK4
|
||||
GDK_DISABLE_DEPRECATED=1
|
||||
GTK_DISABLE_DEPRECATED=1
|
||||
# GTK_DISABLE_DEPRECATED=1
|
||||
# GDK_DISABLE_DEPRECATED=1
|
||||
# GTKMM_DISABLE_DEPRECATED=1
|
||||
# GDKMM_DISABLE_DEPRECATED=1
|
||||
)
|
||||
|
||||
# Support pre-C++17 glibmm with throw(...) exception specifications
|
||||
|
||||
@@ -27,7 +27,6 @@ target_sources(gsmartcontrol PRIVATE
|
||||
gsc_main_window_iconview.h
|
||||
gsc_preferences_window.cpp
|
||||
gsc_preferences_window.h
|
||||
gsc_settings.h
|
||||
gsc_startup_settings.h
|
||||
gsc_text_window.h
|
||||
local_glibmm.h
|
||||
|
||||
@@ -25,6 +25,7 @@ target_sources(applib PRIVATE
|
||||
command_executor_gui.h
|
||||
command_executor_factory.cpp
|
||||
command_executor_factory.h
|
||||
gsc_settings.h
|
||||
gui_utils.cpp
|
||||
gui_utils.h
|
||||
selftest.cpp
|
||||
@@ -59,7 +60,6 @@ target_link_libraries(applib
|
||||
app_gtkmm_interface
|
||||
app_pcrecpp_interface
|
||||
app_gettext_interface
|
||||
PRIVATE
|
||||
build_config
|
||||
)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Copyright:
|
||||
#include <vector>
|
||||
|
||||
#include "app_gtkmm_tools.h"
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
|
||||
@@ -128,13 +128,13 @@ Glib::ustring app_make_valid_utf8(const Glib::ustring& str)
|
||||
|
||||
Glib::ustring app_make_valid_utf8_from_command_output(const std::string& str)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
try {
|
||||
return Glib::locale_to_utf8(str); // detects invalid utf-8 sequences
|
||||
} catch (Glib::ConvertError& e) {
|
||||
// nothing, try to fix as it is
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
try {
|
||||
return Glib::locale_to_utf8(str); // detects invalid utf-8 sequences
|
||||
} catch (Glib::ConvertError& e) {
|
||||
// nothing, try to fix as it is
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return app_ustring_from_gchar(app_make_valid_utf_c(str.c_str()));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ Copyright:
|
||||
#include "hz/fs.h"
|
||||
|
||||
#include "async_command_executor.h"
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
using hz::Error;
|
||||
@@ -149,12 +150,12 @@ bool AsyncCommandExecutor::execute()
|
||||
// Set the locale for a child to Classic - otherwise it may mangle the output.
|
||||
// TODO: Disable this for JSON format.
|
||||
bool change_lang = true;
|
||||
#ifdef _WIN32
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// LANG is posix-only, so it has no effect on win32.
|
||||
// Unfortunately, I was unable to find a way to execute a child with a different
|
||||
// locale in win32. Locale seems to be non-inheritable, so setting it here won't help.
|
||||
change_lang = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::unique_ptr<gchar*, decltype(&g_strfreev)> child_env(g_get_environ(), &g_strfreev);
|
||||
if (change_lang) {
|
||||
|
||||
@@ -13,9 +13,9 @@ Copyright:
|
||||
|
||||
#include "applib/storage_device.h"
|
||||
#include "applib/storage_detector.h"
|
||||
#include "applib/gsc_settings.h"
|
||||
|
||||
#include "hz/main_tools.h"
|
||||
#include "gsc_settings.h" // in src directory
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@ Copyright:
|
||||
******************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup gsc
|
||||
/// \weakgroup gsc
|
||||
/// \ingroup applib
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef GSC_SETTINGS_H
|
||||
#define GSC_SETTINGS_H
|
||||
|
||||
#include "rconfig/rconfig.h"
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
/// Initializes ALL default settings.
|
||||
@@ -25,14 +25,14 @@ inline void init_default_settings()
|
||||
rconfig::set_default_data("system/config_autosave_timeout_sec", 3*60); // 3 minutes. 0 to disable.
|
||||
// rconfig::set_default_data("system/first_boot", true); // used to show the first-start warning.
|
||||
|
||||
#ifndef _WIN32
|
||||
rconfig::set_default_data("system/smartctl_binary", "smartctl"); // must be in PATH or use absolute path.
|
||||
rconfig::set_default_data("system/tw_cli_binary", "tw_cli"); // must be in PATH or use absolute path.
|
||||
#else
|
||||
rconfig::set_default_data("system/smartctl_binary", "smartctl-nc.exe"); // use no-console version by default.
|
||||
rconfig::set_default_data("system/tw_cli_binary", "tw_cli.exe");
|
||||
rconfig::set_default_data("system/areca_cli_binary", "cli.exe"); // if relative, an installation path is prepended (if found).
|
||||
#endif
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) {
|
||||
rconfig::set_default_data("system/smartctl_binary", "smartctl"); // must be in PATH or use absolute path.
|
||||
rconfig::set_default_data("system/tw_cli_binary", "tw_cli"); // must be in PATH or use absolute path.
|
||||
} else {
|
||||
rconfig::set_default_data("system/smartctl_binary", "smartctl-nc.exe"); // use no-console version by default.
|
||||
rconfig::set_default_data("system/tw_cli_binary", "tw_cli.exe");
|
||||
rconfig::set_default_data("system/areca_cli_binary", "cli.exe"); // if relative, an installation path is prepended (if found).
|
||||
}
|
||||
// search for "smartctl-nc.exe" in smartmontools installation first.
|
||||
rconfig::set_default_data("system/win32_search_smartctl_in_smartmontools", true);
|
||||
rconfig::set_default_data("system/win32_smartmontools_regpath", "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\smartmontools"); // in HKLM
|
||||
@@ -23,6 +23,7 @@ Copyright:
|
||||
#include "smartctl_ata_text_parser.h"
|
||||
#include "ata_storage_property_descr.h"
|
||||
#include "warning_colors.h"
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
|
||||
@@ -340,20 +341,20 @@ std::string SmartctlAtaTextParser::parse_byte_size(const std::string& str, int64
|
||||
std::string(1, static_cast<char>(0xc2)),
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
// if current locale is C, then probably we didn't change it at application
|
||||
// startup, so set it now (temporarily). Otherwise, just use the current locale's
|
||||
// thousands separator.
|
||||
{
|
||||
std::string old_locale = hz::locale_c_get();
|
||||
hz::ScopedCLocale loc("", old_locale == "C"); // set system locale if the current one is C
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// if current locale is C, then probably we didn't change it at application
|
||||
// startup, so set it now (temporarily). Otherwise, just use the current locale's
|
||||
// thousands separator.
|
||||
{
|
||||
std::string old_locale = hz::locale_c_get();
|
||||
hz::ScopedCLocale loc("", old_locale == "C"); // set system locale if the current one is C
|
||||
|
||||
struct lconv* lc = std::localeconv();
|
||||
if (lc && lc->thousands_sep && *(lc->thousands_sep)) {
|
||||
to_replace.push_back(lc->thousands_sep);
|
||||
}
|
||||
} // the locale is restored here
|
||||
#endif
|
||||
struct lconv* lc = std::localeconv();
|
||||
if (lc && lc->thousands_sep && lc->thousands_sep[0] != '\0') {
|
||||
to_replace.emplace_back(lc->thousands_sep);
|
||||
}
|
||||
} // the locale is restored here
|
||||
}
|
||||
|
||||
to_replace.emplace_back("bytes");
|
||||
std::string s = hz::string_replace_array_copy(hz::string_trim_copy(str), to_replace, "");
|
||||
|
||||
@@ -16,6 +16,7 @@ Copyright:
|
||||
#include "rconfig/rconfig.h"
|
||||
#include "app_pcrecpp.h"
|
||||
#include "hz/fs.h"
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
|
||||
@@ -23,54 +24,56 @@ hz::fs::path get_smartctl_binary()
|
||||
{
|
||||
auto smartctl_binary = hz::fs::u8path(rconfig::get_data<std::string>("system/smartctl_binary"));
|
||||
|
||||
#ifdef _WIN32
|
||||
// Look in smartmontools installation directory.
|
||||
hz::fs::path system_binary;
|
||||
do {
|
||||
bool use_smt = rconfig::get_data<bool>("system/win32_search_smartctl_in_smartmontools");
|
||||
if (!use_smt)
|
||||
break;
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// Look in smartmontools installation directory.
|
||||
hz::fs::path system_binary;
|
||||
do {
|
||||
bool use_smt = rconfig::get_data<bool>("system/win32_search_smartctl_in_smartmontools");
|
||||
if (!use_smt)
|
||||
break;
|
||||
|
||||
auto smt_regpath = rconfig::get_data<std::string>("system/win32_smartmontools_regpath");
|
||||
auto smt_regpath_wow = rconfig::get_data<std::string>("system/win32_smartmontools_regpath_wow"); // same as above, but with WOW6432Node
|
||||
auto smt_regkey = rconfig::get_data<std::string>("system/win32_smartmontools_regkey");
|
||||
auto smt_smartctl = rconfig::get_data<std::string>("system/win32_smartmontools_smartctl_binary");
|
||||
auto smt_regpath = rconfig::get_data<std::string>("system/win32_smartmontools_regpath");
|
||||
auto smt_regpath_wow = rconfig::get_data<std::string>("system/win32_smartmontools_regpath_wow"); // same as above, but with WOW6432Node
|
||||
auto smt_regkey = rconfig::get_data<std::string>("system/win32_smartmontools_regkey");
|
||||
auto smt_smartctl = rconfig::get_data<std::string>("system/win32_smartmontools_smartctl_binary");
|
||||
|
||||
if ((smt_regpath.empty() && smt_regpath_wow.empty()) || smt_regkey.empty() || smt_smartctl.empty())
|
||||
break;
|
||||
if ((smt_regpath.empty() && smt_regpath_wow.empty()) || smt_regkey.empty() || smt_smartctl.empty())
|
||||
break;
|
||||
|
||||
std::string smt_inst_dir;
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE, smt_regpath, smt_regkey, smt_inst_dir);
|
||||
if (smt_inst_dir.empty()) {
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE, smt_regpath_wow, smt_regkey, smt_inst_dir);
|
||||
}
|
||||
std::string smt_inst_dir;
|
||||
#ifdef _WIN32
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE, smt_regpath, smt_regkey, smt_inst_dir);
|
||||
if (smt_inst_dir.empty()) {
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE, smt_regpath_wow, smt_regkey, smt_inst_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (smt_inst_dir.empty()) {
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Smartmontools installation not found in \"HKLM\\"
|
||||
<< smt_regpath << "\\" << smt_regkey << "\".\n");
|
||||
break;
|
||||
}
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Smartmontools installation found at \"" << smt_inst_dir
|
||||
<< "\", using \"" << smt_smartctl << "\".\n");
|
||||
if (smt_inst_dir.empty()) {
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Smartmontools installation not found in \"HKLM\\"
|
||||
<< smt_regpath << "\\" << smt_regkey << "\".\n");
|
||||
break;
|
||||
}
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Smartmontools installation found at \"" << smt_inst_dir
|
||||
<< "\", using \"" << smt_smartctl << "\".\n");
|
||||
|
||||
auto p = hz::fs::u8path(smt_inst_dir) / hz::fs::u8path(smt_smartctl);
|
||||
auto p = hz::fs::u8path(smt_inst_dir) / hz::fs::u8path(smt_smartctl);
|
||||
|
||||
if (!hz::fs::exists(p) || !hz::fs::is_regular_file(p))
|
||||
break;
|
||||
if (!hz::fs::exists(p) || !hz::fs::is_regular_file(p))
|
||||
break;
|
||||
|
||||
system_binary = p;
|
||||
} while (false);
|
||||
system_binary = p;
|
||||
} while (false);
|
||||
|
||||
if (!system_binary.empty()) {
|
||||
smartctl_binary = system_binary;
|
||||
if (!system_binary.empty()) {
|
||||
smartctl_binary = system_binary;
|
||||
|
||||
} else if (smartctl_binary.is_relative()) {
|
||||
// If smartctl path is relative, and it's Windows, and the package seems to contain smartctl, use our own binary.
|
||||
if (auto app_dir = hz::fs_get_application_dir(); !app_dir.empty() && hz::fs::exists(app_dir / smartctl_binary)) {
|
||||
smartctl_binary = app_dir / smartctl_binary;
|
||||
} else if (smartctl_binary.is_relative()) {
|
||||
// If smartctl path is relative, and it's Windows, and the package seems to contain smartctl, use our own binary.
|
||||
if (auto app_dir = hz::fs_get_application_dir(); !app_dir.empty() && hz::fs::exists(app_dir / smartctl_binary)) {
|
||||
smartctl_binary = app_dir / smartctl_binary;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return smartctl_binary;
|
||||
}
|
||||
@@ -81,15 +84,15 @@ std::string execute_smartctl(const std::string& device, const std::string& devic
|
||||
const std::string& command_options,
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex, std::string& smartctl_output)
|
||||
{
|
||||
#ifndef _WIN32 // win32 doesn't have slashes in devices names
|
||||
{
|
||||
// win32 doesn't have slashes in devices names. For others, check that slash is present.
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) {
|
||||
std::string::size_type pos = device.rfind('/'); // find basename
|
||||
if (pos == std::string::npos) {
|
||||
debug_out_error("app", DBG_FUNC_MSG << "Invalid device name \"" << device << "\".\n");
|
||||
return _("Invalid device name specified.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (!smartctl_ex) // if it doesn't exist, create a default one
|
||||
smartctl_ex = std::make_shared<SmartctlExecutor>();
|
||||
|
||||
@@ -13,7 +13,7 @@ Copyright:
|
||||
#include <gtkmm.h> // compose()
|
||||
#include <algorithm>
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
#include "build_config.h"
|
||||
|
||||
#include "hz/debug.h"
|
||||
|
||||
@@ -37,19 +37,15 @@ std::string StorageDetector::detect(std::vector<StorageDevicePtr>& drives, const
|
||||
|
||||
// Try each one and move to next if it fails.
|
||||
|
||||
#if defined CONFIG_KERNEL_LINUX
|
||||
if constexpr(BuildEnv::is_kernel_linux()) {
|
||||
error_message = detect_drives_linux(all_detected, ex_factory); // linux /proc/partitions as fallback.
|
||||
|
||||
error_message = detect_drives_linux(all_detected, ex_factory); // linux /proc/partitions as fallback.
|
||||
} else if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
error_message = detect_drives_win32(all_detected, ex_factory); // win32
|
||||
|
||||
#elif defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
error_message = detect_drives_win32(all_detected, ex_factory); // win32
|
||||
|
||||
#else // freebsd, etc...
|
||||
|
||||
error_message = detect_drives_other(all_detected, ex_factory); // bsd, etc... . scans /dev.
|
||||
|
||||
#endif
|
||||
} else { // freebsd, etc...
|
||||
error_message = detect_drives_other(all_detected, ex_factory); // bsd, etc... . scans /dev.
|
||||
}
|
||||
|
||||
if (all_detected.empty()) {
|
||||
debug_out_warn("app", DBG_FUNC_MSG << "Cannot detect drives: None of the drive detection methods returned any drives.\n");
|
||||
|
||||
@@ -42,11 +42,11 @@ inline std::string execute_tw_cli(const CommandExecutorFactoryPtr& ex_factory, c
|
||||
std::vector<std::string> binaries; // binaries to try
|
||||
// Note: tw_cli is automatically added to PATH in windows, no need to look for it.
|
||||
binaries.push_back(binary);
|
||||
#ifdef CONFIG_KERNEL_LINUX
|
||||
// tw_cli may be named tw_cli.x86 or tw_cli.x86_64 in linux
|
||||
binaries.push_back(binary + ".x86_64"); // try this first
|
||||
binaries.push_back(binary + ".x86");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_linux()) {
|
||||
// tw_cli may be named tw_cli.x86 or tw_cli.x86_64 in linux
|
||||
binaries.push_back(binary + ".x86_64"); // try this first
|
||||
binaries.push_back(binary + ".x86");
|
||||
}
|
||||
|
||||
for (const auto& bin : binaries) {
|
||||
executor->set_command(Glib::shell_quote(bin), command_options);
|
||||
|
||||
@@ -9,14 +9,12 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if defined CONFIG_KERNEL_LINUX
|
||||
#include "build_config.h"
|
||||
|
||||
#include "local_glibmm.h"
|
||||
#include <algorithm> // std::find
|
||||
#include <cstdio> // std::fgets(), std::FILE
|
||||
#include <cerrno> // ENXIO
|
||||
// #include <cerrno> // ENXIO
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
@@ -1108,6 +1106,4 @@ std::string detect_drives_linux(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
|
||||
|
||||
#endif // CONFIG_KERNEL_LINUX
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -12,9 +12,7 @@ Copyright:
|
||||
#ifndef STORAGE_DETECTOR_LINUX_H
|
||||
#define STORAGE_DETECTOR_LINUX_H
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if defined CONFIG_KERNEL_LINUX
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
#include <string>
|
||||
@@ -30,8 +28,6 @@ std::string detect_drives_linux(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9,12 +9,11 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if !defined CONFIG_KERNEL_LINUX && !defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
#include "build_config.h"
|
||||
|
||||
#include "local_glibmm.h"
|
||||
#include <algorithm> // std::sort
|
||||
#include <cerrno>
|
||||
|
||||
#if defined CONFIG_KERNEL_OPENBSD || defined CONFIG_KERNEL_NETBSD
|
||||
#include <util.h> // getrawpartition()
|
||||
@@ -37,11 +36,11 @@ std::string detect_drives_other(std::vector<StorageDevicePtr>& drives,
|
||||
std::vector<std::string> devices;
|
||||
|
||||
std::string sdev_config_path;
|
||||
#if defined CONFIG_KERNEL_SOLARIS
|
||||
if constexpr(BuildEnv::is_kernel_solaris()) {
|
||||
sdev_config_path = "system/solaris_dev_path";
|
||||
#else // other unixes
|
||||
} else { // other unixes
|
||||
sdev_config_path = "system/unix_sdev_path";
|
||||
#endif
|
||||
}
|
||||
|
||||
// defaults to /dev for freebsd, /dev/rdsk for solaris.
|
||||
auto dev_dir = rconfig::get_data<std::string>(sdev_config_path);
|
||||
@@ -57,130 +56,125 @@ std::string detect_drives_other(std::vector<StorageDevicePtr>& drives,
|
||||
return _("Device directory does not exist.");
|
||||
}
|
||||
|
||||
|
||||
#if defined CONFIG_KERNEL_FREEBSD || defined CONFIG_KERNEL_DRAGONFLY
|
||||
// FreeBSD example device names:
|
||||
// * /dev/ad0 - ide disk 0. /dev/ad0a - non-slice dos partition 1.
|
||||
// * /dev/da1s1e - scsi disk 1 (second disk), slice 1 (aka dos partition 1),
|
||||
// bsd partition e (multiple bsd partitions may be inside one dos partition).
|
||||
// * /dev/acd0 - first cdrom. /dev/acd0c - ?.
|
||||
// Info: http://www.freebsd.org/doc/en/books/handbook/disks-naming.html
|
||||
|
||||
// Of two machines I had access to, freebsd 6.3 had only real devices,
|
||||
// while freebsd 4.10 had lots of dummy ones (ad1, ad2, ad3, da0, da1, da2, da3, sa0, ...).
|
||||
|
||||
static const std::vector<std::string> whitelist = {
|
||||
"/^ad[0-9]+$/", // adN without suffix - fbsd ide
|
||||
"/^da[0-9]+$/", // daN without suffix - fbsd scsi, usb
|
||||
"/^ada[0-9]+$/", // adaN without suffix - fbsd ata cam
|
||||
// "/ ^sa[0-9]+$/", // saN without suffix - fbsd scsi tape
|
||||
// "/^ast[0-9]+$/", // astN without suffix - fbsd ide tape
|
||||
"/^aacd[0-9]+$/", // fbsd adaptec raid
|
||||
"/^mlxd[0-9]+$/", // fbsd mylex raid
|
||||
"/^mlyd[0-9]+$/", // fbsd mylex raid
|
||||
"/^amrd[0-9]+$/", // fbsd AMI raid
|
||||
"/^idad[0-9]+$/", // fbsd compaq raid
|
||||
"/^twed[0-9]+$/", // fbsd 3ware raid
|
||||
// these are checked by smartctl, but they are not mentioned in freebsd docs:
|
||||
"/^tw[ae][0-9]+$/", // fbsd 3ware raid
|
||||
};
|
||||
// unused: acd - ide cdrom, cd - scsi cdrom, mcd - mitsumi cdrom, scd - sony cdrom,
|
||||
// fd - floppy, fla - diskonchip flash.
|
||||
std::vector<std::string> whitelist;
|
||||
|
||||
|
||||
#elif defined CONFIG_KERNEL_SOLARIS
|
||||
if constexpr(BuildEnv::is_kernel_freebsd() || BuildEnv::is_kernel_dragonfly()) {
|
||||
// FreeBSD example device names:
|
||||
// * /dev/ad0 - ide disk 0. /dev/ad0a - non-slice dos partition 1.
|
||||
// * /dev/da1s1e - scsi disk 1 (second disk), slice 1 (aka dos partition 1),
|
||||
// bsd partition e (multiple bsd partitions may be inside one dos partition).
|
||||
// * /dev/acd0 - first cdrom. /dev/acd0c - ?.
|
||||
// Info: http://www.freebsd.org/doc/en/books/handbook/disks-naming.html
|
||||
|
||||
// /dev/rdsk contains "raw" physical char devices, as opposed to
|
||||
// "filesystem" block devices in /dev/dsk. smartctl needs rdsk.
|
||||
// Of two machines I had access to, freebsd 6.3 had only real devices,
|
||||
// while freebsd 4.10 had lots of dummy ones (ad1, ad2, ad3, da0, da1, da2, da3, sa0, ...).
|
||||
|
||||
// x86:
|
||||
whitelist = {
|
||||
"/^ad[0-9]+$/", // adN without suffix - fbsd ide
|
||||
"/^da[0-9]+$/", // daN without suffix - fbsd scsi, usb
|
||||
"/^ada[0-9]+$/", // adaN without suffix - fbsd ata cam
|
||||
// "/ ^sa[0-9]+$/", // saN without suffix - fbsd scsi tape
|
||||
// "/^ast[0-9]+$/", // astN without suffix - fbsd ide tape
|
||||
"/^aacd[0-9]+$/", // fbsd adaptec raid
|
||||
"/^mlxd[0-9]+$/", // fbsd mylex raid
|
||||
"/^mlyd[0-9]+$/", // fbsd mylex raid
|
||||
"/^amrd[0-9]+$/", // fbsd AMI raid
|
||||
"/^idad[0-9]+$/", // fbsd compaq raid
|
||||
"/^twed[0-9]+$/", // fbsd 3ware raid
|
||||
// these are checked by smartctl, but they are not mentioned in freebsd docs:
|
||||
"/^tw[ae][0-9]+$/", // fbsd 3ware raid
|
||||
};
|
||||
// unused: acd - ide cdrom, cd - scsi cdrom, mcd - mitsumi cdrom, scd - sony cdrom,
|
||||
// fd - floppy, fla - diskonchip flash.
|
||||
|
||||
// /dev/rdsk/c0t0d0p0:1
|
||||
// Where c0 is the controller number.
|
||||
// t0 is the target (SCSI ID number) (omit for ATAPI)
|
||||
// d0 is always 0 for SCSI, the drive # for ATAPI
|
||||
// p0 is the partition (p0 is the entire disk, or p1 - p4)
|
||||
// :1 is the logical drive (c - z or 1 - 24) (that is, logical partitions inside extended partition)
|
||||
} else if constexpr(BuildEnv::is_kernel_solaris()) {
|
||||
|
||||
// /dev/rdsk/c0d0p2:1
|
||||
// where p2 means the extended partition (type 0x05) is partition 2 (out of 1-4) and
|
||||
// ":1" is the 2nd extended partition (:0 would be the first extended partition). -- not sure about this!
|
||||
// /dev/rdsk contains "raw" physical char devices, as opposed to
|
||||
// "filesystem" block devices in /dev/dsk. smartctl needs rdsk.
|
||||
|
||||
// p0 whole physical disk
|
||||
// p1 - p4 Four primary fdisk partitions
|
||||
// p5 - p30 26 logical drives in extended DOS partition (not implemented by Solaris)
|
||||
// s0 - s15 16 slices in the Solaris FDISK partition (SPARC has only 8)
|
||||
// On Solaris, by convention, s2 is the whole Solaris partition.
|
||||
// x86:
|
||||
|
||||
// SPARC: There are no *p* devices on sparc afaik, only slices. By convention,
|
||||
// s2 is used as a "whole" disk there (but not with EFI partitions!).
|
||||
// So, c0d0s2 is the whole disk there.
|
||||
// x86 has both c0d0s2 and c0d0p2, where s2 is a whole solaris partition.
|
||||
// /dev/rdsk/c0t0d0p0:1
|
||||
// Where c0 is the controller number.
|
||||
// t0 is the target (SCSI ID number) (omit for ATAPI)
|
||||
// d0 is always 0 for SCSI, the drive # for ATAPI
|
||||
// p0 is the partition (p0 is the entire disk, or p1 - p4)
|
||||
// :1 is the logical drive (c - z or 1 - 24) (that is, logical partitions inside extended partition)
|
||||
|
||||
// NOTE: It seems that smartctl searches for s0 (aka root partition) in the end. I'm not sure
|
||||
// what implications this has for x86, but we replicate this behaviour.
|
||||
// /dev/rdsk/c0d0p2:1
|
||||
// where p2 means the extended partition (type 0x05) is partition 2 (out of 1-4) and
|
||||
// ":1" is the 2nd extended partition (:0 would be the first extended partition). -- not sure about this!
|
||||
|
||||
// Note: Cdroms are ATAPI, so they pose as SCSI, as opposed to IDE hds.
|
||||
// p0 whole physical disk
|
||||
// p1 - p4 Four primary fdisk partitions
|
||||
// p5 - p30 26 logical drives in extended DOS partition (not implemented by Solaris)
|
||||
// s0 - s15 16 slices in the Solaris FDISK partition (SPARC has only 8)
|
||||
// On Solaris, by convention, s2 is the whole Solaris partition.
|
||||
|
||||
// TODO: No idea how to implement /dev/rmt (scsi tape devices),
|
||||
// I have no files in that directory.
|
||||
// SPARC: There are no *p* devices on sparc afaik, only slices. By convention,
|
||||
// s2 is used as a "whole" disk there (but not with EFI partitions!).
|
||||
// So, c0d0s2 is the whole disk there.
|
||||
// x86 has both c0d0s2 and c0d0p2, where s2 is a whole solaris partition.
|
||||
|
||||
static const std::vector<std::string> whitelist = {
|
||||
"/^c[0-9]+(?:t[0-9]+)?d[0-9]+s0$/"
|
||||
};
|
||||
// NOTE: It seems that smartctl searches for s0 (aka root partition) in the end. I'm not sure
|
||||
// what implications this has for x86, but we replicate this behaviour.
|
||||
|
||||
// Note: Cdroms are ATAPI, so they pose as SCSI, as opposed to IDE hds.
|
||||
|
||||
// TODO: No idea how to implement /dev/rmt (scsi tape devices),
|
||||
// I have no files in that directory.
|
||||
|
||||
whitelist = {
|
||||
"/^c[0-9]+(?:t[0-9]+)?d[0-9]+s0$/"
|
||||
};
|
||||
|
||||
} else if constexpr(BuildEnv::is_kernel_openbsd() || BuildEnv::is_kernel_netbsd()) {
|
||||
|
||||
// OpenBSD / NetBSD have /dev/wdNc for IDE/ATA, /dev/sdNc for SCSI disk,
|
||||
// /dev/stNc for scsi tape. N is [0-9]+. "c" means "whole disk" (not sure about
|
||||
// different architectures though). There are no "sdN" devices, only "sdNP".
|
||||
// Another manual says that wd0d would be a whole disk, while wd0c is its
|
||||
// bsd part only (on x86) (only on netbsd?). Anyway, getrawpartition() gives
|
||||
// us the letter we need.
|
||||
// There is no additional level of names for BSD subpartitions (unlike freebsd).
|
||||
// cd0a is cdrom.
|
||||
// Dummy devices are present.
|
||||
|
||||
// Note: This detection may take a while (probably due to open() check).
|
||||
|
||||
char whole_part = 'a';
|
||||
#if defined CONFIG_KERNEL_OPENBSD || defined CONFIG_KERNEL_NETBSD
|
||||
whole_part = 'a' + getrawpartition(); // from bsd's util.h
|
||||
#endif
|
||||
|
||||
whitelist = {
|
||||
hz::string_sprintf("/^wd[0-9]+%c$/", whole_part),
|
||||
hz::string_sprintf("/^sd[0-9]+%c$/", whole_part),
|
||||
hz::string_sprintf("/^st[0-9]+%c$/", whole_part),
|
||||
};
|
||||
|
||||
|
||||
} else if constexpr(BuildEnv::is_kernel_darwin()) {
|
||||
// Darwin has /dev/disk0, /dev/disk0s1, etc...
|
||||
// Only real devices are present, so no need for additional checks.
|
||||
|
||||
#elif defined CONFIG_KERNEL_OPENBSD || defined CONFIG_KERNEL_NETBSD
|
||||
|
||||
// OpenBSD / NetBSD have /dev/wdNc for IDE/ATA, /dev/sdNc for SCSI disk,
|
||||
// /dev/stNc for scsi tape. N is [0-9]+. "c" means "whole disk" (not sure about
|
||||
// different architectures though). There are no "sdN" devices, only "sdNP".
|
||||
// Another manual says that wd0d would be a whole disk, while wd0c is its
|
||||
// bsd part only (on x86) (only on netbsd?). Anyway, getrawpartition() gives
|
||||
// us the letter we need.
|
||||
// There is no additional level of names for BSD subpartitions (unlike freebsd).
|
||||
// cd0a is cdrom.
|
||||
// Dummy devices are present.
|
||||
|
||||
// Note: This detection may take a while (probably due to open() check).
|
||||
|
||||
char whole_part = 'a' + getrawpartition(); // from bsd's util.h
|
||||
|
||||
static const std::vector<std::string> whitelist = {
|
||||
hz::string_sprintf("/^wd[0-9]+%c$/", whole_part),
|
||||
hz::string_sprintf("/^sd[0-9]+%c$/", whole_part),
|
||||
hz::string_sprintf("/^st[0-9]+%c$/", whole_part),
|
||||
};
|
||||
whitelist = {
|
||||
"/^disk[0-9]+$/"
|
||||
};
|
||||
|
||||
|
||||
} else if constexpr(BuildEnv::is_kernel_qnx()) {
|
||||
// QNX has /dev/hd0, /dev/hd0t78 (partition?).
|
||||
// Afaik, IDE and SCSI have the same prefix. fd for floppy, cd for cdrom.
|
||||
// Not sure about the tapes.
|
||||
// Only real devices are present, so no need for additional checks.
|
||||
|
||||
#elif defined CONFIG_KERNEL_DARWIN
|
||||
whitelist = {
|
||||
"/^hd[0-9]+$/",
|
||||
};
|
||||
|
||||
// Darwin has /dev/disk0, /dev/disk0s1, etc...
|
||||
// Only real devices are present, so no need for additional checks.
|
||||
|
||||
static const std::vector<std::string> whitelist = {
|
||||
"/^disk[0-9]+$/"
|
||||
};
|
||||
|
||||
|
||||
#elif defined CONFIG_KERNEL_QNX
|
||||
|
||||
// QNX has /dev/hd0, /dev/hd0t78 (partition?).
|
||||
// Afaik, IDE and SCSI have the same prefix. fd for floppy, cd for cdrom.
|
||||
// Not sure about the tapes.
|
||||
// Only real devices are present, so no need for additional checks.
|
||||
|
||||
static const std::vector<std::string> whitelist = {
|
||||
"/^hd[0-9]+$/",
|
||||
};
|
||||
|
||||
#else // unsupported OS
|
||||
|
||||
static const std::vector<std::string> whitelist;
|
||||
|
||||
#endif // unix platforms
|
||||
} // unix platforms
|
||||
|
||||
|
||||
std::vector<hz::fs::path> matched_devices;
|
||||
@@ -212,8 +206,8 @@ std::string detect_drives_other(std::vector<StorageDevicePtr>& drives,
|
||||
|
||||
|
||||
// List ones who need dummy device filtering
|
||||
#if defined CONFIG_KERNEL_FREEBSD || defined CONFIG_KERNEL_DRAGONFLY \
|
||||
|| defined CONFIG_KERNEL_OPENBSD || defined CONFIG_KERNEL_NETBSD
|
||||
if constexpr(BuildEnv::is_kernel_freebsd() || BuildEnv::is_kernel_dragonfly()
|
||||
|| BuildEnv::is_kernel_openbsd() || BuildEnv::is_kernel_netbsd()) {
|
||||
// Since we may have encountered dummy devices, we should check
|
||||
// if they really exist. Unfortunately, this involves opening them, which
|
||||
// is not good with some media (e.g. it may hang on audio cd (freebsd, maybe others), etc...).
|
||||
@@ -248,25 +242,22 @@ std::string detect_drives_other(std::vector<StorageDevicePtr>& drives,
|
||||
devices.push_back(dev.string());
|
||||
}
|
||||
|
||||
#else // not *BSD
|
||||
} else { // not *BSD
|
||||
for (const auto& dev : matched_devices) {
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Device \"" << dev << "\" matched the whitelist, adding to device list.\n");
|
||||
devices.push_back(dev);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
for (auto& device : devices) {
|
||||
drives.emplace_back(std::make_shared<StorageDevice>(device));
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // !defined CONFIG_KERNEL_LINUX && !defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -12,10 +12,7 @@ Copyright:
|
||||
#ifndef STORAGE_DETECTOR_OTHER_H
|
||||
#define STORAGE_DETECTOR_OTHER_H
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if !defined CONFIG_KERNEL_LINUX && !defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -30,8 +27,6 @@ std::string detect_drives_other(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -9,18 +9,19 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
#include "build_config.h"
|
||||
|
||||
#include "local_glibmm.h"
|
||||
#include <windows.h> // CreateFileA(), CloseHandle(), etc...
|
||||
#include <set>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> // CreateFileA(), CloseHandle(), etc...
|
||||
#endif
|
||||
|
||||
#include "hz/win32_tools.h"
|
||||
#include "hz/string_sprintf.h"
|
||||
#include "hz/fs.h"
|
||||
@@ -105,6 +106,7 @@ std::map<char, DriveLetterInfo> win32_get_drive_letter_map()
|
||||
{
|
||||
std::map<char, DriveLetterInfo> drive_letter_map;
|
||||
|
||||
#ifdef _WIN32
|
||||
std::bitset<32> drives(GetLogicalDrives());
|
||||
|
||||
// Check which drives are fixed
|
||||
@@ -160,7 +162,7 @@ std::map<char, DriveLetterInfo> win32_get_drive_letter_map()
|
||||
|
||||
drive_letter_map[drive] = dli;
|
||||
}
|
||||
|
||||
#endif
|
||||
return drive_letter_map;
|
||||
}
|
||||
|
||||
@@ -185,7 +187,7 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDevicePtr>& drive
|
||||
return _("Smartctl binary is not specified in configuration.");
|
||||
}
|
||||
|
||||
std::string smartctl_def_options = rconfig::get_data<std::string>("system/smartctl_options");
|
||||
auto smartctl_def_options = rconfig::get_data<std::string>("system/smartctl_options");
|
||||
|
||||
if (!smartctl_def_options.empty())
|
||||
smartctl_def_options += " ";
|
||||
@@ -224,9 +226,9 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDevicePtr>& drive
|
||||
const pcrecpp::RE port_re = app_pcre_re("/^(/dev/[a-z0-9]+),([0-9]+)[ \\t]+-d[ \\t]+([^ \\t\\n]+)/i");
|
||||
const pcrecpp::RE dev_re = app_pcre_re("/^/dev/sd([a-z])$/");
|
||||
|
||||
for (std::size_t i = 0; i < lines.size(); ++i) {
|
||||
for (const auto& line : lines) {
|
||||
std::string dev, port_str, type;
|
||||
if (port_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &dev, &port_str, &type)) {
|
||||
if (port_re.PartialMatch(hz::string_trim_copy(line), &dev, &port_str, &type)) {
|
||||
std::string sd_letter;
|
||||
int drive_num = -1;
|
||||
if (dev_re.PartialMatch(dev, &sd_letter)) {
|
||||
@@ -250,7 +252,7 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDevicePtr>& drive
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -276,7 +278,7 @@ inline std::string execute_areca_cli(const CommandExecutorFactoryPtr& ex_factory
|
||||
return _("Areca CLI returned an empty output.");
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -394,14 +396,16 @@ inline std::string areca_cli_get_drives(const std::string& cli_binary, const std
|
||||
pcrecpp::RE exp_header_re = app_pcre_re("/^\\s*#\\s+Enc#/mi");
|
||||
|
||||
FormatType format_type = FormatType::Unknown;
|
||||
for (std::size_t i = 0; i < lines.size(); ++i) {
|
||||
if (noenc1_header_re.PartialMatch(lines.at(i))) {
|
||||
for (const auto& line : lines) {
|
||||
if (noenc1_header_re.PartialMatch(line)) {
|
||||
format_type = FormatType::NoEnc1;
|
||||
break;
|
||||
} else if (noenc2_header_re.PartialMatch(lines.at(i))) {
|
||||
}
|
||||
if (noenc2_header_re.PartialMatch(line)) {
|
||||
format_type = FormatType::NoEnc2;
|
||||
break;
|
||||
} else if (exp_header_re.PartialMatch(lines.at(i))) {
|
||||
}
|
||||
if (exp_header_re.PartialMatch(line)) {
|
||||
format_type = FormatType::Enc;
|
||||
break;
|
||||
}
|
||||
@@ -423,11 +427,11 @@ inline std::string areca_cli_get_drives(const std::string& cli_binary, const std
|
||||
debug_out_dump("app", "Areca controller doesn't have any enclosures.\n");
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < lines.size(); ++i) {
|
||||
for (const auto& line : lines) {
|
||||
std::string port_str, model_str;
|
||||
if (has_enclosure) {
|
||||
std::string enclosure_str;
|
||||
if (exp_port_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &enclosure_str, &port_str, &model_str)) {
|
||||
if (exp_port_re.PartialMatch(hz::string_trim_copy(line), &enclosure_str, &port_str, &model_str)) {
|
||||
if (model_str != "N.A.") {
|
||||
int port = hz::string_to_number_nolocale<int>(port_str);
|
||||
int enclosure = hz::string_to_number_nolocale<int>(enclosure_str);
|
||||
@@ -438,7 +442,7 @@ inline std::string areca_cli_get_drives(const std::string& cli_binary, const std
|
||||
}
|
||||
} else { // no enclosures
|
||||
pcrecpp::RE port_re = (format_type == FormatType::NoEnc1 ? noexp1_port_re : noexp2_port_re);
|
||||
if (port_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &port_str, &model_str)) {
|
||||
if (port_re.PartialMatch(hz::string_trim_copy(line), &port_str, &model_str)) {
|
||||
if (model_str != "N.A.") {
|
||||
int port = hz::string_to_number_nolocale<int>(port_str);
|
||||
drives.emplace_back(std::make_shared<StorageDevice>(dev, "areca," + hz::number_to_string_nolocale(port)));
|
||||
@@ -448,7 +452,7 @@ inline std::string areca_cli_get_drives(const std::string& cli_binary, const std
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -493,30 +497,33 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
int scan_controllers = rconfig::get_data<int>("system/win32_areca_scan_controllers");
|
||||
if (scan_controllers == 0) { // disabled
|
||||
debug_out_info("app", "Areca controller scanning is disabled through config.\n");
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Check if Areca tools are installed
|
||||
|
||||
std::string cli_inst_path;
|
||||
#ifdef _WIN32
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CLI", "InstallPath", cli_inst_path);
|
||||
if (cli_inst_path.empty()) {
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CLI", "InstallPath", cli_inst_path);
|
||||
}
|
||||
|
||||
#endif
|
||||
if (scan_controllers == 2) { // auto
|
||||
std::string http_inst_path;
|
||||
#ifdef _WIN32
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\archttp", "InstallPath", http_inst_path);
|
||||
if (http_inst_path.empty()) {
|
||||
hz::win32_get_registry_value_string(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\archttp", "InstallPath", http_inst_path);
|
||||
}
|
||||
#endif
|
||||
if (cli_inst_path.empty() && http_inst_path.empty()) {
|
||||
debug_out_info("app", "No Areca software found. Install Areca CLI or set \"system/win32_areca_scan_controllers\" config key to 1 to force scanning.\n");
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
if (http_inst_path.empty()) {
|
||||
debug_out_dump("app", "Areca HTTP installation not found.\n");
|
||||
@@ -535,7 +542,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
int use_cli = rconfig::get_data<int>("system/win32_areca_use_cli");
|
||||
bool scan_detect = (use_cli != 1); // Whether to detect using sequential port scanning. Only do that if CLI is not forced.
|
||||
if (use_cli == 2) { // auto
|
||||
use_cli = cli_found;
|
||||
use_cli = cli_found ? 1 : 0;
|
||||
}
|
||||
|
||||
hz::fs::path cli_binary;
|
||||
@@ -557,7 +564,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
// Since CLI may segfault if there are no drives, test the controller presence first.
|
||||
// It doesn't matter if we use areca,N or areca,N/E - we will still get a different
|
||||
// error if there's no controller.
|
||||
if (use_cli) {
|
||||
if (use_cli != 0) {
|
||||
debug_out_dump("app", "Testing Areca controller presence using smartctl...\n");
|
||||
|
||||
auto drive = std::make_shared<StorageDevice>("/dev/arcmsr0", "areca,1");
|
||||
@@ -571,7 +578,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
}
|
||||
}
|
||||
|
||||
if (use_cli) {
|
||||
if (use_cli != 0) {
|
||||
debug_out_info("app", "Scanning Areca drives using CLI...\n");
|
||||
int cli_max_controllers = 1; // TODO controller # with CLI.
|
||||
for (int controller_no = 0; controller_no < cli_max_controllers; ++controller_no) {
|
||||
@@ -623,6 +630,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
for (int enclosure_no = 1; enclosure_no < max_enclosures; ++enclosure_no) {
|
||||
debug_out_dump("app", "Starting brute-force port scan (enclosure #" << enclosure_no << ") on 1-" << max_enc_ports << " ports, device \"" << dev
|
||||
<< "\". Change the maximums by setting \"system/win32_areca_onc_max_scan_port\" and \"system/win32_areca_enc_max_enclosure\" config keys.\n");
|
||||
// FIXME Not sure whether we should ignore this error message
|
||||
error_message = smartctl_scan_drives_sequentially(dev, "areca,%d/" + hz::number_to_string_nolocale(enclosure_no), 1, max_enc_ports, drives, ex_factory, last_output);
|
||||
}
|
||||
}
|
||||
@@ -633,7 +641,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
|
||||
debug_out_info("app", DBG_FUNC_MSG << "Finished scanning Areca controllers.\n");
|
||||
|
||||
return std::string();
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -673,21 +681,21 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
// Find out their serial numbers and whether there are Arecas there.
|
||||
std::map<std::string, StorageDevicePtr> serials;
|
||||
for (std::size_t i = 0; i < drives.size(); ++i) {
|
||||
std::string local_error = drives.at(i)->fetch_basic_data_and_parse(smartctl_ex);
|
||||
for (auto& drive : drives) {
|
||||
std::string local_error = drive->fetch_basic_data_and_parse(smartctl_ex);
|
||||
if (!local_error.empty()) {
|
||||
debug_out_info("app", "Smartctl returned with an error: " << local_error << "\n");
|
||||
// Don't exit, just report it.
|
||||
}
|
||||
if (!drives.at(i)->get_serial_number().empty()) {
|
||||
if (!drive->get_serial_number().empty()) {
|
||||
// add model as well, who knows, there may be duplicates across vendors
|
||||
std::string drive_serial_id = drives.at(i)->get_model_name() + "_" + drives.at(i)->get_serial_number();
|
||||
serials[drive_serial_id] = drives.at(i);
|
||||
std::string drive_serial_id = drive->get_model_name() + "_" + drive->get_serial_number();
|
||||
serials[drive_serial_id] = drive;
|
||||
}
|
||||
|
||||
// See if there are any areca devices. This is not implemented yet by smartctl (as of 6.0),
|
||||
// but if it ever is, we can skip our own detection below.
|
||||
std::string type_arg = drives.at(i)->get_type_argument();
|
||||
std::string type_arg = drive->get_type_argument();
|
||||
if (type_arg.find("areca") != std::string::npos) {
|
||||
areca_open_found = true;
|
||||
}
|
||||
@@ -698,8 +706,9 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
debug_out_info("app", "Starting sequential scan of \\\\.\\PhysicalDriveN devices...\n");
|
||||
|
||||
int num_failed = 0;
|
||||
for (int drive_num = 0; ; ++drive_num) {
|
||||
[[maybe_unused]] int num_failed = 0;
|
||||
const int max_drives = 255; // arbitrary
|
||||
for (int drive_num = 0; drive_num < max_drives; ++drive_num) {
|
||||
|
||||
// If the drive was already encountered in --scan-open (with a port number), skip it.
|
||||
if (used_pds.count(drive_num) > 0) {
|
||||
@@ -709,6 +718,7 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
std::string phys_name = hz::string_sprintf("\\\\.\\PhysicalDrive%d", drive_num);
|
||||
|
||||
#ifdef _WIN32
|
||||
// If the drive is openable, then it's there. Yes, CreateFile() is open, not create.
|
||||
// NOTE: Administrative privileges are required to open it.
|
||||
// We don't use any long/unopenable files here, so use the ANSI version.
|
||||
@@ -723,11 +733,11 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
if (num_failed >= 3) {
|
||||
debug_out_dump("app", "Stopping sequential scan.\n");
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
CloseHandle(h);
|
||||
#endif
|
||||
|
||||
debug_out_dump("app", "Successfully opened \"" << phys_name << "\".\n");
|
||||
|
||||
@@ -777,16 +787,17 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
if (!multiport_found) {
|
||||
debug_out_info("app", "Checking for additional 3ware devices...\n");
|
||||
std::string inst_path;
|
||||
#ifdef _WIN32
|
||||
hz::win32_get_registry_value_string(HKEY_USERS, ".DEFAULT\\Software\\3ware\\3DM2", "InstallPath", inst_path);
|
||||
|
||||
#endif
|
||||
if (!inst_path.empty()) {
|
||||
debug_out_dump("app", "3ware 3DM2 found at\"" << inst_path << "\".\n");
|
||||
std::vector<int> controllers;
|
||||
error_message = tw_cli_get_controllers(ex_factory, controllers);
|
||||
// ignore the error message above, it's of no use.
|
||||
for (std::size_t i = 0; i < controllers.size(); ++i) {
|
||||
for (int controller : controllers) {
|
||||
// don't specify device, it's ignored in tw_cli mode
|
||||
tw_cli_get_drives("", controllers.at(i), drives, ex_factory, true);
|
||||
tw_cli_get_drives("", controller, drives, ex_factory, true);
|
||||
}
|
||||
} else {
|
||||
debug_out_info("app", "3ware 3DM2 not installed.\n");
|
||||
@@ -807,6 +818,4 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
|
||||
|
||||
#endif // CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -12,10 +12,7 @@ Copyright:
|
||||
#ifndef STORAGE_DETECTOR_WIN32_H
|
||||
#define STORAGE_DETECTOR_WIN32_H
|
||||
|
||||
#include "build_config.h" // CONFIG_*
|
||||
|
||||
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -30,8 +27,6 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Com
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -12,20 +12,9 @@ Copyright:
|
||||
#ifndef BUILD_CONFIG_H
|
||||
#define BUILD_CONFIG_H
|
||||
|
||||
// NOTE: Parts of this file are replaced by cmake
|
||||
|
||||
// Parts of this file are replaced by cmake
|
||||
|
||||
#define PACKAGE_NAME "@CMAKE_PROJECT_NAME@"
|
||||
#define PACKAGE_VERSION "@CMAKE_PROJECT_VERSION@"
|
||||
|
||||
#define PACKAGE_PKGDATA_DIR "@CMAKE_INSTALL_FULL_DATADIR@"
|
||||
#define PACKAGE_SYSCONF_DIR "@CMAKE_INSTALL_FULL_SYSCONFDIR@"
|
||||
#define PACKAGE_LOCALE_DIR "@CMAKE_INSTALL_FULL_LOCALEDIR@"
|
||||
#define PACKAGE_DOC_DIR "@CMAKE_INSTALL_FULL_DOCDIR@"
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
#define PACKAGE_TOP_SOURCE_DIR "@CMAKE_SOURCE_DIR@"
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
|
||||
#cmakedefine CONFIG_KERNEL_WINDOWS32
|
||||
#cmakedefine CONFIG_KERNEL_WINDOWS64
|
||||
@@ -43,6 +32,161 @@ Copyright:
|
||||
#endif
|
||||
|
||||
|
||||
/// Build environment constexpr variables
|
||||
struct BuildEnv {
|
||||
|
||||
/// See if this is a debug build.
|
||||
static constexpr bool debug_build()
|
||||
{
|
||||
#ifdef DEBUG_BUILD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// CMake package name
|
||||
static constexpr const char* package_name() { return "@CMAKE_PROJECT_NAME@"; }
|
||||
|
||||
/// CMake package version
|
||||
static constexpr const char* package_version() { return "@CMAKE_PROJECT_VERSION@"; }
|
||||
|
||||
/// pkgdata directory - /usr/share
|
||||
static constexpr const char* package_pkgdata_dir() { return "@CMAKE_INSTALL_FULL_DATADIR@"; }
|
||||
|
||||
/// sysconf directory - /etc
|
||||
static constexpr const char* package_sysconf_dir() { return "@CMAKE_INSTALL_FULL_SYSCONFDIR@"; }
|
||||
|
||||
/// locale directory - /usr/share/locale
|
||||
static constexpr const char* package_locale_dir() { return "@CMAKE_INSTALL_FULL_LOCALEDIR@"; }
|
||||
|
||||
/// doc directory - /usr/share/doc/package_name
|
||||
static constexpr const char* package_doc_dir() { return "@CMAKE_INSTALL_FULL_DOCDIR@"; }
|
||||
|
||||
/// Top source directory. Available in debug build only.
|
||||
static constexpr const char* package_top_source_dir()
|
||||
{
|
||||
#ifdef DEBUG_BUILD
|
||||
// Hide it in ifdef so that the binary does not contain it unless required.
|
||||
return "@CMAKE_SOURCE_DIR@";
|
||||
#else
|
||||
throw std::logic_error("This function is unavailable in non-debug builds.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// Check if target kernel is 32-bit Windows
|
||||
static constexpr bool is_kernel_windows32()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_WINDOWS32
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is 64-bit Windows
|
||||
static constexpr bool is_kernel_windows64()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_WINDOWS64
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is Windows.
|
||||
/// Note: This slightly differs from _WIN32 - the macro indicates that win32 API is available.
|
||||
static constexpr bool is_kernel_family_windows()
|
||||
{
|
||||
return is_kernel_windows32() || is_kernel_windows64();
|
||||
}
|
||||
|
||||
|
||||
/// Check if target kernel is Linux.
|
||||
static constexpr bool is_kernel_linux()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_LINUX
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is FreeBSD.
|
||||
static constexpr bool is_kernel_freebsd()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_FREEBSD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is OpenBSD.
|
||||
static constexpr bool is_kernel_openbsd()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_OPENBSD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is NetBSD.
|
||||
static constexpr bool is_kernel_netbsd()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_NETBSD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is DragonflyBSD.
|
||||
static constexpr bool is_kernel_dragonfly()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_DRAGONFLY
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is Solaris.
|
||||
static constexpr bool is_kernel_solaris()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_SOLARIS
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is Darwin.
|
||||
static constexpr bool is_kernel_darwin()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_DARWIN
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Check if target kernel is QNX.
|
||||
static constexpr bool is_kernel_qnx()
|
||||
{
|
||||
#ifdef CONFIG_KERNEL_QNX
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ GscAboutDialog::GscAboutDialog(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builde
|
||||
|
||||
// Note: The dialogs have ESC accelerator attached by default.
|
||||
|
||||
set_version(PACKAGE_VERSION);
|
||||
set_version(BuildEnv::package_version());
|
||||
|
||||
// set these properties here (after setting hooks) to make the links work.
|
||||
set_website("https://gsmartcontrol.shaduri.dev/");
|
||||
|
||||
@@ -44,11 +44,11 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
|
||||
top_info_link_label->set_text(Glib::ustring::compose(top_info_link_label->get_text(), man_url));
|
||||
|
||||
Glib::ustring device_name_tooltip = _("Device name");
|
||||
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
device_name_tooltip = _("Device name (for example, use \"pd0\" for the first physical drive)");
|
||||
#elif defined CONFIG_KERNEL_LINUX
|
||||
device_name_tooltip = _("Device name (for example, /dev/sda or /dev/twa0)");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
device_name_tooltip = _("Device name (for example, use \"pd0\" for the first physical drive)");
|
||||
} else if constexpr(BuildEnv::is_kernel_linux()) {
|
||||
device_name_tooltip = _("Device name (for example, /dev/sda or /dev/twa0)");
|
||||
}
|
||||
if (auto* device_name_label = lookup_widget<Gtk::Label*>("device_name_label")) {
|
||||
app_gtkmm_set_widget_tooltip(*device_name_label, device_name_tooltip);
|
||||
}
|
||||
@@ -61,9 +61,9 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
|
||||
|
||||
|
||||
Glib::ustring device_type_tooltip = _("Smartctl -d option parameter");
|
||||
#if defined CONFIG_KERNEL_LINUX || defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
device_type_tooltip = _("Smartctl -d option parameter. For example, use areca,1 for the first drive behind Areca RAID controller.");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows() || BuildEnv::is_kernel_linux()) {
|
||||
device_type_tooltip = _("Smartctl -d option parameter. For example, use areca,1 for the first drive behind Areca RAID controller.");
|
||||
}
|
||||
if (auto* device_type_label = lookup_widget<Gtk::Label*>("device_type_label")) {
|
||||
app_gtkmm_set_widget_tooltip(*device_type_label, device_type_tooltip);
|
||||
}
|
||||
@@ -81,12 +81,12 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// "Browse" doesn't make sense in win32, hide it.
|
||||
if (device_name_browse_button) {
|
||||
device_name_browse_button->hide();
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// "Browse" doesn't make sense in win32, hide it.
|
||||
if (device_name_browse_button) {
|
||||
device_name_browse_button->hide();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Populate type combo with common types
|
||||
@@ -98,18 +98,18 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
|
||||
type_combo->append("usbsunplus");
|
||||
type_combo->append("ata");
|
||||
type_combo->append("scsi");
|
||||
#if defined CONFIG_KERNEL_LINUX
|
||||
type_combo->append("marvell");
|
||||
type_combo->append("megaraid,N");
|
||||
type_combo->append("areca,N");
|
||||
type_combo->append("areca,N/E");
|
||||
#endif
|
||||
#if defined CONFIG_KERNEL_LINUX || defined CONFIG_KERNEL_FREEBSD || defined CONFIG_KERNEL_DRAGONFLY
|
||||
type_combo->append("3ware,N"); // this option is not needed in windows
|
||||
type_combo->append("cciss,N");
|
||||
type_combo->append("hpt,L/M");
|
||||
type_combo->append("hpt,L/M/N");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_linux()) {
|
||||
type_combo->append("marvell");
|
||||
type_combo->append("megaraid,N");
|
||||
type_combo->append("areca,N");
|
||||
type_combo->append("areca,N/E");
|
||||
}
|
||||
if constexpr(BuildEnv::is_kernel_linux() || BuildEnv::is_kernel_freebsd() ||BuildEnv::is_kernel_dragonfly()) {
|
||||
type_combo->append("3ware,N"); // this option is not needed in windows
|
||||
type_combo->append("cciss,N");
|
||||
type_combo->append("hpt,L/M");
|
||||
type_combo->append("hpt,L/M/N");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -94,11 +94,11 @@ GscExecutorLogWindow::GscExecutorLogWindow(BaseObjectType* gtkcobj, Glib::RefPtr
|
||||
// Surprisingly, the treeview column text still works.
|
||||
|
||||
// The problem seems to have disappeared (new compiler/runtime?)
|
||||
// #ifdef _WIN32
|
||||
// if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// Gtk::Box* command_hbox = this->lookup_widget<Gtk::Box*>("command_hbox");
|
||||
// if (command_hbox)
|
||||
// command_hbox->hide();
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// ---------------
|
||||
|
||||
|
||||
+46
-51
@@ -39,12 +39,12 @@ Copyright:
|
||||
#include "hz/win32_tools.h" // win32_get_registry_value_string()
|
||||
#include "hz/env_tools.h"
|
||||
#include "hz/string_num.h"
|
||||
#include "build_config.h" // VERSION, *PACKAGE*, ...
|
||||
#include "build_config.h" // BuildEnv
|
||||
|
||||
#include "applib/window_instance_manager.h"
|
||||
#include "applib/gsc_settings.h"
|
||||
#include "gsc_main_window.h"
|
||||
#include "gsc_executor_log_window.h"
|
||||
#include "gsc_settings.h"
|
||||
#include "gsc_init.h"
|
||||
#include "gsc_startup_settings.h"
|
||||
|
||||
@@ -97,11 +97,11 @@ namespace {
|
||||
{
|
||||
// Default system-wide settings. This file is empty by default.
|
||||
hz::fs::path global_config_file;
|
||||
#ifdef _WIN32
|
||||
global_config_file = hz::fs::u8path("gsmartcontrol2.conf"); // CWD, installation dir by default.
|
||||
#else
|
||||
global_config_file = hz::fs::u8path(PACKAGE_SYSCONF_DIR) / "gsmartcontrol2.conf";
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
global_config_file = hz::fs::u8path("gsmartcontrol2.conf"); // CWD, installation dir by default.
|
||||
} else {
|
||||
global_config_file = hz::fs::u8path(BuildEnv::package_sysconf_dir()) / "gsmartcontrol2.conf";
|
||||
}
|
||||
|
||||
debug_out_dump("app", DBG_FUNC_MSG << "Global config file: \"" << global_config_file.u8string() << "\"\n");
|
||||
debug_out_dump("app",
|
||||
@@ -278,7 +278,7 @@ namespace {
|
||||
/// Print application version information
|
||||
inline void app_print_version_info()
|
||||
{
|
||||
std::string versiontext = "\n" + Glib::ustring::compose(_("GSmartControl version %1"), PACKAGE_VERSION) + "\n";
|
||||
std::string versiontext = "\n" + Glib::ustring::compose(_("GSmartControl version %1"), BuildEnv::package_version()) + "\n";
|
||||
|
||||
std::string warningtext = std::string("\n") + _("Warning: GSmartControl comes with ABSOLUTELY NO WARRANTY.\n"
|
||||
"See LICENSE.txt file for details.") + "\n\n";
|
||||
@@ -296,15 +296,15 @@ namespace {
|
||||
|
||||
bool app_init_and_loop(int& argc, char**& argv)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Disable client-side decorations (enable native windows decorations) under Windows.
|
||||
hz::env_set_value("GTK_CSD", "0");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// Disable client-side decorations (enable native windows decorations) under Windows.
|
||||
hz::env_set_value("GTK_CSD", "0");
|
||||
}
|
||||
|
||||
// Set up gettext. This has to be before gtk is initialized.
|
||||
bindtextdomain(PACKAGE_NAME, PACKAGE_LOCALE_DIR);
|
||||
bind_textdomain_codeset(PACKAGE_NAME, "UTF-8");
|
||||
textdomain(PACKAGE_NAME);
|
||||
bindtextdomain(BuildEnv::package_name(), BuildEnv::package_locale_dir());
|
||||
bind_textdomain_codeset(BuildEnv::package_name(), "UTF-8");
|
||||
textdomain(BuildEnv::package_name());
|
||||
|
||||
// Glib needs the C locale set to system locale for command line args.
|
||||
// We will reset it later if needed.
|
||||
@@ -382,14 +382,14 @@ bool app_init_and_loop(int& argc, char**& argv)
|
||||
|
||||
debug_out_dump("app", "LibDebug options:\n" << debug_get_cmd_args_dump());
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!std::isnan(args.arg_gdk_scale)) {
|
||||
hz::env_set_value("GDK_SCALE", hz::number_to_string_nolocale(args.arg_gdk_scale));
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) { // X11
|
||||
if (!std::isnan(args.arg_gdk_scale)) {
|
||||
hz::env_set_value("GDK_SCALE", hz::number_to_string_nolocale(args.arg_gdk_scale));
|
||||
}
|
||||
if (!std::isnan(args.arg_gdk_dpi_scale)) {
|
||||
hz::env_set_value("GDK_DPI_SCALE", hz::number_to_string_nolocale(args.arg_gdk_dpi_scale));
|
||||
}
|
||||
}
|
||||
if (!std::isnan(args.arg_gdk_dpi_scale)) {
|
||||
hz::env_set_value("GDK_DPI_SCALE", hz::number_to_string_nolocale(args.arg_gdk_dpi_scale));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Load config files
|
||||
@@ -453,31 +453,31 @@ bool app_init_and_loop(int& argc, char**& argv)
|
||||
|
||||
// Add data file search paths
|
||||
if (is_from_source) {
|
||||
#ifdef DEBUG_BUILD
|
||||
hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "data");
|
||||
hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "src/ui");
|
||||
hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_TOP_SOURCE_DIR) / "doc");
|
||||
#else
|
||||
// Assume the source is the parent directory (standard cmake build with the build directory as a subdirectory of source directory,
|
||||
// and the executables placed directly in the build directory).
|
||||
hz::data_file_add_search_directory("icons", application_dir.parent_path() / "data");
|
||||
hz::data_file_add_search_directory("ui", application_dir.parent_path() / "src/ui");
|
||||
hz::data_file_add_search_directory("doc", application_dir.parent_path() / "doc");
|
||||
#endif
|
||||
if constexpr(BuildEnv::debug_build()) {
|
||||
hz::data_file_add_search_directory("icons", hz::fs::u8path(BuildEnv::package_top_source_dir()) / "data");
|
||||
hz::data_file_add_search_directory("ui", hz::fs::u8path(BuildEnv::package_top_source_dir()) / "src/ui");
|
||||
hz::data_file_add_search_directory("doc", hz::fs::u8path(BuildEnv::package_top_source_dir()) / "doc");
|
||||
} else {
|
||||
// Assume the source is the parent directory (standard cmake build with the build directory as a subdirectory of source directory,
|
||||
// and the executables placed directly in the build directory).
|
||||
hz::data_file_add_search_directory("icons", application_dir.parent_path() / "data");
|
||||
hz::data_file_add_search_directory("ui", application_dir.parent_path() / "src/ui");
|
||||
hz::data_file_add_search_directory("doc", application_dir.parent_path() / "doc");
|
||||
}
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
hz::data_file_add_search_directory("icons", application_dir);
|
||||
hz::data_file_add_search_directory("ui", application_dir / "ui");
|
||||
hz::data_file_add_search_directory("doc", application_dir / "doc");
|
||||
#else
|
||||
hz::data_file_add_search_directory("icons", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "icons"); // /usr/share/program_name/icons
|
||||
hz::data_file_add_search_directory("ui", hz::fs::u8path(PACKAGE_PKGDATA_DIR) / "ui"); // /usr/share/program_name/ui
|
||||
hz::data_file_add_search_directory("doc", hz::fs::u8path(PACKAGE_DOC_DIR)); // /usr/share/doc/[packages/]gsmartcontrol
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
hz::data_file_add_search_directory("icons", application_dir);
|
||||
hz::data_file_add_search_directory("ui", application_dir / "ui");
|
||||
hz::data_file_add_search_directory("doc", application_dir / "doc");
|
||||
} else {
|
||||
hz::data_file_add_search_directory("icons", hz::fs::u8path(BuildEnv::package_pkgdata_dir()) / "icons"); // /usr/share/program_name/icons
|
||||
hz::data_file_add_search_directory("ui", hz::fs::u8path(BuildEnv::package_pkgdata_dir()) / "ui"); // /usr/share/program_name/ui
|
||||
hz::data_file_add_search_directory("doc", hz::fs::u8path(BuildEnv::package_doc_dir())); // /usr/share/doc/[packages/]gsmartcontrol
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Windows "Classic" theme is broken under GTK+3's "win32" theme.
|
||||
// Make sure we fall back to Adwaita (which works, but looks non-native)
|
||||
// for platforms which support "Classic" theme - Windows Server and Windows Vista / 7.
|
||||
@@ -487,20 +487,20 @@ bool app_init_and_loop(int& argc, char**& argv)
|
||||
if (gtk_settings) {
|
||||
Glib::ustring theme_name = gtk_settings->property_gtk_theme_name().get_value();
|
||||
debug_out_dump("app", "Current GTK theme: " << theme_name << "\n");
|
||||
#ifdef _WIN32
|
||||
if (IsWindowsServer() || !IsWindows8OrGreater()) {
|
||||
if (theme_name == "win32") {
|
||||
debug_out_dump("app", "Windows with Classic theme support detected, switching to Adwaita theme.\n");
|
||||
gtk_settings->property_gtk_theme_name().set_value("Adwaita");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set default icon for all windows.
|
||||
// Win32 version has its icon compiled-in, so no need to set it there.
|
||||
#ifndef _WIN32
|
||||
{
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
// we load it via icontheme to provide multi-size version.
|
||||
|
||||
// application-installed, /usr/share/icons/<theme_name>/apps/<size>
|
||||
@@ -516,7 +516,6 @@ bool app_init_and_loop(int& argc, char**& argv)
|
||||
Gtk::Window::set_default_icon_name("gtk-harddisk");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Export some command line arguments to rconfig
|
||||
@@ -574,11 +573,7 @@ void app_quit()
|
||||
debug_out_info("app", "Saving config before exit...\n");
|
||||
|
||||
// save the config
|
||||
#if defined ENABLE_GLIB && ENABLE_GLIB
|
||||
rconfig::autosave_force_now();
|
||||
#else
|
||||
rconfig::save_to_file(get_home_config_file());
|
||||
#endif
|
||||
|
||||
// exit the main loop
|
||||
debug_out_info("app", "Trying to exit the main loop...\n");
|
||||
|
||||
+11
-10
@@ -1090,9 +1090,9 @@ void GscMainWindow::run_update_drivedb()
|
||||
}
|
||||
std::string update_binary = Glib::shell_quote(update_binary_path.u8string());
|
||||
|
||||
#ifndef _WIN32
|
||||
update_binary = "xterm -hold -e " + update_binary;
|
||||
#endif
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) { // X11
|
||||
update_binary = "xterm -hold -e " + update_binary;
|
||||
}
|
||||
|
||||
try {
|
||||
Glib::spawn_command_line_async(update_binary);
|
||||
@@ -1106,14 +1106,15 @@ void GscMainWindow::run_update_drivedb()
|
||||
|
||||
bool GscMainWindow::add_device(const std::string& file, const std::string& type_arg, const std::string& extra_args)
|
||||
{
|
||||
#ifndef _WIN32 // win32 doesn't have device files, so skip the check
|
||||
std::error_code ec;
|
||||
if (!hz::fs::exists(hz::fs::u8path(file), ec)) {
|
||||
gui_show_error_dialog(_("Cannot add device"),
|
||||
(ec.message().empty() ? Glib::ustring::compose(_("Device \"%1\" doesn't exist."), file).raw() : ec.message()), this);
|
||||
return false;
|
||||
// win32 doesn't have device files, so skip the check in Windows.
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) {
|
||||
std::error_code ec;
|
||||
if (!hz::fs::exists(hz::fs::u8path(file), ec)) {
|
||||
gui_show_error_dialog(_("Cannot add device"),
|
||||
(ec.message().empty() ? Glib::ustring::compose(_("Device \"%1\" doesn't exist."), file).raw() : ec.message()), this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto drive = std::make_shared<StorageDevice>(file);
|
||||
drive->set_type_argument(type_arg);
|
||||
|
||||
@@ -27,6 +27,7 @@ Copyright:
|
||||
|
||||
#include "gsc_main_window.h"
|
||||
#include "rconfig/rconfig.h"
|
||||
#include "build_config.h"
|
||||
|
||||
|
||||
|
||||
@@ -294,11 +295,11 @@ class GscMainWindowIconView : public Gtk::IconView {
|
||||
if (rconfig::get_data<bool>("gui/icons_show_device_name")) {
|
||||
if (!drive->get_is_virtual()) {
|
||||
std::string dev = Glib::Markup::escape_text(drive->get_device_with_type());
|
||||
#ifndef _WIN32
|
||||
name += "\n" + dev;
|
||||
#else
|
||||
name += "\n" + Glib::ustring::compose(_("%1 (%2)"), dev, drive_letters);
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
name += "\n" + Glib::ustring::compose(_("%1 (%2)"), dev, drive_letters);
|
||||
} else {
|
||||
name += "\n" + dev;
|
||||
}
|
||||
} else if (!drive->get_virtual_filename().empty()) {
|
||||
name += "\n" + Glib::Markup::escape_text(drive->get_virtual_filename());
|
||||
}
|
||||
@@ -326,9 +327,9 @@ class GscMainWindowIconView : public Gtk::IconView {
|
||||
tooltip_strs.push_back(Glib::ustring::compose(_("Device: %1"), "<b>" + Glib::Markup::escape_text(drive->get_device_with_type()) + "</b>"));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
tooltip_strs.push_back(Glib::ustring::compose(_("Drive letters: %1"), "<b>" + drive_letters_with_volname + "</b>"));
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
tooltip_strs.push_back(Glib::ustring::compose(_("Drive letters: %1"), "<b>" + drive_letters_with_volname + "</b>"));
|
||||
}
|
||||
|
||||
if (!drive->get_serial_number().empty()) {
|
||||
tooltip_strs.push_back(Glib::ustring::compose(_("Serial number: %1"), "<b>" + Glib::Markup::escape_text(drive->get_serial_number()) + "</b>"));
|
||||
|
||||
@@ -235,9 +235,9 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, Glib::RefPtr
|
||||
|
||||
|
||||
Glib::ustring smartctl_binary_tooltip = _("A path to smartctl binary. If the path is not absolute, the binary will be looked for in user's PATH.");
|
||||
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
smartctl_binary_tooltip += Glib::ustring("\n") + _("Note: smartctl.exe shows a console during execution, while smartctl-nc.exe (default) doesn't (nc means no-console).");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
smartctl_binary_tooltip += Glib::ustring("\n") + _("Note: smartctl.exe shows a console during execution, while smartctl-nc.exe (default) doesn't (nc means no-console).");
|
||||
}
|
||||
if (auto* smartctl_binary_label = lookup_widget<Gtk::Label*>("smartctl_binary_label")) {
|
||||
app_gtkmm_set_widget_tooltip(*smartctl_binary_label, smartctl_binary_tooltip);
|
||||
}
|
||||
@@ -260,11 +260,11 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, Glib::RefPtr
|
||||
APP_BUILDER_AUTO_CONNECT(device_options_device_entry, changed);
|
||||
|
||||
Glib::ustring device_options_tooltip = _("A device name to match");
|
||||
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
device_options_tooltip = _("A device name to match (for example, use \"pd0\" for the first physical drive)");
|
||||
#elif defined CONFIG_KERNEL_LINUX
|
||||
device_options_tooltip = _("A device name to match (for example, /dev/sda or /dev/twa0)");
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
device_options_tooltip = _("A device name to match (for example, use \"pd0\" for the first physical drive)");
|
||||
} else if constexpr(BuildEnv::is_kernel_linux()) {
|
||||
device_options_tooltip = _("A device name to match (for example, /dev/sda or /dev/twa0)");
|
||||
}
|
||||
if (auto* device_options_device_label = lookup_widget<Gtk::Label*>("device_options_device_label")) {
|
||||
app_gtkmm_set_widget_tooltip(*device_options_device_label, device_options_tooltip);
|
||||
}
|
||||
@@ -298,11 +298,11 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, Glib::RefPtr
|
||||
this->device_widget_set_remove_possible(false); // initial state
|
||||
|
||||
// hide win32-only options for non-win32.
|
||||
#ifndef _WIN32
|
||||
if (auto* smartctl_search_check = this->lookup_widget<Gtk::CheckButton*>("search_in_smartmontools_first_check"))
|
||||
smartctl_search_check->hide();
|
||||
#endif
|
||||
|
||||
if constexpr(!BuildEnv::is_kernel_family_windows()) {
|
||||
if (auto* smartctl_search_check = this->lookup_widget<Gtk::CheckButton*>("search_in_smartmontools_first_check")) {
|
||||
smartctl_search_check->hide();
|
||||
}
|
||||
}
|
||||
|
||||
import_config();
|
||||
|
||||
@@ -519,15 +519,16 @@ void GscPreferencesWindow::on_smartctl_binary_browse_button_clicked()
|
||||
|
||||
int result = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
|
||||
specific_filter->set_name(_("Executable Files"));
|
||||
specific_filter->add_pattern("*.exe");
|
||||
Glib::RefPtr<Gtk::FileFilter> specific_filter, all_filter;
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
specific_filter = Gtk::FileFilter::create();
|
||||
specific_filter->set_name(_("Executable Files"));
|
||||
specific_filter->add_pattern("*.exe");
|
||||
|
||||
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
|
||||
all_filter->set_name(_("All Files"));
|
||||
all_filter->add_pattern("*");
|
||||
#endif
|
||||
all_filter = Gtk::FileFilter::create();
|
||||
all_filter->set_name(_("All Files"));
|
||||
all_filter->add_pattern("*");
|
||||
}
|
||||
|
||||
#if GTK_CHECK_VERSION(3, 20, 0)
|
||||
std::unique_ptr<GtkFileChooserNative, decltype(&g_object_unref)> dialog(gtk_file_chooser_native_new(
|
||||
@@ -537,10 +538,10 @@ void GscPreferencesWindow::on_smartctl_binary_browse_button_clicked()
|
||||
if (path.is_absolute())
|
||||
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog.get()), path.u8string().c_str());
|
||||
|
||||
#ifdef _WIN32
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), specific_filter->gobj());
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), all_filter->gobj());
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), specific_filter->gobj());
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), all_filter->gobj());
|
||||
}
|
||||
|
||||
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
|
||||
|
||||
@@ -552,10 +553,10 @@ void GscPreferencesWindow::on_smartctl_binary_browse_button_clicked()
|
||||
dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||
dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
|
||||
|
||||
#ifdef _WIN32
|
||||
dialog.add_filter(specific_filter);
|
||||
dialog.add_filter(all_filter);
|
||||
#endif
|
||||
if constexpr(BuildEnv::is_kernel_family_windows()) {
|
||||
dialog.add_filter(specific_filter);
|
||||
dialog.add_filter(all_filter);
|
||||
}
|
||||
|
||||
// Note: This works on absolute paths only (otherwise it's gtk warning).
|
||||
if (path.is_absolute())
|
||||
|
||||
Reference in New Issue
Block a user