mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-25 05:15:33 +00:00
Added support for specifying -d option and extra parameters via command line
and preferences dialog. StorageDevice will use the specified type and arguments when executing smartctl. This change effectively adds support for multiple drives behind a single device name. The preferences dialog can distinguish between various device types now (when supplying smartctl arguments).
This commit is contained in:
@@ -30,31 +30,12 @@ std::string StorageDevice::get_type_readable_name(StorageDevice::detected_type_t
|
||||
return "invalid";
|
||||
case detected_type_cddvd:
|
||||
return "cd/dvd";
|
||||
case detected_type_scsi:
|
||||
return "scsi";
|
||||
}
|
||||
return "[internal_error]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::get_type_arg_name(StorageDevice::detected_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case detected_type_unknown:
|
||||
return "";
|
||||
case detected_type_invalid:
|
||||
return "";
|
||||
case detected_type_cddvd:
|
||||
return "";
|
||||
case detected_type_scsi:
|
||||
return "scsi";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::get_status_name(StorageDevice::status_t status, bool use_yesno)
|
||||
{
|
||||
switch (status) {
|
||||
@@ -169,9 +150,9 @@ std::string StorageDevice::fetch_basic_data_and_parse(hz::intrusive_ptr<CmdexSyn
|
||||
// This means that the old SCSI identify command isn't executed by default,
|
||||
// and there is no information about the device manufacturer/etc... in the output.
|
||||
// We detect this and set the device type to scsi to at least have _some_ info.
|
||||
if (get_detected_type() == detected_type_invalid) {
|
||||
if (get_detected_type() == detected_type_invalid && get_type_argument().empty()) {
|
||||
debug_out_info("app", "The device seems to be of different type than auto-detected, trying again with scsi.\n");
|
||||
this->set_detected_type(detected_type_scsi);
|
||||
this->set_type_argument("scsi");
|
||||
return this->fetch_basic_data_and_parse(smartctl_ex); // try again with scsi
|
||||
}
|
||||
|
||||
@@ -288,7 +269,7 @@ std::string StorageDevice::fetch_data_and_parse(hz::intrusive_ptr<CmdexSync> sma
|
||||
|
||||
// instead of -a, we use all the individual options -a encompasses, so that
|
||||
// an addition to default -a output won't affect us.
|
||||
if (this->get_detected_type() == detected_type_scsi) {
|
||||
if (this->get_type_argument() == "scsi") { // not sure about correctness... FIXME probably fails with RAID/scsi
|
||||
// This doesn't do much yet, but just in case...
|
||||
// SCSI equivalent of -a:
|
||||
error_msg = execute_smartctl("-H -i -A -l error -l selftest", smartctl_ex, output);
|
||||
@@ -298,9 +279,9 @@ std::string StorageDevice::fetch_data_and_parse(hz::intrusive_ptr<CmdexSync> sma
|
||||
smartctl_ex, output, true); // set type to invalid if needed
|
||||
}
|
||||
// See notes above (in fetch_basic_data_and_parse()).
|
||||
if (get_detected_type() == detected_type_invalid) {
|
||||
if (get_detected_type() == detected_type_invalid && get_type_argument().empty()) {
|
||||
debug_out_info("app", "The device seems to be of different type than auto-detected, trying again with scsi.\n");
|
||||
this->set_detected_type(detected_type_scsi);
|
||||
this->set_type_argument("scsi");
|
||||
return this->fetch_data_and_parse(smartctl_ex); // try again with scsi
|
||||
}
|
||||
|
||||
@@ -603,7 +584,7 @@ std::string StorageDevice::get_type_argument() const
|
||||
|
||||
|
||||
|
||||
void StorageDevice::set_extra_argument(const string& args)
|
||||
void StorageDevice::set_extra_arguments(const string& args)
|
||||
{
|
||||
extra_args_ = args;
|
||||
}
|
||||
@@ -766,20 +747,26 @@ std::string StorageDevice::get_device_options() const
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string config_options = app_get_device_option(get_device());
|
||||
// If we have some special type or option, specify it on the command line (like "-d scsi").
|
||||
// Note that the latter "-d" option overrides the former.
|
||||
|
||||
// If we have some special type, specify it on the command line (like "-d scsi").
|
||||
// Note that the latter "-d" option overrides the former, so we're ok with multiple ones.
|
||||
std::string type_arg = get_type_arg_name(this->get_detected_type());
|
||||
|
||||
if (!type_arg.empty()) {
|
||||
if (!config_options.empty()) {
|
||||
config_options += " ";
|
||||
}
|
||||
config_options += "-d " + type_arg;
|
||||
// lowest priority - the detected type
|
||||
std::vector<std::string> args;
|
||||
if (!get_type_argument().empty()) {
|
||||
args.push_back("-d " + get_type_argument());
|
||||
}
|
||||
// extra args, as specified manually in CLI or when adding the drive
|
||||
if (!get_extra_arguments().empty()) {
|
||||
args.push_back(get_extra_arguments());
|
||||
}
|
||||
|
||||
return config_options;
|
||||
// config options, as specified in preferences.
|
||||
std::string config_options = app_get_device_option(get_device(), get_type_argument());
|
||||
if (!config_options.empty()) {
|
||||
args.push_back(config_options);
|
||||
}
|
||||
|
||||
return hz::string_join(args, " ");
|
||||
}
|
||||
|
||||
|
||||
@@ -846,7 +833,7 @@ std::string StorageDevice::execute_smartctl(const std::string& command_options,
|
||||
// This means that the old SCSI identify command isn't executed by default,
|
||||
// and there is no information about the device manufacturer/etc... in the output.
|
||||
// We detect this and set the device type to scsi to at least have _some_ info.
|
||||
if (check_type && this->get_detected_type() == detected_type_unknown // && this->get_type() == ""
|
||||
if (check_type && this->get_detected_type() == detected_type_unknown
|
||||
&& app_pcre_match("/specify device type with the -d option/mi", output)) {
|
||||
this->set_detected_type(detected_type_invalid);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
detected_type_unknown, // unknown. will be autodetected by smartctl
|
||||
detected_type_invalid, // this is set by smartctl executor if it detects invalid type (but not if it's scsi).
|
||||
detected_type_cddvd, // unsupported by smartctl, only basic info is given.
|
||||
detected_type_scsi // this is used to force "-d scsi" to execute IDENTIFY command.
|
||||
};
|
||||
|
||||
|
||||
@@ -41,10 +40,6 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
static std::string get_type_readable_name(detected_type_t type);
|
||||
|
||||
|
||||
/// This gives a string which, if not empty, can be given as a parameter of "-d".
|
||||
static std::string get_type_arg_name(detected_type_t type);
|
||||
|
||||
|
||||
/// Statuses of various states
|
||||
enum status_t {
|
||||
status_enabled, ///< SMART, AODC
|
||||
@@ -138,7 +133,7 @@ class StorageDevice : public hz::intrusive_ptr_referenced {
|
||||
|
||||
|
||||
/// Set extra arguments smartctl
|
||||
void set_extra_argument(const std::string& args);
|
||||
void set_extra_arguments(const std::string& args);
|
||||
|
||||
/// Get extra arguments smartctl
|
||||
std::string get_extra_arguments() const;
|
||||
|
||||
@@ -68,7 +68,7 @@ inline std::string app_serialize_device_option_map(const device_option_map_t& op
|
||||
|
||||
|
||||
|
||||
inline std::string app_get_device_option(const std::string& dev)
|
||||
inline std::string app_get_device_option(const std::string& dev, const std::string& type_arg)
|
||||
{
|
||||
if (dev.empty())
|
||||
return std::string();
|
||||
@@ -79,11 +79,27 @@ inline std::string app_get_device_option(const std::string& dev)
|
||||
|
||||
device_option_map_t devmap = app_unserialize_device_option_map(devmap_str);
|
||||
|
||||
device_option_map_t::const_iterator iter = devmap.find(dev);
|
||||
if (iter == devmap.end())
|
||||
return std::string();
|
||||
// try the concrete type first
|
||||
if (!type_arg.empty()) {
|
||||
device_option_map_t::const_iterator iter = devmap.find(dev + "::" + type_arg);
|
||||
if (iter != devmap.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
// in case there's a trailing delimiter
|
||||
device_option_map_t::const_iterator iter = devmap.find(dev + "::" + type_arg);
|
||||
if (iter != devmap.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
// just the device name
|
||||
iter = devmap.find(dev);
|
||||
if (iter != devmap.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -207,12 +207,20 @@ inline bool parse_cmdline_args(CmdArgs& args, int& argc, char**& argv)
|
||||
{
|
||||
static const GOptionEntry arg_entries[] =
|
||||
{
|
||||
{ "no-locale", 'l', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_locale), "Don't use system locale", NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &(args.arg_version), "Display version information", NULL },
|
||||
{ "no-scan", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_scan), "Don't scan devices on startup", NULL },
|
||||
{ "no-hide-tabs", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_hide_tabs), "Don't hide non-identity tabs when SMART is disabled. Useful for debugging.", NULL },
|
||||
{ "add-virtual", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_virtual), "Load smartctl data from file, creating a virtual drive", NULL },
|
||||
{ "add-device", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_device), "Add this device to device list. Useful with --no-scan to list certain drives only.", NULL },
|
||||
{ "no-locale", 'l', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_locale),
|
||||
"Don't use system locale", NULL },
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &(args.arg_version),
|
||||
"Display version information", NULL },
|
||||
{ "no-scan", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_scan),
|
||||
"Don't scan devices on startup", NULL },
|
||||
{ "no-hide-tabs", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_hide_tabs),
|
||||
"Don't hide non-identity tabs when SMART is disabled. Useful for debugging.", NULL },
|
||||
{ "add-virtual", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_virtual),
|
||||
"Load smartctl data from file, creating a virtual drive. You can specify this option multiple times.", NULL },
|
||||
{ "add-device", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_device),
|
||||
"Add this device to device list. The format of the device is \"<device>::<type>::<extra_args>\", where type and extra_args are optional."
|
||||
" This option is useful with --no-scan to list certain drives only. You can specify this option multiple times."
|
||||
"Example: --add-device /dev/sda --add-device /dev/twa0::3ware,2 --add-device '/dev/sdb::::-T permissive'", NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -319,7 +327,7 @@ bool app_init_and_loop(int& argc, char**& argv)
|
||||
load_devices.push_back(entry);
|
||||
}
|
||||
}
|
||||
std::string load_devices_str = hz::string_join(load_devices, ", "); // for display purposes only
|
||||
std::string load_devices_str = hz::string_join(load_devices, "; "); // for display purposes only
|
||||
|
||||
|
||||
// it's here because earlier there are no domains
|
||||
|
||||
@@ -145,7 +145,14 @@ void GscMainWindow::populate_iconview(bool smartctl_valid)
|
||||
if (rconfig::get_data("/runtime/gui/add_devices_on_startup", load_devices)) {
|
||||
for (unsigned int i = 0; i < load_devices.size(); ++i) {
|
||||
if (!load_devices[i].empty()) {
|
||||
add_device(load_devices[i]);
|
||||
std::vector<std::string> parts;
|
||||
hz::string_split(load_devices[i], "::", parts, false);
|
||||
std::string file = (parts.size() > 0 ? parts.at(0) : "");
|
||||
std::string type_arg = (parts.size() > 1 ? parts.at(1) : "");
|
||||
std::string extra_args = (parts.size() > 2 ? parts.at(2) : "");
|
||||
if (!file.empty()) {
|
||||
add_device(file, type_arg, extra_args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1027,7 +1034,7 @@ void GscMainWindow::rescan_devices()
|
||||
|
||||
|
||||
|
||||
bool GscMainWindow::add_device(const std::string& file)
|
||||
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
|
||||
hz::File f(file);
|
||||
@@ -1040,6 +1047,8 @@ bool GscMainWindow::add_device(const std::string& file)
|
||||
#endif
|
||||
|
||||
StorageDeviceRefPtr d(new StorageDevice(file));
|
||||
d->set_type_argument(type_arg);
|
||||
d->set_extra_arguments(extra_args);
|
||||
d->set_is_manually_added(true);
|
||||
|
||||
SmartctlExecutorGuiRefPtr ex(new SmartctlExecutorGui());
|
||||
@@ -1199,7 +1208,10 @@ void GscMainWindow::show_add_device_chooser()
|
||||
"For example, pd0 means the first physical drive",
|
||||
dev, last_str, this, false)) {
|
||||
last_str = dev; // safe for the future
|
||||
this->add_device(dev); // both the GUI and the API is in utf-8, no conversion is necessary.
|
||||
std::string type_arg = ""; /// TODO
|
||||
std::string extra_args = ""; /// TODO
|
||||
// both the GUI and the API is in utf-8, no conversion is necessary.
|
||||
this->add_device(dev, type_arg, extra_args);
|
||||
}
|
||||
|
||||
|
||||
@@ -1231,7 +1243,9 @@ void GscMainWindow::show_add_device_chooser()
|
||||
last_dir = dialog.get_current_folder(); // safe for the future
|
||||
|
||||
std::string file = dialog.get_filename(); // in fs encoding
|
||||
this->add_device(file);
|
||||
std::string type_arg = ""; /// TODO
|
||||
std::string extra_args = ""; /// TODO
|
||||
this->add_device(file, type_arg, extra_args);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class GscMainWindow : public AppUIResWidget<GscMainWindow, false> {
|
||||
|
||||
|
||||
// manually add device file to icon list
|
||||
bool add_device(const std::string& file);
|
||||
bool add_device(const std::string& file, const std::string& type_arg, const std::string& extra_args);
|
||||
|
||||
|
||||
// read smartctl data from file, add it as a virtual drive to icon list
|
||||
|
||||
@@ -210,7 +210,9 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, const app_ui
|
||||
|
||||
Gtk::Entry* device_options_device_entry = 0;
|
||||
APP_UI_RES_AUTO_CONNECT(device_options_device_entry, changed);
|
||||
Glib::ustring device_options_tooltip = "Device name (for example, %s)";
|
||||
Glib::ustring device_options_tooltip = "Format: <device name>::<type>, where \"::<type>\" part is optional. "
|
||||
" An example of device name would be %s. Type is an argument of smartctl -d option and can be "
|
||||
" used to specify a drive behind a RAID device, e.g. /dev/twa0::3ware,2";
|
||||
#ifdef _WIN32
|
||||
device_options_tooltip = hz::string_sprintf(device_options_tooltip.c_str(), "\"pd0\" for the first physical drive");
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user