diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index d570e54..7e17ff4 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cad1a81..e82bbb5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/applib/CMakeLists.txt b/src/applib/CMakeLists.txt index 7623335..11d332b 100644 --- a/src/applib/CMakeLists.txt +++ b/src/applib/CMakeLists.txt @@ -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 ) diff --git a/src/applib/app_gtkmm_tools.cpp b/src/applib/app_gtkmm_tools.cpp index b586599..e316b25 100644 --- a/src/applib/app_gtkmm_tools.cpp +++ b/src/applib/app_gtkmm_tools.cpp @@ -16,7 +16,7 @@ Copyright: #include #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())); } diff --git a/src/applib/async_command_executor.cpp b/src/applib/async_command_executor.cpp index c4062b4..90c3506 100644 --- a/src/applib/async_command_executor.cpp +++ b/src/applib/async_command_executor.cpp @@ -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 child_env(g_get_environ(), &g_strfreev); if (change_lang) { diff --git a/src/applib/examples/example_storage_detector.cpp b/src/applib/examples/example_storage_detector.cpp index f4fe25e..bfb5769 100644 --- a/src/applib/examples/example_storage_detector.cpp +++ b/src/applib/examples/example_storage_detector.cpp @@ -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 diff --git a/src/gsc_settings.h b/src/applib/gsc_settings.h similarity index 88% rename from src/gsc_settings.h rename to src/applib/gsc_settings.h index e65853c..d6f35e8 100644 --- a/src/gsc_settings.h +++ b/src/applib/gsc_settings.h @@ -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 diff --git a/src/applib/smartctl_ata_text_parser.cpp b/src/applib/smartctl_ata_text_parser.cpp index a2cb736..37dca04 100644 --- a/src/applib/smartctl_ata_text_parser.cpp +++ b/src/applib/smartctl_ata_text_parser.cpp @@ -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(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, ""); diff --git a/src/applib/smartctl_executor.cpp b/src/applib/smartctl_executor.cpp index a755003..4c909ce 100644 --- a/src/applib/smartctl_executor.cpp +++ b/src/applib/smartctl_executor.cpp @@ -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("system/smartctl_binary")); -#ifdef _WIN32 - // Look in smartmontools installation directory. - hz::fs::path system_binary; - do { - bool use_smt = rconfig::get_data("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("system/win32_search_smartctl_in_smartmontools"); + if (!use_smt) + break; - auto smt_regpath = rconfig::get_data("system/win32_smartmontools_regpath"); - auto smt_regpath_wow = rconfig::get_data("system/win32_smartmontools_regpath_wow"); // same as above, but with WOW6432Node - auto smt_regkey = rconfig::get_data("system/win32_smartmontools_regkey"); - auto smt_smartctl = rconfig::get_data("system/win32_smartmontools_smartctl_binary"); + auto smt_regpath = rconfig::get_data("system/win32_smartmontools_regpath"); + auto smt_regpath_wow = rconfig::get_data("system/win32_smartmontools_regpath_wow"); // same as above, but with WOW6432Node + auto smt_regkey = rconfig::get_data("system/win32_smartmontools_regkey"); + auto smt_smartctl = rconfig::get_data("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 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(); diff --git a/src/applib/storage_detector.cpp b/src/applib/storage_detector.cpp index da89c34..083fe31 100644 --- a/src/applib/storage_detector.cpp +++ b/src/applib/storage_detector.cpp @@ -13,7 +13,7 @@ Copyright: #include // compose() #include -#include "build_config.h" // CONFIG_* +#include "build_config.h" #include "hz/debug.h" @@ -37,19 +37,15 @@ std::string StorageDetector::detect(std::vector& 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"); diff --git a/src/applib/storage_detector_helpers.h b/src/applib/storage_detector_helpers.h index 7aab8cb..ac40d2d 100644 --- a/src/applib/storage_detector_helpers.h +++ b/src/applib/storage_detector_helpers.h @@ -42,11 +42,11 @@ inline std::string execute_tw_cli(const CommandExecutorFactoryPtr& ex_factory, c std::vector 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); diff --git a/src/applib/storage_detector_linux.cpp b/src/applib/storage_detector_linux.cpp index dfab28d..b3a3422 100644 --- a/src/applib/storage_detector_linux.cpp +++ b/src/applib/storage_detector_linux.cpp @@ -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 // std::find #include // std::fgets(), std::FILE -#include // ENXIO +// #include // ENXIO #include #include #include @@ -1108,6 +1106,4 @@ std::string detect_drives_linux(std::vector& drives, const Com -#endif // CONFIG_KERNEL_LINUX - /// @} diff --git a/src/applib/storage_detector_linux.h b/src/applib/storage_detector_linux.h index f0882e0..0f148a9 100644 --- a/src/applib/storage_detector_linux.h +++ b/src/applib/storage_detector_linux.h @@ -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 @@ -30,8 +28,6 @@ std::string detect_drives_linux(std::vector& drives, const Com -#endif - #endif diff --git a/src/applib/storage_detector_other.cpp b/src/applib/storage_detector_other.cpp index f79ff2a..674935a 100644 --- a/src/applib/storage_detector_other.cpp +++ b/src/applib/storage_detector_other.cpp @@ -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 // std::sort +#include #if defined CONFIG_KERNEL_OPENBSD || defined CONFIG_KERNEL_NETBSD #include // getrawpartition() @@ -37,11 +36,11 @@ std::string detect_drives_other(std::vector& drives, std::vector 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(sdev_config_path); @@ -57,130 +56,125 @@ std::string detect_drives_other(std::vector& 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 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 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 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 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 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 whitelist = { - "/^hd[0-9]+$/", - }; - -#else // unsupported OS - - static const std::vector whitelist; - -#endif // unix platforms + } // unix platforms std::vector matched_devices; @@ -212,8 +206,8 @@ std::string detect_drives_other(std::vector& 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& 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(device)); } - return std::string(); + return {}; } -#endif // !defined CONFIG_KERNEL_LINUX && !defined CONFIG_KERNEL_FAMILY_WINDOWS - /// @} diff --git a/src/applib/storage_detector_other.h b/src/applib/storage_detector_other.h index 2510d2a..fc41ff2 100644 --- a/src/applib/storage_detector_other.h +++ b/src/applib/storage_detector_other.h @@ -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 #include @@ -30,8 +27,6 @@ std::string detect_drives_other(std::vector& drives, const Com -#endif - #endif /// @} diff --git a/src/applib/storage_detector_win32.cpp b/src/applib/storage_detector_win32.cpp index 333a572..c18eb9d 100644 --- a/src/applib/storage_detector_win32.cpp +++ b/src/applib/storage_detector_win32.cpp @@ -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 // CreateFileA(), CloseHandle(), etc... #include #include #include #include #include +#ifdef _WIN32 + #include // CreateFileA(), CloseHandle(), etc... +#endif + #include "hz/win32_tools.h" #include "hz/string_sprintf.h" #include "hz/fs.h" @@ -105,6 +106,7 @@ std::map win32_get_drive_letter_map() { std::map drive_letter_map; +#ifdef _WIN32 std::bitset<32> drives(GetLogicalDrives()); // Check which drives are fixed @@ -160,7 +162,7 @@ std::map 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& drive return _("Smartctl binary is not specified in configuration."); } - std::string smartctl_def_options = rconfig::get_data("system/smartctl_options"); + auto smartctl_def_options = rconfig::get_data("system/smartctl_options"); if (!smartctl_def_options.empty()) smartctl_def_options += " "; @@ -224,9 +226,9 @@ std::string get_scan_open_multiport_devices(std::vector& 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& 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(port_str); int enclosure = hz::string_to_number_nolocale(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(port_str); drives.emplace_back(std::make_shared(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& driv int scan_controllers = rconfig::get_data("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& driv int use_cli = rconfig::get_data("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& 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("/dev/arcmsr0", "areca,1"); @@ -571,7 +578,7 @@ inline std::string detect_drives_win32_areca(std::vector& 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& 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& 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& drives, const Com // Find out their serial numbers and whether there are Arecas there. std::map 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& 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& 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& 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& 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 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& drives, const Com -#endif // CONFIG_KERNEL_FAMILY_WINDOWS - /// @} diff --git a/src/applib/storage_detector_win32.h b/src/applib/storage_detector_win32.h index dbe8984..f5ded86 100644 --- a/src/applib/storage_detector_win32.h +++ b/src/applib/storage_detector_win32.h @@ -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 #include @@ -30,8 +27,6 @@ std::string detect_drives_win32(std::vector& drives, const Com -#endif - #endif /// @} diff --git a/src/build_config/build_config.in.h b/src/build_config/build_config.in.h index 344ecdf..f68337b 100644 --- a/src/build_config/build_config.in.h +++ b/src/build_config/build_config.in.h @@ -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 #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 diff --git a/src/gsc_about_dialog.cpp b/src/gsc_about_dialog.cpp index f577728..f50c877 100644 --- a/src/gsc_about_dialog.cpp +++ b/src/gsc_about_dialog.cpp @@ -30,7 +30,7 @@ GscAboutDialog::GscAboutDialog(BaseObjectType* gtkcobj, Glib::RefPtrset_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("device_name_label")) { app_gtkmm_set_widget_tooltip(*device_name_label, device_name_tooltip); } @@ -61,9 +61,9 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr("device_type_label")) { app_gtkmm_set_widget_tooltip(*device_type_label, device_type_tooltip); } @@ -81,12 +81,12 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtrhide(); + 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::RefPtrappend("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"); + } } diff --git a/src/gsc_executor_log_window.cpp b/src/gsc_executor_log_window.cpp index cc054ce..162ae04 100644 --- a/src/gsc_executor_log_window.cpp +++ b/src/gsc_executor_log_window.cpp @@ -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("command_hbox"); // if (command_hbox) // command_hbox->hide(); -// #endif +// } // --------------- diff --git a/src/gsc_init.cpp b/src/gsc_init.cpp index f75f025..08967d9 100644 --- a/src/gsc_init.cpp +++ b/src/gsc_init.cpp @@ -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//apps/ @@ -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"); diff --git a/src/gsc_main_window.cpp b/src/gsc_main_window.cpp index 06e89d2..67c7ef9 100644 --- a/src/gsc_main_window.cpp +++ b/src/gsc_main_window.cpp @@ -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(file); drive->set_type_argument(type_arg); diff --git a/src/gsc_main_window_iconview.h b/src/gsc_main_window_iconview.h index 63d208d..e895e43 100644 --- a/src/gsc_main_window_iconview.h +++ b/src/gsc_main_window_iconview.h @@ -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("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"), "" + Glib::Markup::escape_text(drive->get_device_with_type()) + "")); } - #ifdef _WIN32 - tooltip_strs.push_back(Glib::ustring::compose(_("Drive letters: %1"), "" + drive_letters_with_volname + "")); - #endif + if constexpr(BuildEnv::is_kernel_family_windows()) { + tooltip_strs.push_back(Glib::ustring::compose(_("Drive letters: %1"), "" + drive_letters_with_volname + "")); + } if (!drive->get_serial_number().empty()) { tooltip_strs.push_back(Glib::ustring::compose(_("Serial number: %1"), "" + Glib::Markup::escape_text(drive->get_serial_number()) + "")); diff --git a/src/gsc_preferences_window.cpp b/src/gsc_preferences_window.cpp index f7edd4f..8608670 100644 --- a/src/gsc_preferences_window.cpp +++ b/src/gsc_preferences_window.cpp @@ -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("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("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("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("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 specific_filter = Gtk::FileFilter::create(); - specific_filter->set_name(_("Executable Files")); - specific_filter->add_pattern("*.exe"); + Glib::RefPtr 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 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 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())