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:
Alexander Shaduri
2022-01-18 15:30:55 +04:00
parent 235fba8a04
commit 88e9e8c2f7
25 changed files with 542 additions and 416 deletions
+4 -2
View File
@@ -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
-1
View File
@@ -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
+1 -1
View File
@@ -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
)
+7 -7
View File
@@ -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()));
}
+3 -2
View File
@@ -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
+14 -13
View File
@@ -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, "");
+43 -40
View File
@@ -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>();
+8 -12
View File
@@ -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");
+5 -5
View File
@@ -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);
+2 -6
View File
@@ -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
/// @}
+1 -5
View File
@@ -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
+110 -119
View File
@@ -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
/// @}
+1 -6
View File
@@ -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
/// @}
+49 -40
View File
@@ -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
/// @}
+1 -6
View File
@@ -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
/// @}
+157 -13
View File
@@ -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
+1 -1
View File
@@ -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/");
+25 -25
View File
@@ -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");
}
}
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+9 -8
View File
@@ -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>"));
+30 -29
View File
@@ -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())