Compare commits

...
60 Commits
Author SHA1 Message Date
Alexander Shaduri 168aeec882 Tagged 0.9.0. 2017-05-11 09:00:23 +00:00
Alexander Shaduri afdb516386 Updated copyright years. 2017-05-11 08:42:23 +00:00
Alexander Shaduri 9a1f28fe9a Fixed some win32 installer issues. 2017-05-10 21:26:56 +00:00
Alexander Shaduri b4583a7cc6 Bumped version to 0.9.0. 2017-05-10 20:08:20 +00:00
Alexander Shaduri 9918b13214 Updated drive descriptions to drivedb.h r4430, 2017-05-03.
Fixed selective self-test section parsing (if it's unsupported).
2017-05-10 20:06:44 +00:00
Alexander Shaduri 3f9d830294 Added appdata metainfo file. 2017-05-08 17:54:25 +00:00
Alexander Shaduri 7b2627b236 Clear the drives and show "please rescan" message after the preferences are
updated; this ensures that no old settings are used.
2017-05-08 17:16:27 +00:00
Alexander Shaduri c40d87b3ae Require gtk2 2.6.0 until we move to 2.24.0.
Win32 drive detection: stop scanning only after 3 not-found drives, so that
we detect drives after old removed drives.
2017-05-08 16:47:52 +00:00
Alexander Shaduri 99f707b6c6 Require gtk2 2.24.0, for future compatibility with gtk3. 2017-05-08 10:51:27 +00:00
Alexander Shaduri a561d5fef6 Changed the license field in spec file to conform to OBS requirements. 2016-06-04 16:14:12 +00:00
Alexander Shaduri 1d305e7626 Fixed time formatting with VS. 2015-07-01 12:10:23 +00:00
Alexander Shaduri 194fb51f75 Disable dpiAware flag in win32 manifest since it's not supported that well. 2014-05-29 18:00:49 +00:00
Alexander Shaduri e2dc39bff2 Don't show the info window if there's nothing to show. 2014-05-05 10:37:24 +00:00
Alexander Shaduri 836aa73430 Avoid scientific notation when displaying the drive size. 2014-05-05 10:16:38 +00:00
Alexander Shaduri 63f5b885a3 Fixed glib 2.32 warnings. 2014-05-05 09:36:10 +00:00
Alexander Shaduri c68d017475 Updated to latest libhz. 2014-05-05 09:20:18 +00:00
Alexander Shaduri bbe3bac923 Make sure we write some data from the Info window on Save Output if only basic
data is available.
Fixed a harmless "Number of written bytes doesn't match the data size" warning.
Added support for SSD-only and HDD-only vendor attributes.
Added the latest (r3897 / 2014-04-28) attributes from smartmontools.
Increased the Info window size a bit.
2014-05-05 08:59:13 +00:00
Alexander Shaduri 2293e357f4 Increased main window size a bit to avoid the iconview shift down each time an
icon is selected.
Added some scsi-output properties to full parser to avoid console warnings.
Devices having only basic info can be displayed now in the info window.
2014-04-30 10:38:48 +00:00
Alexander Shaduri 85dbceb14d Fixed a crash at scan time (bad parsing of empty smartctl output sections).
Updated program descriptions to include SSD.
2014-04-16 20:04:04 +00:00
Alexander Shaduri 45cba39be7 RAID volumes which report having SMART are now detected and explicitly set to
not having SMART.
2013-10-17 10:26:53 +00:00
Alexander Shaduri a0b235dd8a Increased timeouts when executing commands before the "Cancel" dialog is
shown; this helps with constant focus stealing from other windows when
smartctl is too slow (usually under Windows).
2013-02-25 20:27:18 +00:00
Alexander Shaduri 7e3db9ec30 Implemented detection for some new "not supported" smartctl messages. 2013-02-24 20:07:51 +00:00
Alexander Shaduri 6cc8770599 Implemented Linux support for Areca controllers with enclosures (untested).
Implemented Windows support for Areca controllers (thanks to Richard Kagerer);
untested so far.
2013-02-24 20:02:30 +00:00
Alexander Shaduri 462d465f3a Modified all glade files to use gtk 2.8 compatibility (not sure if it works).
Removed "tooltip_text" properties from all glade files, "tooltip" should be
enough.
Set the "activates_default" property on all relevant entries in glade files;
this will make the Enter key activate the default dialog action when these
entries are focused.
Added some clarifying text to Add Device dialog.
Clarified the per-drive parameters section (what it does) in Preferences.
Added a confirmation dialog in case the user doesn't set the Parameters field
in one of the Per-Drive Parameters entries.
Added a "Smartctl Options" section to README/Help.
Clarified the difference between smartctl.exe and smartctl-nc.exe in a
tooltip.
Improved some other tooltips.
2013-02-11 11:09:00 +00:00
Alexander Shaduri 6ac62cd0de Device detection is a lot more verbose now.
The read /proc files are now cached to avoid needless re-reading.
Some other minor changes.
2013-02-10 20:55:58 +00:00
Alexander Shaduri 1174b62b8f Bumped version number to 0.8.8. 2012-12-23 19:27:47 +00:00
Alexander Shaduri ef713900a0 Implemented support for HP controllers behind cciss and hpsa/hpahcisr drivers. 2012-12-23 19:25:20 +00:00
Alexander Shaduri c60f6815fa Fixed BDRW drive detection (it was detected as a HDD).
Added support for recent smartctl -i changes.
2012-09-28 08:52:10 +00:00
Alexander Shaduri 7ca709fcbb Fixed a comment. 2012-08-11 14:24:58 +00:00
Alexander Shaduri c3ce878376 Don't require libglademm in debian control file, it confuses newer Ubuntus. 2012-08-11 14:19:58 +00:00
Alexander Shaduri a06ac42eff Don't limit Fedora versions. 2012-08-11 13:30:55 +00:00
Alexander Shaduri 444eb6c211 Fixed spec file problems with Fedora.
Updated NEWS file.
2012-08-11 11:43:39 +00:00
Alexander Shaduri eb6cbe1ee0 Fixed make dist error. 2012-08-10 16:47:11 +00:00
Alexander Shaduri bcae9a2c37 Increased application version to 0.8.7.
Added Fedora consolehelper support to the spec file.
2012-08-10 16:33:29 +00:00
Alexander Shaduri d411b34dae Updated smartctl attributes from r3515 to r3587.
Added warnings for SSD lifetime attributes.
2012-08-10 15:49:28 +00:00
Alexander Shaduri a0fad4375a Added options to show device name and serial number under drive icons.
Added serial number to drive icon tooltip.
Fixed compiler error introduced in previous revision.
Removed some useless tooltips from UI.
2012-08-10 09:44:06 +00:00
Alexander Shaduri ffb02984fe Documented the rest of the code (rconfig, rmn, libdebug).
Fixed up the doxygen documentation, should be in usable state now.
2012-08-08 17:33:26 +00:00
Alexander Shaduri b400df2565 Completely documented hz, gsc and applib.
Fixed some compiler warnings.
Removed some unused files.
Added hz/initialized.h as part of hz.
2012-08-05 20:18:22 +00:00
Alexander Shaduri b06607cc37 Added a missing #include statement that caused build errors on SLES SP2.
Updated .spec and .desktop file to fix some warnings.
2012-04-28 15:17:44 +00:00
Alexander Shaduri 8881f42470 Fixed the detection of 3ware 9750 (twl) devices.
Implemented support for systems with several different 3ware controllers
(twa/twe/twl).
2012-03-12 20:06:33 +00:00
Alexander Shaduri 6558d31680 Support Areca RAID controller detection under Linux (untested).
Support 3ware 3w-sas-supported RAID controller detection under Linux (untested).
2012-03-03 18:03:15 +00:00
Alexander Shaduri 6e949677ec Don't open \\.\PhysicalDriveN needlessly if it was filtered out by --scan-open. 2012-02-26 19:19:34 +00:00
Alexander Shaduri 72f2d166b6 Updated the man page to reflect the new gsmartcontrol-root syntax.
The previous commit also contained the following changes:
The gsmartcontrol-root wrapper script now properly escapes the arguments
before passing them to gsmartcontrol.
gsmartcontrol-root has a new argument "--desktop=..." which replaces the old
positional argument; compatibility with the old invokation syntax has been
retained.
2012-02-19 15:09:26 +00:00
Alexander Shaduri 7b13cdf7b3 GSmartControl now prints an error message and a help text if an invalid
command-line options was specified.
2012-02-19 15:04:47 +00:00
Alexander Shaduri c7bdaad30a Fixed invalid parsing of tw_cli output which caused non-detection of drives
and controllers with controller or port numbers greater than 9 (3ware linux,
windows).
The same-brand controllers with identical SCSI host numbers are collapsed into
one controller now (the others are for LUNs and only pollute the drive list).
The drives are sorted during detection, not when adding them to the GUI.
The drive sorting algorithm has been slightly changed.
2012-02-19 13:10:05 +00:00
Alexander Shaduri fd9fce25fc Implemented support for Adaptec RAID 5805 controller and possibly other
Adaptec models as well.
2012-02-19 10:28:52 +00:00
Alexander Shaduri 5ba7add5b5 Fixed a few VS /analyze warnings in win32_tools.h. 2012-01-16 16:28:52 +00:00
Alexander Shaduri 68889d3804 Updated copyright headers for year 2012.
Updated the command line option descriptions in the man page and README.txt.
2012-01-11 17:26:34 +00:00
Alexander Shaduri 8ab18d433a The manifest now indicates that GSmartControl is dpi-aware (no more blurring
in high-dpi situations under Windows).
2012-01-09 16:52:29 +00:00
Alexander Shaduri 13d83949c4 Fix possibly invalid utf-8 data before showing it to the user (GscTextWindow,
GscExecutorLogWindow).
2011-12-15 16:58:06 +00:00
Alexander Shaduri daf98009d4 Added description for Multi_Zone_Error_Rate. 2011-12-15 15:57:58 +00:00
Alexander Shaduri 0cf5848772 Merged FreeBSD patches (fix in gsmartcontrol-root, /dev/ada* detection. 2011-11-19 18:08:58 +00:00
Alexander Shaduri 0ecc4bd8d3 Fixed compilation under Glib 2.31.x. 2011-11-02 16:00:39 +00:00
Alexander Shaduri 388a195794 Fixed compilation error.
Fixed parsing 'smartctl -v 194,raw8 -a' output (the attribute line).
2011-10-15 17:56:55 +00:00
Alexander Shaduri 0f89010225 Documented some more of hz. 2011-08-17 20:15:58 +00:00
Alexander Shaduri 42da49c5c1 Documented parts of hz library using doxygen tags. 2011-08-16 20:05:39 +00:00
Alexander Shaduri 0ffba26b1f Added (untested) Doxyfile.
Documented a few more hz files.
Added clang detection to the build system, use it when setting flags, etc...
Added some clang-specific flags to avoid excessive and unneeded warnings.
Fixed compilation under clang.
Fixed some clang-reported warnings.
2011-08-15 20:08:11 +00:00
Alexander Shaduri b19b094aaa Fixed a bug that issued SIGTERM to the child process instead of SIGKILL.
Documented applib completely.
Some minor member visibility adjustments.
2011-07-30 19:57:28 +00:00
Alexander Shaduri 5cc1e898b9 Use model name as well when detecting S/N duplicates. 2011-07-30 16:16:21 +00:00
Alexander Shaduri a4aa68a085 Very minor documentation changes.
NSIS: Don't strip update-smart-database.exe (it breaks if stripped) and
smartctl* (no reason to do it).
NSIS: Delete gtk installer on uninstall, sometimes it's not deleted during
installation.
2011-06-20 20:59:36 +00:00
343 changed files with 15457 additions and 11007 deletions
View File
+1743
View File
File diff suppressed because it is too large Load Diff
View File
+7 -5
View File
@@ -68,7 +68,7 @@ src-rpm: dist
# NSIS installer support.
# Requires wine, installed NSIS, smartctl-nc.exe, smartctl.exe.
# Requires wine, installed NSIS, smartctl-nc.exe, smartctl.exe, update-smart-drivedb.exe.
# Gtkmm dlls and pcre dlls are required if linking against them.
# dos2unix on build machine.
# Execute only with win32 build present.
@@ -91,6 +91,8 @@ win-dist-clean: win-dist-cleanup
win-dist-prepare-all: nsis-dist-prepare win-zip-dist-prepare
# Don't strip smartctl (it will only change the header), and
# don't strip update-smart-drivedb (it will break its CRC check).
win-dist-prepare: all
$(MKDIR_P) win-dist
cp $(top_srcdir)/data/icon_*.png win-dist/
@@ -100,13 +102,13 @@ win-dist-prepare: all
cp $(top_srcdir)/AUTHORS.txt $(top_srcdir)/LICENSE_* $(top_srcdir)/README.txt win-dist/doc/
cp $(top_srcdir)/NEWS win-dist/doc/NEWS.txt
cp "@WINDOWS_BINDIR@"/smartctl-nc.exe win-dist/
cp "@WINDOWS_BINDIR@"/smartctl.exe win-dist/
cp src/gsmartcontrol.exe src/gsmartcontrol.exe.manifest win-dist/
unix2dos win-dist/doc/*.txt
$(STRIP) win-dist/*.exe
cp -p "@WINDOWS_BINDIR@"/smartctl-nc.exe win-dist/
cp -p "@WINDOWS_BINDIR@"/smartctl.exe win-dist/
cp -p "@WINDOWS_BINDIR@"/update-smart-drivedb.exe win-dist/
nsis-dist-prepare: win-dist-prepare
+49 -1
View File
@@ -1,5 +1,53 @@
Version 0.8.6, released on 2011-05-29
Version 0.9.0, released on 2017-05-11
Implemented (untested) support for Linux-based Areca controllers with
enclosures.
Implemented (untested) support for Windows-based Areca controllers (thanks
to Richard Kagerer).
Implemented (untested) support for Linux-based HP controllers with cciss
and hpsa/hpahcisr drivers (thanks to Fabrice Bacchella).
Changes in Preferences no longer fail silently until rescan/restart.
Better drive detection under Windows after removable drives are detached.
Windows version is no longer marked as "dpi aware" since it's not
supported that well.
Drive attribute descriptions have been updated (including clarifications
for SSDs).
Added support for SSD-only and HDD-only vendor attributes.
Devices having only basic info can be displayed now in the info window.
Fixed BDRW drive detection (it was detected as a HDD).
Other minor improvements.
A number of issues have been fixed (including a crash).
Version 0.8.7, released on 2012-08-11
Implemented support for Adaptec RAID 5805 controller and possibly other
Adaptec models as well (Linux).
Implemented support for Areca RAID controller detection under Linux
(untested).
Implemented support for 3ware 3w-sas-supported (twl) RAID controller
detection under Linux (untested).
Implemented support for systems with several different 3ware controllers
(twa/twe/twl).
Fixed invalid parsing of tw_cli output which caused non-detection of
drives and controllers with controller or port numbers greater than 9
if tw_cli was found (3ware linux, windows).
The duplicate drives are no longer shown for some Intel matrix controllers
under Windows; Intel RAID controllers are fully supported under
Windows now.
Added options to show device name and serial number under drive icons.
Updated SMART attribute definitions and added warnings for SSD lifetime
attributes.
gsmartcontrol-root has a new argument "--desktop=..." which replaces the
old positional argument; compatibility with the old invocation syntax
has been retained.
Completely documented the source using doxygen tags.
Added support for Fedora's consolehelper.
Made GSmartControl DPI-aware under Windows.
Fixed compilation issues with clang and gcc 4.7, as well as glib 2.31.x
and newer.
Fixed minor issues in NSIS installer.
Fixed other minor bugs and made minor improvements.
Version 0.8.6, released on 2011-06-12
Support detecting drives behind 3ware controllers (Linux, Windows),
including tw_cli/cx/px mode in Windows. Having tw_cli is recommended
but not required.
+47 -35
View File
@@ -1,19 +1,20 @@
About GSmartControl
GSmartControl - Hard disk drive health inspection tool.
GSmartControl - Hard disk drive and SSD health inspection tool.
GSmartControl is a graphical user interface for smartctl (from smartmontools
package, see http://smartmontools.sourceforge.net), which is a tool for
querying and controlling SMART (Self-Monitoring, Analysis, and Reporting
Technology) data on modern hard disk drives. It allows you to inspect the
drive's SMART data to determine its health, as well as run various tests on
it.
Technology) data on modern hard disk and solid-state drives. It allows you to
inspect the drive's SMART data to determine its health, as well as run various
tests on it.
Note: GSmartControl supports ATA drives (both PATA and SATA), various USB to
ATA bridges and drives behind 3ware RAID controllers.
ATA bridges and drives behind some RAID controllers (selected models of
3ware, Areca, Adaptec, Intel RAID controllers).
http://gsmartcontrol.berlios.de
http://gsmartcontrol.sourceforge.net
@@ -51,15 +52,15 @@ methods to predict certain kinds of failures with certain chance of success.
Long answer: read below.
Self-Monitoring, Analysis, and Reporting Technology, or SMART, is a
monitoring system for hard drives to detect and report various indicators of
reliability, in the hope of anticipating failures. It is implemented inside
the drives SMART provides several ways of monitoring hard drive health. It
may provide information about general health, various drive attributes (for
example, number of unreadable sectors), error logs, and so on. It may also
provide ways to instruct the drive to run various self-tests, which may report
valuable information. It may even automatically scan the disk surface in when
the drive is idle, and repair the defects, reallocating the data to more safe
areas.
monitoring system for hard drives and SSDs to detect and report various
indicators of reliability, in the hope of anticipating failures. SMART is
implemented inside the drives, providing several ways of monitoring the drive
health. It may present information about general health, various drive
attributes (for example, number of unreadable sectors), error logs, and so on.
It may also provide ways to instruct the drive to run various self-tests,
which may report valuable information. It may even automatically scan the disk
surface in when the drive is idle, repairing the defects while reallocating
the data to more safe areas.
While having SMART sounds really good, there are some nuances to consider. One
of the common pitfalls is that it may create a false sense of security. That
@@ -75,15 +76,15 @@ necessarily agree on precise attribute definitions and measurement units, the
exact meaning of the attributes may vary greatly across different drive
models.
At present SMART is implemented individually by manufacturers, and while some
At present SMART is implemented individually by manufacturers. While some
aspects are standardized for compatibility, others are not. In fact, most
manufacturers refer the users to their own health monitoring utilities, and
manufacturers refer the users to their own health monitoring utilities and
advice against taking SMART data seriously. Nevertheless, SMART may prove an
effective measure against data loss.
Yet another issue is that quite often the drives have bugs which prevent
correct SMART usage. This is usually due to buggy firmware, or the
manufacturer ignoring the standard. Luckily, smartmontools usually detects
manufacturer ignoring the standards. Luckily, smartmontools usually detects
these bugs and works around them.
@@ -101,7 +102,7 @@ You need to have the following software installed:
* Gtkmm, version 2.6 or higher - see http://www.gtkmm.org .
* libglademm, version 2.4 or higher - see http://www.gtkmm.org .
Note: libglademm is not needed when using GTK / Gtkmm 2.12 or newer.
Note: libglademm is not needed when using GTK+ / Gtkmm 2.12 or newer.
Note that having GTK+ 2.12 and Gtkmm 2.12 is HIGHLY recommended. While earlier
versions may work, they may produce suboptimal results and buggy behavior.
@@ -131,7 +132,6 @@ Note: If using the official Windows package, the requirements are listed on
GSmartControl's website.
The following operating systems are supported:
* Linux - All the popular configurations should work.
@@ -148,11 +148,9 @@ Windows port uses pd0, pd1, etc... for physical drives 0, 1, etc... .
* Solaris - Tested with Solaris 10 / x86 / gcc-3.4.3 / blastwave,
Solaris 10 / x86 / sunstudio12 / sunfreeware. OpenSolaris should work but has
not been tested yet. Note: smartctl doesn't seem to support ATA under Solaris,
while GSmartControl doesn't support SCSI yet. This only leaves various USB to
ATA bridges. See smartctl (5), -d option for details.
not been tested yet.
* Mac OS X - 3rd-party testing by Fink project.
* Mac OS X - 3rd-party testing by the MacPorts and Fink projects.
* DragonFlyBSD - Code written but no testing has been performed yet. Expected
to work without any issues.
@@ -189,6 +187,18 @@ directly from the build directory.
Smartctl Options
GSmartControl tries its best to guard the user from having to specify smartctl
options. However, this is not always possible due to drive firmware bugs,
unimplemented features, and so on. The smartctl manual page contains all the
information you may need when dealing with smartctl.
See http://smartmontools.sourceforge.net/man/smartctl.8.html
Additional information is available at http://smartmontools.sourceforge.net
Command Line Options
GSmartControl inherits options from GTK+ and other libraries, so be sure to
@@ -202,22 +212,24 @@ The most important parameters are:
-?, --help - Show help options.
-V, --version - Display version information.
-l, --no-locale - Don't use system locale.
-l, --no-locale - Disable locale.
-V, --version - Display version information.
--no-scan - Don't scan devices on startup.
--no-hide-tabs - Don't hide non-identity tabs when SMART is disabled.
--no-hide-tabs - Don't hide non-identity tabs when SMART is disabled. Useful
for debugging.
--add-virtual - Load smartctl data from file, creating a virtual drive.
--add-virtual - Load smartctl data from file, creating a virtual drive. You
can specify this option multiple times.
--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'
"<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'.
-v, --verbose - Enable verbose logging; same as --verbosity-level 5.
@@ -286,7 +298,7 @@ For more information, see smartctl and smartd documentation.
Known Issues
Only ATA drives (both PATA and SATA), various USB to ATA bridges and drives
behind 3ware RAID controllers are supported for now. The main reasons are:
behind some RAID controllers are supported for now. The main reasons are:
* We can't support drives which don't work with smartmontools. This affects
drives which don't support SMART or don't export SMART data correctly (e.g.
@@ -296,7 +308,7 @@ some USB enclosures, RAIDs, etc...).
Also, SCSI drives are rarely found in desktop systems and the servers rarely
have X11 / Gtkmm running, so this is a low priority task.
* I only have ATA drives, so testing would be almost impossible.
* I only have ATA drives, so testing anything else is very difficult.
Immediate Offline Tests are not supported. I haven't found a way to reliably
monitor them yet. Besides, they run automatically anyway if Automatic Offline
+71 -61
View File
@@ -20,26 +20,63 @@ with existing model, which should be unset.
Bugs / patches:
Patch pangomm for Pango::strip_markup().
+ gtkmm bug: No Gtk::AboutDialog::set_logo(NULL);
+ Gtk::Main m(argc, argv, false);
If gtk_get_option_group() and g_option_context_parse() were used before,
this generates a warning:
(gsmartcontrol:28241): Gtk-WARNING **: gtk_disable_setlocale() must be called before gtk_init()
--------------------------------------------------------
TODO:
Don't rely on smartctl return code (2), parse the output instead.
This will allow us to show the Info page.
test, release RC version for testing.
Update to drivedb.h from 5.41, include 5.41 into release.
?Fix not being able to quit while executing commands.
Cannot reproduce.
https://www.google.com/search?client=opera&q=IA__gtk_main_quit:+assertion+%60main_loops+!=+NULL'+failed&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest
https://developer.gnome.org/gtk2/2.24/gtk2-General.html#gtk-main-quit
https://www.google.com/search?num=50&hl=en&safe=off&client=opera&hs=Dr5&channel=suggest&q=calling+gtk_main_quit+during+gtk_main_iteration+warning&oq=calling+gtk_main_quit+during+gtk_main_iteration+warning&gs_l=serp.12...7064.8155.0.12753.8.8.0.0.0.0.216.935.0j6j1.7.0.les%3B..0.0...1c.1.4.serp.GUiDL5IM2U8
https://developer.gnome.org/glib/2.34/glib-The-Main-Event-Loop.html#g-main-loop-quit
Port to GTK2 with disable-deprecated flags, then GTK3.
Drop support for old distros.
In main window add multi-selection support and right-click menu with various
tests, so that it's possible to run multiple tests in parallel from there.
Areca detection
Linux:
Somehow differentiate between the cards with expanders (-d areca,N/E) and without (-d areca,N).
The expander ones seem to have "ix" (case-insensitive) as their name suffixes.
areca,N - N is [1,24].
areca,N/E - N is [1,128], E is [1,8].
We should limit these using some config key (36 for N and 4 for E seems ok).
N/E syntax is since smartmontools 5.43.
For older versions we get: /dev/<something>: Option -d areca,N requires N to be a non-negative integer
Windows Detection:
Credit Richard Kagerer.
Credit Fabrice Bacchella for Linux CCISS detection.
Add ability (through ctrl-C?) to copy individual rows from attributes page,
in tab-separated format (for easy pasting into libreoffice).
Investiage the new "-l ssd" and "-l devstat" options (since 5.42)
Check also other options in 5.42 and 5.43.
"-g all" looks promising alongside -i (shows APM and other stuff as well).
Add --identify option to context menu, for convenience.
Add menu item - "update drive database" (not sure about linux, should
check if it's supported first; also need to run it in terminal).
Testing:
@@ -51,13 +88,19 @@ Testing:
may be stuck due to bad firmware, e.g. 3ware/windows).
Add support for launching with consolehelper (from usermode package).
Fedora uses this by default.
Investigate Fedora selinux situation.
usermode-gtk contains consolehelper-gtk, not sure about our package
requirement. consolehelper-gtk is not supposed to be launched by user,
but I think we can check it with "which".
http://fedoranews.org/contributors/matt_hansen/nautilus/
48-bit ATA command support:
'-l xerror' -> Extended Comprehensive Error log: An multi-sector and
LBA48 capable version of '-l error'. Output is similar, except more
entries can exists and the high bytes of the registers are also printed.
Some newer drives (Samsung) only write to this log.
'-l xselftest' -> Extended Self Test Log: An multi-sector and LBA48
capable version of '-l selftest'. Output will be similar, except more
entries can exists and the LBA values can be somewhat longer.
"smartctl -l this_wont_exist" gives the list of supported logs - this
is needed to detect xerror / xselftest support in smartctl.
Rework drive properties UI:
@@ -92,6 +135,12 @@ Monitor:
Periodically see if drives were added / removed (possibly use OS callbacks
instead of polling?)
Win7 widget:
Can be done in html/js.
Shows temperature
Detects drives
Opens GSmartControl
If a drive is not recognized, suggest using -d (sat, sat,12, ...)
Refer the user to
http://sourceforge.net/apps/trac/smartmontools/wiki/Supported_USB-Devices
@@ -101,21 +150,11 @@ If a drive is not recognized, suggest using -d (sat, sat,12, ...)
RAID:
http://sourceforge.net/apps/trac/smartmontools/wiki/Supported_RAID-Controllers
Areca Linux:
Call as: smartctl -i -d areca,[1-24] /dev/sg0
Detection:
Check if /proc/scsi/sg/device_strs contains "Areca RAID controller".
If not, there's no Areca controller present.
Check /proc/scsi/sg/devices, the line # with type 3 is the sg* number.
The "host" field value is the N value in /sys, see below.
Check /sys/bus/scsi/devices/hostN/scsi_host/hostN/host_fw_hd_channels, set
its contents as the number of ports. If not present, use 24.
Probe each port for a valid drive: If the output contains "Device Read Identity Failed",
then there is no drive on that port (or Areca has an old firmware, nothing we can
do there).
Notification: If /sys/bus/scsi/devices/hostN/scsi_host/hostN/host_fw_version
is older than "V1.46 2009-01-06", notify the user (maybe its better to grep
the smartctl output for that on port 0?).
Areca Windows:
Detection not supported by smartctl --scan-open.
Areca FreeBSD: since 5.42.
Call as: smartctl -a -d areca,[1-24] /dev/arcmsr1
3ware FreeBSD:
Call as: smartctl -i -d 3ware,[0-127] /dev/twa0 (or twe0)
@@ -142,21 +181,6 @@ RAID:
Detection: unknown.
TODO: Analyze sent info.
CCISS (HP (Compaq) Smart Array Controller) Linux:
Call as: smartctl -a -d cciss,[0-127] /dev/cciss/c0d0
c0d0 is the controller (d0 seems to be a logical drive, doesn't matter?).
/dev/cciss/c0d0p1 is the first ordinary partition (used in mount, etc...).
The port limit had a brief regression in 5.39.x (limited to 15).
5.39 doesn't seem to work at all (prereleases work with P400 controller)?
Possibly a 64-bit-only issue?
To detect controller presence: cat /proc/devices, contains "cciss0"
for controller 0.
There is a cciss_vol_status utility but it doesn't report anything except "OK" status.
It may not return the "SMART Health Status: OK" line in smartctl -i for some reason?
(It returns it in -a though, and in some freebsd output I found).
If no /dev/cciss exists, you may need to run "cd /dev; ./MAKEDEV cciss".
Smartctl SVN has some /dev/sg* stuff, check it out.
CCISS (HP (Compaq) Smart Array Controller) FreeBSD:
Seems to be the same as Linux (uses the same driver?).
Detection: unknown.
@@ -172,20 +196,6 @@ libdebug:
use format_time() instead of ctime() and friends, with ISO formatting.
48-bit ATA command support:
'-l xerror' -> Extended Comprehensive Error log: An multi-sector and
LBA48 capable version of '-l error'. Output is similar, except more
entries can exists and the high bytes of the registers are also printed.
Some newer drives (Samsung) only write to this log.
'-l xselftest' -> Extended Self Test Log: An multi-sector and LBA48
capable version of '-l selftest'. Output will be similar, except more
entries can exists and the LBA values can be somewhat longer.
"smartctl -l this_wont_exist" gives the list of supported logs - this
is needed to detect xerror / xselftest support in smartctl.
'-l sataphy' -> SATA Phy event counters: Non-SMART feature, useful to detect SATA cabling problems.
@@ -30,7 +30,7 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
# ---- Common compiler options (warnings, etc...)
AC_ARG_ENABLE(common-options, AS_HELP_STRING([--enable-common-options=<compiler>|auto|none],
[enable useful compilation options (warnings, mostly). Accepted values are auto, none, gnu, intel, sun. (Default: auto)]),
[enable useful compilation options (warnings, mostly). Accepted values are auto, none, gnu, clang, intel, sun. (Default: auto)]),
[app_cv_compiler_common_options=${enableval}], [app_cv_compiler_common_options=auto])
# the default value is "yes" (if no value given after =), treat it as auto.
@@ -47,8 +47,8 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
if test "x$app_cv_compiler_common_options" != "xnone"; then
# gcc / gnu environment, mingw, cygwin.
if test "x$app_cv_compiler_common_options" = "xgnu"; then
# gcc (or clang) / gnu environment, mingw, cygwin.
if test "x$app_cv_compiler_common_options" = "xgnu" || test "x$app_cv_compiler_common_options" = "xclang"; then
if test "x$app_cv_target_os_env" = "xmingw32" || test "x$app_cv_target_os_env" = "xmingw64" \
|| test "x$app_cv_target_os_env" = "xcygwin"; then
@@ -63,6 +63,10 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
app_cv_compiler_tmp_var="-Wall -Wcast-align -Wcast-qual -Wconversion \
-Wctor-dtor-privacy -Wfloat-equal -Wnon-virtual-dtor -Woverloaded-virtual \
-Wpointer-arith -Wshadow -Wsign-compare -Wsign-promo -Wundef -Wwrite-strings";
if test "x$app_cv_compiler_common_options" = "xclang"; then
# these are really annoying
app_cv_compiler_tmp_var="$app_cv_compiler_tmp_var -Wno-sign-conversion -Wno-format-security"
fi
app_cv_compiler_options_cflags="$app_cv_compiler_options_cflags $app_cv_compiler_tmp_var";
app_cv_compiler_options_cxxflags="$app_cv_compiler_options_cxxflags $app_cv_compiler_tmp_var";
@@ -102,7 +106,7 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
# ---- Compiler options for debug builds
AC_ARG_ENABLE(debug-options, AS_HELP_STRING([--enable-debug-options=<compiler>|auto|none],
[enable debug build options. Accepted values are auto, none, gnu, intel, sun. (Default: none)]),
[enable debug build options. Accepted values are auto, none, gnu, clang, intel, sun. (Default: none)]),
[app_cv_compiler_debug_options=${enableval}], [app_cv_compiler_debug_options=none])
# the default value is "yes" (if no value given after =), treat it as auto.
@@ -124,7 +128,7 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
AC_DEFINE([DEBUG_BUILD], [1], [Defined for debug builds])
# gcc, mingw
if test "x$app_cv_compiler_debug_options" = "xgnu"; then
if test "x$app_cv_compiler_debug_options" = "xgnu" || test "x$app_cv_compiler_debug_options" = "xclang"; then
# We could put libstdc++ debug options here, but it generates binary-incompatible
# C++ code, which leads to runtime errors with e.g. libsigc++.
app_cv_compiler_options_cflags="$app_cv_compiler_options_cflags -g3 -O0";
@@ -154,7 +158,7 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
# ---- Compiler options for optimized builds
AC_ARG_ENABLE(optimize-options, AS_HELP_STRING([--enable-optimize-options=<compiler>|auto|none],
[enable optimized build options. Accepted values are auto, none, gnu, intel, sun. (Default: none)]),
[enable optimized build options. Accepted values are auto, none, gnu, clang, intel, sun. (Default: none)]),
[app_cv_compiler_optimize_options=${enableval}], [app_cv_compiler_optimize_options=none])
# the default value is "yes" (if no value given after =), treat it as auto.
@@ -172,7 +176,7 @@ AC_DEFUN([APP_COMPILER_OPTIONS], [
if test "x$app_cv_compiler_optimize_options" != "xnone"; then
# gcc, mingw
if test "x$app_cv_compiler_optimize_options" = "xgnu"; then
if test "x$app_cv_compiler_optimize_options" = "xgnu" || test "x$app_cv_compiler_optimize_options" = "xclang"; then
# -mtune=generic is since gcc 4.0 iirc
if test "x$app_cv_target_os_env" = "xmingw32"; then
app_cv_compiler_options_cflags="$app_cv_compiler_options_cflags -g0 -O3 -s -march=i686";
@@ -55,8 +55,8 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
linux)
# glibc manual says that defining either _REENTRANT or _THREAD_SAFE
# enables some thread-safe implementations of glibc functions.
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "intel" \
|| test "$ax_cv_cxx_compiler_vendor" = "pathscale"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang" \
|| test "$ax_cv_cxx_compiler_vendor" = "intel" || test "$ax_cv_cxx_compiler_vendor" = "pathscale"; then
app_cv_target_thread_cflags="-pthread -D_MT -D_THREAD_SAFE"
app_cv_target_thread_cxxflags="-pthread -D_MT -D_THREAD_SAFE"
app_cv_target_thread_libs="-pthread"
@@ -77,12 +77,12 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
;;
windows*)
# NOTE: Not sure about cygwin.
# NOTE: Not sure about cygwin or clang.
# NOTE: This only enables multithreaded code generation. For linking
# with pthreads-win32 you need additional flags.
# gcc man page: -mthreads: Support thread-safe exception handling on Mingw32.
# -mthreads defines -D_MT, and links with -lmingwthrd.
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
app_cv_target_thread_cflags="-mthreads -D_THREAD_SAFE"
app_cv_target_thread_cxxflags="-mthreads -D_THREAD_SAFE"
app_cv_target_thread_libs="-mthreads"
@@ -104,7 +104,7 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
# NOTE: Not sure about debian gnu/kfreebsd and gnu/netbsd.
# Freebsd had -kthread, but it has been discontinued (afaik).
# For freebsd -pthread replaces libc with libc_r.
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
app_cv_target_thread_cflags="-pthread -D_MT -D_THREAD_SAFE"
app_cv_target_thread_cxxflags="-pthread -D_MT -D_THREAD_SAFE"
app_cv_target_thread_libs="-pthread"
@@ -113,7 +113,7 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
;;
openbsd)
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
app_cv_target_thread_cflags="-pthread -D_REENTRANT"
app_cv_target_thread_cxxflags="-pthread -D_REENTRANT"
app_cv_target_thread_libs="-pthread"
@@ -123,7 +123,7 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
netbsd)
# See sys/featuretest.h
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
app_cv_target_thread_cflags="-pthread -D_REENTRANT"
app_cv_target_thread_cxxflags="-pthread -D_REENTRANT"
app_cv_target_thread_libs="-pthread"
@@ -132,7 +132,7 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
;;
solaris)
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
# gnu documentation mentions -threads (and its aliases, -pthreads and -pthread).
# _REENTRANT is needed to enable some thread-safe equivalents of standard
# functions.
@@ -159,14 +159,14 @@ AC_DEFUN([APP_GET_MT_FLAGS], [
;;
darwin)
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
# Darwin produces mt code by default, and -pthread is an error.
app_cv_target_thread_found="yes"
fi
;;
qnx)
if test "$ax_cv_cxx_compiler_vendor" = "gnu"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang"; then
# afaik, gcc/qnx produces mt code by default (at least on newer qnx releases),
# so no flags are needed.
app_cv_target_thread_found="yes"
@@ -53,7 +53,7 @@ AC_DEFUN([AX_COMPILER_VENDOR],
AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
[ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
# note: don't check for gcc first since some other compilers define __GNUC__
for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
for ventest in clang:__clang__ intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
#if !($vencpp)
View File
@@ -8,7 +8,7 @@ configure_script="$2";
if [ "$type" == "" ]; then
echo "Usage: $0 <type> [<configure_script>]"
echo "where <type> is one of:"
echo "debug optimized icc win32 win32-debug win64-debug sun portland open64";
echo "debug optimized icc clang win32 win32-debug win64-debug sun portland open64";
echo "<configure_script> is ../configure by default"
exit 1;
fi
@@ -25,13 +25,16 @@ case $type in
flags="--disable-user-flags --enable-optimize-options --enable-tests" ;;
debug)
flags="--enable-debug-options --enable-tests" ;;
clang)
flags="CC=clang CXX=clang++ --enable-debug-options --enable-tests" ;;
icc)
flags="CC=icc64 CXX=icpc64 --disable-user-flags --enable-tests" ;;
win32)
flags="CC=i386-pc-mingw32-gcc CXX=i386-pc-mingw32-g++ \
PKG_CONFIG_PATH=/cross/w32/target/lib/pkgconfig PKG_CONFIG_LIBDIR=\"\" \
PATH=\"/cross/w32/gcc-bin:/cross/w32/target/bin:$PATH\" \
--with-windows-gtk-name=gtk2-runtime-2.16.6-2010-05-12-ash --disable-user-flags \
--with-windows-gtk-name=gtk2-runtime-2.24.10-2012-10-10-ash --disable-user-flags \
--with-nsis=/root/.wine/drive_c/Programs_x86/NSIS/makensis.exe \
--enable-optimize-options --enable-tests --build=i686-linux --host=i386-pc-mingw32" ;;
win32-debug)
flags="CC=i386-pc-mingw32-gcc CXX=i386-pc-mingw32-g++ \
+4 -3
View File
@@ -1,5 +1,5 @@
AC_INIT([GSmartControl],[0.8.6],[],[gsmartcontrol])
AC_INIT([GSmartControl],[0.9.0],[],[gsmartcontrol])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_HEADERS([config.h])
@@ -454,7 +454,8 @@ ADDITIONAL_INCLUDES="-I\$(top_builddir) -I\$(top_srcdir)/src -I\$(top_srcdir)/sr
# (e.g. gccfss (gcc frontend / sun backend), etc...).
# We use -include only when using pch.
if test "x$app_cv_compiler_gcc_pch" = "xyes"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "intel" || test "$ax_cv_cxx_compiler_vendor" = "pathscale"; then
if test "$ax_cv_cxx_compiler_vendor" = "gnu" || test "$ax_cv_cxx_compiler_vendor" = "clang" \
|| test "$ax_cv_cxx_compiler_vendor" = "intel" || test "$ax_cv_cxx_compiler_vendor" = "pathscale"; then
# This auto-includes this file when compiling any file. Benefits include pch support.
ADDITIONAL_INCLUDES="$ADDITIONAL_INCLUDES -include global_macros.h"
fi
@@ -528,7 +529,7 @@ AC_SUBST(AUTODIRS)
# -------------------------------------------------------------------------------------
AC_CONFIG_FILES([ data/gsmartcontrol.desktop \
AC_CONFIG_FILES([ data/gsmartcontrol.desktop data/gsmartcontrol.appdata.xml \
data/nsis/distribution.txt data/nsis/distribution-nogtk.txt data/nsis/gsmartcontrol.nsi \
debian.dist/changelog \
src/gsc_winres.rc src/gsmartcontrol.exe.manifest \

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

@@ -40,6 +40,10 @@ appdata_DATA = icon_cddvd.png icon_hdd.png
desktopdir = $(datadir)/applications
desktop_DATA = gsmartcontrol.desktop
# Appdata files
metainfodir = $(datadir)/metainfo
metainfo_DATA = gsmartcontrol.appdata.xml
# Application pixmap (fallback icon for desktop files).
# Same as 48/gsmartcontrol.png.
@@ -1,7 +1,7 @@
#!/bin/bash
#!/usr/bin/env bash
############################################################################
# Copyright:
# (C) 2008 - 2010 Alexander Shaduri <ashaduri 'at' gmail.com>
# (C) 2008 - 2014 Alexander Shaduri <ashaduri 'at' gmail.com>
# License: See LICENSE_zlib.txt file
############################################################################
@@ -11,18 +11,43 @@
EXEC_BIN="@prefix@/bin/gsmartcontrol";
prog_name="gsmartcontrol"
DESKTOP="$1";
# This works for --help too
if [ "$DESKTOP" = "" ]; then
DESKTOP="auto"; # default
# Preserve quotes in arguments
final_args_quoted="";
for i in "$@";do
final_args_quoted="$final_args_quoted \"${i//\"/\\\"}\"";
done;
elif [ "$DESKTOP" != "auto" ] && [ "$DESKTOP" != "kde" ] && \
DESKTOP="auto";
# Compatibility with old syntax:
# gsmartcontrol-root [<desktop> [program_options]]
if [ "$1" == "auto" ] || [ "$1" == "kde" ] || [ "$1" == "gnome" ] || [ "$1" == "other" ]; then
DESKTOP="$1";
shift; # remove $1
else
# New syntax:
# gsmartcontrol-root [--desktop=<auto|kde|gnome|other>] [program_options]
for arg in $*; do
case $arg in
--desktop=*)
DESKTOP="${arg#*=}";
final_args_quoted="${final_args_quoted/\"$arg\"/}";
;;
*)
# unknown option
;;
esac
done
fi
if [ "$DESKTOP" != "auto" ] && [ "$DESKTOP" != "kde" ] && \
[ "$DESKTOP" != "gnome" ] && [ "$DESKTOP" != "other" ]; then
echo "Usage: $0 [<auto|kde|gnome|other> [<${prog_name}_options>] ]";
echo "Usage: $0 [--desktop=<auto|kde|gnome|other>] [<${prog_name}_options>]";
exit 1;
fi
shift; # remove $1
# Auto-detect current desktop if auto was specified.
@@ -42,6 +67,9 @@ fi
# echo $DESKTOP;
# They're basically the same, only the order is different.
# sux requires xterm to ask for the password.
# xdg-su is basically like this script, except worse :)
@@ -86,9 +114,10 @@ fi
# Add these directories _before_ existing PATH, so that the user is not
# tricked into running it from some other path (we're running as root with
# the user's env after all).
# Add @prefix@/sbin as well (freebsd seems to require it).
# Note that beesu won't show a GUI login box if /usr/sbin is before /usr/bin,
# so add it first as well.
EXTRA_PATHS="/usr/bin:/usr/sbin:/usr/local/sbin";
EXTRA_PATHS="/usr/bin:/usr/sbin:/usr/local/sbin:@prefix@/sbin";
export PATH="$EXTRA_PATHS:$PATH"
@@ -101,29 +130,30 @@ export PATH="$EXTRA_PATHS:$PATH"
# su-to-root -X -c 'gsmartcontrol --no-scan'
# xterm -e sux -c 'gsmartcontrol --no-scan' # sux asks for password in a terminal
full_cmd="";
if [ "$GSMARTCONTROL_SU" != "" ]; then
full_cmd="$GSMARTCONTROL_SU '$EXEC_BIN $@'";
full_cmd="$GSMARTCONTROL_SU '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "sux" ]; then
full_cmd="xterm -e sux -c '$EXEC_BIN $@'";
full_cmd="xterm -e sux -c '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "gksu" ]; then
full_cmd="$found_su '$EXEC_BIN $@'";
full_cmd="$found_su '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "beesu" ]; then
full_cmd="$found_su -P '$EXEC_BIN $@'";
full_cmd="$found_su -P '$EXEC_BIN $final_args_quoted'";
elif [ "$found_su" = "su-to-root" ]; then
full_cmd="$found_su -X -c '$EXEC_BIN $@'";
full_cmd="$found_su -X -c '$EXEC_BIN $final_args_quoted'";
else # gnomesu, kdesu, xdg-su
full_cmd="$found_su -c '$EXEC_BIN $@'";
full_cmd="$found_su -c '$EXEC_BIN $final_args_quoted'";
fi
#echo $full_cmd
# echo $full_cmd
eval $full_cmd
@@ -1,16 +1,16 @@
.TH GSmartControl "1" "" "gsmartcontrol " "User Commands"
.SH NAME
GSmartControl \- Hard disk drive health inspection tool
GSmartControl \- Hard disk drive and SSD health inspection tool
.SH SYNOPSIS
\fBgsmartcontrol\fP [OPTIONS]
\fBgsmartcontrol\-root\fP [\fI<desktop>\fP [OPTIONS]]
\fBgsmartcontrol\-root\fP [--desktop=\fI<desktop>\fP] [OPTIONS]
.SH DESCRIPTION
\fBGSmartControl\fP is a graphical user interface for smartctl (from
smartmontools), which is a tool for querying and controlling SMART
(Self-Monitoring, Analysis, and Reporting Technology) data on modern hard disk
drives. It allows you to inspect the drive's SMART data to determine its
health, as well as run various tests on it.
and solid-state drives. It allows you to inspect the drive's SMART data to
determine its health, as well as run various tests on it.
.PP
This manual page documents briefly the \fBgsmartcontrol\fP and
\fBgsmartcontrol\-root\fP commands.
@@ -37,7 +37,7 @@ Show logging options
.SS "Application Options:"
.TP
\fB\-l\fP, \fB\-\-no\-locale\fP
Disable locale
Don't use system locale
.TP
\fB\-V\fP, \fB\-\-version\fP
Display version information
@@ -49,10 +49,17 @@ Don't scan devices on startup
Don't hide non\-identity tabs when SMART is disabled. Useful for debugging.
.TP
\fB\-\-add\-virtual\fP
Load smartctl data from file, creating a virtual drive
Load smartctl data from file, creating a virtual drive. You
can specify this option multiple times.
.TP
\fB\-\-add\-device\fP
Add this device to device list. Useful with \fB\-\-no\-scan\fP to list certain drives only.
Add this device to device list. The format of the device is
\fI<device>::<type>::<extra_args>\fP, where type and extra_args are optional.
This option is useful with \fB\-\-no\-scan\fP to list certain drives only. You
can specify this option multiple times. Example:\fR
.nf
\-\-add\-device /dev/sda \-\-add\-device /dev/twa0::3ware,2 \-\-add\-device '/dev/sdb::::-T permissive'
.fi
.TP
\fB\-\-display\fP=\fIDISPLAY\fP
X display to use
@@ -67,8 +74,8 @@ Disable logging; same as \fB\-\-verbosity\-level\fP 0
Set verbosity level [0\-5]
.PP
.SH COPYRIGHT
Copyright \(co 2008 \- 2009 Alexander Shaduri <ashaduri \'at\' gmail.com>
Copyright \(co 2008 \- 2012 Alexander Shaduri <ashaduri \'at\' gmail.com>
.PP
.SH AUTHOR
This manual page was originally written by Giuseppe Iuculano
<giuseppe@iuculano.it>, for the Debian project.
<giuseppe@iuculano.it> for the Debian project.
+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 GSmartControl developers -->
<component type="desktop">
<id>gsmartcontrol</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0 and GPL-3.0</project_license>
<name>GSmartControl</name>
<summary>Hard Disk and SSD Health Inspection</summary>
<description>
<p>
GSmartControl is a graphical user interface for smartctl, which is a tool for
querying and controlling SMART (Self-Monitoring, Analysis, and Reporting
Technology) data in hard disk and solid-state drives. It allows you to inspect
the drive's SMART data to determine its health, as well as run various tests
on it.
</p>
</description>
<launchable type="desktop-id">gsmartcontrol.desktop</launchable>
<url type="homepage">http://gsmartcontrol.sourceforge.net</url>
<screenshots>
<screenshot type="default">
<caption>Main window</caption>
<image>http://gsmartcontrol.sourceforge.net/home/images/main_ok.png</image>
</screenshot>
<screenshot>
<caption>Drive identity information</caption>
<image>http://gsmartcontrol.sourceforge.net/home/images/info_identity.png</image>
</screenshot>
<screenshot>
<caption>Attribute list of a failing drive</caption>
<image>http://gsmartcontrol.sourceforge.net/home/images/info_failing.png</image>
</screenshot>
</screenshots>
</component>
@@ -8,9 +8,9 @@ Categories=System;Monitor;
Name=GSmartControl
# short description, usually shown in parentheses after Name
GenericName=Hard Disk Health Inspection
GenericName=Hard Disk and SSD Health Inspection
# tooltip
Comment=Monitor and control SMART data on hard disks
Comment=Monitor and control SMART data on hard disk and solid-state drives
# If it's a name only, it looks for "name.[png|xpm]" file in
# $XDG_DATA_DIRS/icons and /usr/share/pixmaps.
@@ -24,6 +24,3 @@ Icon=gsmartcontrol
# Run with root permissions.
Exec="@prefix@/bin/gsmartcontrol-root"
# Build service rpmlint gives errors without this
X-SuSE-translate=false

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

@@ -1,12 +1,12 @@
GSmartControl - Hard disk drive health inspection tool
GSmartControl - Hard disk drive and SSD health inspection tool
Version @VERSION@
The latest version of this distribution, as well as the source code of
GSmartControl, can be found at
http://gsmartcontrol.berlios.de
http://gsmartcontrol.sourceforge.net
and
http://developer.berlios.de/project/showfiles.php?group_id=10075
https://sourceforge.net/projects/gsmartcontrol/files/
You need GTK+ for Windows Runtime package to use this program. You can get one
at http://gtk-win.sf.net (you must download at least version 2.16.6-2010-02-21
@@ -20,9 +20,9 @@ binary was compiled for 32-bit Windows, and should work on both 32-bit and
64-bit Windows. The binary was statically compiled against Gtkmm
(http://www.gtkmm.org/) and related libraries, and PCRE (http://www.pcre.org/).
* Smartctl binaries (from smartmontools 5.41, http://smartmontools.sf.net/)
* Smartctl binaries (from smartmontools 6.5, http://smartmontools.sf.net/)
- smartctl-nc.exe (compiled without console output), smartctl.exe (compiled
with console output).
with console output), update-smart-drivedb.exe (drive database updater).
The combined distribution is multi-licensed under GNU GPL versions 2 and 3.
@@ -1,12 +1,12 @@
GSmartControl - Hard disk drive health inspection tool
GSmartControl - Hard disk drive and SSD health inspection tool
Version @VERSION@
The latest version of this distribution, as well as the source code of
GSmartControl, can be found at
http://gsmartcontrol.berlios.de
http://gsmartcontrol.sourceforge.net
and
http://developer.berlios.de/project/showfiles.php?group_id=10075
https://sourceforge.net/projects/gsmartcontrol/files/
This distribution includes:
@@ -16,9 +16,9 @@ binary was compiled for 32-bit Windows, and should work on both 32-bit and
64-bit Windows. The binary was statically compiled against Gtkmm
(http://www.gtkmm.org/) and related libraries, and PCRE (http://www.pcre.org/).
* Smartctl binaries (from smartmontools 5.41, http://smartmontools.sf.net/)
* Smartctl binaries (from smartmontools 6.5, http://smartmontools.sf.net/)
- smartctl-nc.exe (compiled without console output), smartctl.exe (compiled
with console output).
with console output), update-smart-drivedb.exe (drive database updater).
* GTK+ for Windows Runtime package (@GTK_INSTALLER_NAME@)
from http://gtk-win.sf.net, either in original or unpacked form.
@@ -13,7 +13,7 @@
!define PRODUCT_NAME "GSmartControl"
!define PRODUCT_NAME_SMALL "gsmartcontrol"
!define PRODUCT_PUBLISHER "Alexander Shaduri"
!define PRODUCT_WEB_SITE "http://gsmartcontrol.berlios.de"
!define PRODUCT_WEB_SITE "http://gsmartcontrol.sourceforge.net"
;!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\AppMainExe.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
@@ -158,6 +158,7 @@ SectionIn 1 RO
; File *.dll
File smartctl-nc.exe
File smartctl.exe
File update-smart-drivedb.exe
; Include the "doc" directory completely, excluding the file we're not using (e.g. the -nogtk file in gtk installer).
!ifdef NO_GTK
@@ -168,7 +169,7 @@ SectionIn 1 RO
; Add Shortcuts (this inherits the exe's run permissions)
CreateShortCut "$SMPROGRAMS\GSmartControl.lnk" "$INSTDIR\gsmartcontrol.exe" "" \
"$INSTDIR\gsmartcontrol.ico" "" SW_SHOWNORMAL "" "GSmartControl - Hard disk drive health inspection tool"
"$INSTDIR\gsmartcontrol.ico" "" SW_SHOWNORMAL "" "GSmartControl - Hard disk drive and SSD health inspection tool"
SectionEnd
@@ -300,7 +301,7 @@ FunctionEnd
; Section descriptions
!ifndef NO_GTK ; this page is shown only when using gtk
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecMain} "GSmartControl - hard disk drive health inspection tool"
!insertmacro MUI_DESCRIPTION_TEXT ${SecMain} "GSmartControl - hard disk drive and SSD health inspection tool"
!insertmacro MUI_DESCRIPTION_TEXT ${SecGtkPrivate} "GTK+ libraries, needed by GSmartControl. \
This will install a private version of GTK+, usable only by GSmartControl."
!insertmacro MUI_DESCRIPTION_TEXT ${SecGtkPublic} "GTK+ libraries, needed by GSmartControl. \
@@ -400,15 +401,29 @@ Section Uninstall
; Delete "$INSTDIR\*.dll"
Delete "$INSTDIR\smartctl-nc.exe"
Delete "$INSTDIR\smartctl.exe"
Delete "$INSTDIR\update-smart-drivedb.exe"
; update-smart-drivedb may leave these
Delete "$INSTDIR\drivedb.h"
Delete "$INSTDIR\drivedb.h.new"
Delete "$INSTDIR\drivedb.h.old"
Delete "$INSTDIR\drivedb.h.error"
Delete "$INSTDIR\drivedb.h.lastcheck"
RMDir /r "$INSTDIR\doc"
; leftover from gtk
RMDir /r "$INSTDIR\share"
; clean up generated stuff
Delete "$INSTDIR\*stdout.txt"
Delete "$INSTDIR\*stderr.txt"
RMDir "$INSTDIR" ; only if empty
; For some reason, sometimes it's not deleted in the sections, so do it here.
Delete "$INSTDIR\${GTK_INSTALLER_EXE}"
!ifndef NO_GTK
StrCmp $gtk_mode "private" skip_exe_PATH_remove
!endif

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 766 B

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 766 B

@@ -1,21 +1,21 @@
Source: gsmartcontrol
Section: utils
Priority: extra
Homepage: http://gsmartcontrol.berlios.de/
Homepage: http://gsmartcontrol.sourceforge.net/
Maintainer: Alexander Shaduri <ashaduriREMOVETHIS@gmail.com>
# technically, we don't need libglademm if gtkmm >= 2.12, but it won't get
# into Depends if it's not needed, so let's leave it here.
# libglademm is also needed if libgtkmm-2.4 < 2.12, but don't write it
# here - newer distributions don't contain it.
Build-Depends: debhelper (>= 5), autotools-dev,
libpcre3-dev, libgtkmm-2.4-dev (>= 2.6.0), libglademm-2.4-dev
libpcre3-dev, libgtkmm-2.4-dev (>= 2.6.0)
Standards-Version: 3.7.3
Package: gsmartcontrol
Architecture: any
#Depends: ${shlibs:Depends}, ${misc:Depends}, smartmontools, menu
Depends: ${shlibs:Depends}, smartmontools, menu
Description: Hard disk drive health inspection tool
Description: Hard disk drive and SSD health inspection tool
GSmartControl is a graphical user interface for smartctl (from smartmontools
package), which is a tool for querying and controlling SMART
(Self-Monitoring, Analysis, and Reporting Technology) data on modern hard
disk drives. It allows you to inspect the drive's SMART data to determine its
health, as well as run various tests on it.
disk and solid-state drives. It allows you to inspect the drive's SMART data
to determine its health, as well as run various tests on it.
@@ -1,11 +1,11 @@
This package was debianized by Alexander Shaduri <ashaduri 'at' gmail.com> on
Sat, 15 Nov 2008 00:12:04 +0400.
It was downloaded from <http://gsmartcontrol.berlios.de/>
It was downloaded from <http://gsmartcontrol.sourceforge.net/>
Copyright:
Copyright (C) 2008 - 2010 Alexander Shaduri <ashaduri 'at' gmail.com>
Copyright (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License:
@@ -27,6 +27,6 @@ On Debian systems, the complete text of the GNU General
Public Licenses can be found in `/usr/share/common-licenses/GPL-2' and
`/usr/share/common-licenses/GPL-3'.
The Debian packaging is (C) 2008 - 2010 Alexander Shaduri <ashaduri 'at' gmail.com> and
The Debian packaging is (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com> and
is licensed under the GPLv2 and GPLv3, see above.
@@ -1,4 +1,4 @@
?package(gsmartcontrol):needs="X11" section="Applications/System/Hardware"\
title="GSmartControl" command="/usr/bin/gsmartcontrol-root"\
longtitle="Hard Disk Health Inspection"\
longtitle="Hard Disk and SSD Health Inspection"\
icon="/usr/share/pixmaps/gsmartcontrol.xpm"
+35
View File
@@ -0,0 +1,35 @@
/**************************************************************************
Copyright:
(C) 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
// This file is for generating documentation only. Do NOT include it.
/// \file
/// \author Alexander Shaduri
/**
\mainpage GSmartControl Index
\section intro_section Introduction
This is GSmartControl internal documentation.
*/
// Group definitions and titles.
/**
\addtogroup applib Application-Specific Components
\addtogroup applib_tests Tests of Application-Specific Components
\addtogroup hz HZ Common System Components
\addtogroup hz_tests Tests for HZ Common System Components
\addtogroup libdebug LibDebug Flexible Debug Logging
\addtogroup libdebug_tests Tests for LibDebug Flexible Debug Logging
\addtogroup rmn Resource Manager
\addtogroup rmn_tests Tests for Resource Manager
\addtogroup rconfig Resource Manager-Based Configuration
\addtogroup rconfig_tests Tests for Resource Manager-Based Configuration
\addtogroup gsc GSmartControl Application
*/
@@ -1,7 +1,7 @@
#!/bin/bash
############################################################################
# Copyright:
# (C) 2008 - 2010 Alexander Shaduri <ashaduri 'at' gmail.com>
# (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com>
# License: See LICENSE_zlib.txt file
############################################################################
@@ -1,13 +1,13 @@
Name: gsmartcontrol
Version: @VERSION@
Release: 1as
License: GPLv2, GPLv3
Url: http://gsmartcontrol.berlios.de
License: GPL-2.0 AND GPL-3.0
Url: http://gsmartcontrol.sourceforge.net
Vendor: Alexander Shaduri <ashaduri 'at' gmail.com>
Packager: Alexander Shaduri <ashaduri 'at' gmail.com>
# Packager: Alexander Shaduri <ashaduri 'at' gmail.com>
Source: gsmartcontrol-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Summary: GSmartControl - Hard Disk Health Inspection Tool
Summary: GSmartControl - Hard Disk Drive and SSD Health Inspection Tool
%if 0%{?mandriva_version}
Group: System/Kernel and hardware
@@ -15,12 +15,6 @@ Group: System/Kernel and hardware
Group: Hardware/Other
%endif
# Support build service rpmlint. Disabled - the build service
# stopped recognizing the flag for some architectures.
# %if 0%{?opensuse_bs} && 0%{?suse_version} >= 1010
# Support: rpmlint-bs
# %endif
# Dependencies for various distributions. The actual deps are:
# smartmontools, pcre, (gtkmm2 >= 2.12 || (gtkmm2 >= 2.6.0 && libglademm >= 2.4.0))
@@ -46,6 +40,11 @@ Requires: smartmontools, pcre, gtkmm24 >= 2.6.0, libglademm >= 2.4.0
BuildRequires: gcc-c++, libstdc++-devel, pcre-devel, gtkmm24-devel >= 2.6.0, libglademm-devel >= 2.4.0
%endif
%endif
BuildRequires: update-desktop-files
%if 0%{?suse_version} >= 1030
BuildRequires: fdupes
%endif
%endif
@@ -62,10 +61,10 @@ Requires: smartmontools, pcre, gtkmm24 >= 2.6.0, libglademm24 >= 2.4.0
BuildRequires: gcc-c++, pcre-devel, gtkmm24-devel >= 2.6.0, libglademm24-devel >= 2.4.0
%endif
# Fedora doesn't include gnomesu or anything similar except beesu (since 11), so force it.
# usermode-gtk is for consolehelper-gtk (optional for beesu, needed for GUI auth).
%if 0%{?fedora_version} >= 11
Requires: beesu, usermode-gtk
# Fedora with consolehelper.
# usermode-gtk is for consolehelper-gtk.
%if 0%{?fedora_version}
Requires: usermode-gtk
%endif
%endif
@@ -89,8 +88,9 @@ BuildRequires: gcc-c++, gcc-cpp, pcre-devel, gtkmm2.4-devel >= 2.6.0, libglademm
%description
GSmartControl is a graphical user interface for smartctl, which is a tool for
querying and controlling SMART (Self-Monitoring, Analysis, and Reporting
Technology) data in hard disk drives. It allows you to inspect the drive's
SMART data to determine its health, as well as run various tests on it.
Technology) data in hard disk and solid-state drives. It allows you to inspect
the drive's SMART data to determine its health, as well as run various tests
on it.
%prep
@@ -104,21 +104,80 @@ SMART data to determine its health, as well as run various tests on it.
%build
# Set up for parallel builds
numprocs=`egrep -c ^cpu[0-9]+ /proc/stat || :`
if [ "$numprocs" = "0" ]; then
numprocs=1
fi
make -j$numprocs
# make
#numprocs=`grep -E -c ^cpu[0-9]+ /proc/stat || :`
#if [ "$numprocs" = "0" ]; then
# numprocs=1
#fi
#make -j$numprocs
make %{?_smp_mflags}
%install
# %makeinstall
# %%makeinstall
make DESTDIR=%buildroot install-strip
# Remove the icon cache file "make install" generates, to avoid package conflicts.
rm -f $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/icon-theme.cache
%if 0%{?suse_version}
%suse_update_desktop_file -n %{name}
# There are some png file duplicates, hardlink them.
%if 0%{?suse_version} >= 1030
%fdupes
%endif
# We install icons, so this is needed.
%if 0%{?suse_version} >= 1140
%post
%icon_theme_cache_post
%postun
%icon_theme_cache_postun
%endif
# endif suse
%endif
%if 0%{?fedora_version}
# We still retain gsmartcontrol-root for consistency with other distributions.
# Make the desktop file run gsmartcontrol instead of gsmartcontrol-root
sed "s|gsmartcontrol-root|gsmartcontrol|g" %{buildroot}%{_datadir}/applications/gsmartcontrol.desktop > %{buildroot}%{_datadir}/applications/gsmartcontrol.desktop.new
mv -f %{buildroot}%{_datadir}/applications/gsmartcontrol.desktop.new %{buildroot}%{_datadir}/applications/gsmartcontrol.desktop
# The rest is taken from the official fedora spec:
# http://pkgs.fedoraproject.org/cgit/gsmartcontrol.git/tree/
# Set up for console-helper
mkdir -p %{buildroot}%{_sbindir}
# Add a copy as "gsmartcontrol-noroot", since gsmartcontrol will always
# ask for root password.
cp %{buildroot}%{_bindir}/%{name} %{buildroot}%{_bindir}/%{name}-noroot
mv %{buildroot}%{_bindir}/%{name} %{buildroot}%{_sbindir}/%{name}
ln -s consolehelper %{buildroot}%{_bindir}/%{name}
mkdir -p %{buildroot}%{_sysconfdir}/pam.d
cat <<EOF >%{buildroot}%{_sysconfdir}/pam.d/%{name}
#%%PAM-1.0
auth include config-util
account include config-util
session include config-util
EOF
mkdir -p %{buildroot}%{_sysconfdir}/security/console.apps
cat <<EOF >%{buildroot}%{_sysconfdir}/security/console.apps/%{name}
USER=root
PROGRAM=/usr/sbin/gsmartcontrol
SESSION=true
EOF
# endif fedora
%endif
%if 0%{?mandriva_version}
desktop-file-install --vendor="" \
@@ -137,29 +196,23 @@ rm -rf %buildroot
%defattr(-,root,root)
%attr(0755,root,root) %{_bindir}/*
# %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/*
# %%attr(0644,root,root) %%config(noreplace) %%{_sysconfdir}/*
%doc %{_datadir}/doc/gsmartcontrol
%doc %{_mandir}/man1/*
%{_datadir}/gsmartcontrol
# %{_datadir}/gsmartcontrol/*
# %%{_datadir}/gsmartcontrol/*
%{_datadir}/applications/*.desktop
%{_datadir}/metainfo
%{_datadir}/metainfo/*.appdata.xml
%{_datadir}/icons/*
%{_datadir}/pixmaps/*
%if 0%{?fedora_version}
%config(noreplace) %{_sysconfdir}/pam.d/%{name}
%config(noreplace) %{_sysconfdir}/security/console.apps/%{name}
%{_sbindir}/gsmartcontrol
%endif
%changelog
* Fri Dec 10 2010 Alexander Shaduri <ashaduri 'at' gmail.com>
- Fixes for Fedora 14.
* Fri Nov 14 2008 Alexander Shaduri <ashaduri 'at' gmail.com>
- Updated .spec file to incorporate changes from the official Mandriva package.
* Mon Oct 06 2008 Alexander Shaduri <ashaduri 'at' gmail.com>
- Updated .spec file to support OpenSUSE < 10.3, Fedora and friends,
Mandriva (for OpenSUSE Build Service).
* Mon Sep 15 2008 Alexander Shaduri <ashaduri 'at' gmail.com>
- Initial .spec file.
@@ -1,97 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef APP_GTKMM_UTILS_H
#define APP_GTKMM_UTILS_H
#include <string>
#include <gtkmm/widget.h>
#include <gtkmm/treeviewcolumn.h>
#include <gtkmm/treemodelcolumn.h>
#include <gtkmm/treeview.h>
#include <gtkmm/combobox.h>
#include <gtkmm/cellrenderertext.h>
#include <gtkmm/iconview.h>
#include <gtkmm/liststore.h>
#include <gtkmm/icontheme.h> // must include (even if gtkmm.h is included) for older gtkmm (at least 2.6, but not 2.12)
#include "hz/down_cast.h"
// Note: This works only if the column has custom widget set.
Gtk::Widget* app_gtkmm_get_column_header(Gtk::TreeViewColumn& column);
// Read column header text and create a label with that text, set it as column's custom widget.
Gtk::Widget* app_gtkmm_labelize_column(Gtk::TreeViewColumn& column);
// unset model on treeview, cross-gtkmm-version.
void app_gtkmm_treeview_unset_model(Gtk::TreeView* treeview);
// unset model on combobox (there's no straight way to do it in gtkmm, I think)
void app_gtkmm_combobox_unset_model(Gtk::ComboBox* box);
// A wrapper around set_tooltip_*() for portability across different gtkmm versions.
void app_gtkmm_set_widget_tooltip(Gtk::Widget& widget,
const Glib::ustring& tooltip_text, bool use_markup = false);
// A portable wrapper around TreeView::set_tooltip_column().
void gtkmm_set_treeview_tooltip_column(Gtk::TreeView* treeview,
Gtk::TreeModelColumn<Glib::ustring>& col_tooltip);
// A portable wrapper around IconView::set_tooltip_column().
void gtkmm_set_iconview_tooltip_column(Gtk::IconView* iconview,
Gtk::TreeModelColumn<Glib::ustring>& col_tooltip, Glib::RefPtr<Gtk::ListStore> model);
// Convenience function for creating a TreeViewColumn .
template<typename T> inline
int app_gtkmm_create_tree_view_column(Gtk::TreeModelColumn<T>& mcol, Gtk::TreeView& treeview,
const Glib::ustring& title, const Glib::ustring& tooltip_text, bool sortable = false, bool cell_markup = false)
{
int num_tree_cols = treeview.append_column(title, mcol);
Gtk::TreeViewColumn* tcol = treeview.get_column(num_tree_cols - 1);
if (tcol) {
if (sortable)
tcol->set_sort_column(mcol);
app_gtkmm_labelize_column(*tcol);
tcol->set_reorderable(true);
tcol->set_resizable(true);
}
Gtk::Widget* header = app_gtkmm_get_column_header(*tcol);
if (header)
app_gtkmm_set_widget_tooltip(*header, tooltip_text);
if (cell_markup) {
Gtk::CellRendererText* cr_type = hz::down_cast<Gtk::CellRendererText*>(treeview.get_column_cell_renderer(num_tree_cols - 1));
if (cr_type) { // may not be true if it's not Text (unless static_cast is used, in which case we're screwed)
treeview.get_column(num_tree_cols - 1)->clear_attributes(*cr_type); // clear "text" attribute. "markup" won't work without this.
treeview.get_column(num_tree_cols - 1)->add_attribute(cr_type->property_markup(), mcol); // render col_type as markup.
}
}
return num_tree_cols;
}
bool app_gtkmm_icon_theme_has_icon(Glib::RefPtr<Gtk::IconTheme> theme,
const Glib::ustring& icon_name, int size);
#endif
-312
View File
@@ -1,312 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef APP_CMDEX_H
#define APP_CMDEX_H
#include <string>
#include <glib.h>
#include "hz/process_signal.h" // hz::SIGNAL_*
#include "hz/error_holder.h"
#include "hz/sync.h" // hz::SyncPolicyNone
/*
There are two ways to detect when the command exits:
1. Add a callback to signal_exited.
2. Manually poll stopped_cleanup_needed() (from the same thread).
In both cases, stopped_cleanup() must be called afterwards
(from the main thread).
*/
// inheriting from sigc::trackable automatically disconnects this class's
// slots upon destruction.
class Cmdex : public hz::ErrorHolder<hz::SyncPolicyNone> {
public:
using hz::ErrorHolder<hz::SyncPolicyNone>::ptr_error_list_t; // auto-deleting container
using hz::ErrorHolder<hz::SyncPolicyNone>::error_list_t;
typedef std::string (*exit_status_translator_func_t)(int, void*);
typedef void (*exited_callback_func_t)(void*);
Cmdex(
// exit_status_translator_func_t translator_func,
exited_callback_func_t exited_cb = NULL, void* exited_cb_data = NULL
)
: running_(false), kill_signal_sent_(0), child_watch_handler_called_(false),
pid_(0), waitpid_status_(0),
timer_(g_timer_new()),
event_source_id_term(0), event_source_id_kill(0),
fd_stdout_(0), fd_stderr_(0), channel_stdout_(0), channel_stderr_(0),
channel_stdout_buffer_size_(100 * 1024), channel_stderr_buffer_size_(10 * 1024), // 100K and 10K
event_source_id_stdout_(0), event_source_id_stderr_(0),
translator_func_(0), translator_func_data_(0),
exited_callback_(exited_cb), exited_callback_data_(exited_cb_data)
{ }
// Please don't destroy this object unless the child has exited. It will leak stuff
// and possibly crash, etc... .
~Cmdex()
{
// This will help if object is destroyed after the command has exited, but before
// stopped_cleanup() has been called.
stopped_cleanup();
g_timer_destroy(timer_);
// no need to destroy the channels - stopped_cleanup() calls
// cleanup_members(), which deletes them.
}
// Call before execute.
// Note: The command and the arguments _must_ be shell-escaped.
// Use g_shell_quote() or Glib::shell_quote(). Note that each argument
// must be escaped separately.
void set_command(const std::string& command_exec, const std::string& command_args)
{
command_exec_ = command_exec;
command_args_ = command_args;
}
// launch the command.
bool execute();
// send SIGTERM(15) (terminate).
// use after execute(). using it after the command has exited has no effect.
bool try_stop(hz::signal_t sig = hz::SIGNAL_SIGTERM);
// Send SIGKILL(9) (kill). This signal cannot be overridden in child process.
// use after execute(). using it after the command has exited has no effect.
bool try_kill()
{
return try_stop(hz::SIGNAL_SIGKILL);
}
// set a timeout (since call to this function) to terminate, kill or both (use 0 to ignore the parameter).
// the timeouts will be unset automatically when the command exits.
// This has an effect only if the command is running (after execute()).
void set_stop_timeouts(int term_timeout_msec = 0, int kill_timeout_msec = 0);
// Unset timeouts. This will stop the timeout counters.
// This has an effect only if the command is running (after execute()).
void unset_stop_timeouts();
// If stopped_cleanup_needed() returned true, call this. The command
// should be exited by this time. Must be called before the next execute().
void stopped_cleanup();
// Returns true if command has stopped.
// Call repeatedly in a waiting function, after execute(). When returns true, call stopped_cleanup().
bool stopped_cleanup_needed()
{
return (child_watch_handler_called_);
}
// The process is running. Note that if this returns false, it doesn't mean that
// the io channels have been closed or that the data may be read safely. Poll
// stopped_cleanup_needed() instead.
bool is_running() const
{
return running_;
}
// Call this before execution. There is a race-like condition - when the command
// outputs something, the io channel reads it from fd to its buffer and the event
// source callback is called. If the command dies, the io channel callback reads
// the remaining data to the channel buffer.
// Since the event source callbacks (which read from the buffer and empty it)
// happen rather sporadically (from the glib loop), the buffer may not get read and
// emptied at all (before the command exits). This is why it's necessary to have
// a buffer size which potentially can hold _all_ the command output.
// A way to fight this is to increase event source priority (which may not help).
// Another way is to delay the command exit so that the event source callback
// catches on and reads the buffer.
// Use 0 to ignore the parameter. Call before execute().
void set_buffer_sizes(int stdout_buffer_size = 0, int stderr_buffer_size = 0)
{
if (stdout_buffer_size)
channel_stdout_buffer_size_ = stdout_buffer_size; // 100K by default
if (stderr_buffer_size)
channel_stderr_buffer_size_ = stderr_buffer_size; // 10K by default
}
// If stdout_make_str_as_available_ is false, call this after stopped_cleanup(),
// before next execute(). If it's true, you may call this before the command has
// stopped, but it will decrease performance significantly.
std::string get_stdout_str(bool clear_existing = false)
{
// debug_out_dump("app", str_stdout_);
if (clear_existing) {
std::string ret = str_stdout_;
str_stdout_.clear();
return ret;
}
return str_stdout_;
}
// See notes on get_stdout_str().
std::string get_stderr_str(bool clear_existing = false)
{
if (clear_existing) {
std::string ret = str_stderr_;
str_stderr_.clear();
return ret;
}
return str_stderr_;
}
// Return execution time, in seconds. Call after execute().
double get_execution_time()
{
gulong microsec = 0;
return g_timer_elapsed(timer_, &microsec);
}
// this will disconnect earlier slots. Call before execute().
void set_exit_status_translator(exit_status_translator_func_t func, void* user_data)
{
translator_func_ = func;
translator_func_data_ = user_data;
}
// You can use stopped_cleanup_needed() polling instead.
void set_exited_callback(exited_callback_func_t func, void* user_data)
{
exited_callback_ = func;
exited_callback_data_ = user_data;
}
// these are sorta-private
// for passing to callback
enum channel_t {
channel_type_stdout,
channel_type_stderr
};
// Callbacks (Note: These are called by the real callbacks)
static void on_child_watch_handler(GPid arg_pid, int waitpid_status, gpointer data);
static gboolean on_channel_io(GIOChannel* source,
GIOCondition cond, Cmdex* self, channel_t type);
private:
void cleanup_members()
{
kill_signal_sent_ = 0;
child_watch_handler_called_ = false;
pid_ = 0;
waitpid_status_ = 0;
event_source_id_stdout_ = 0;
event_source_id_stderr_ = 0;
fd_stdout_ = 0;
fd_stderr_ = 0;
if (channel_stdout_) {
g_io_channel_shutdown(channel_stdout_, false, NULL);
g_io_channel_unref(channel_stdout_);
channel_stdout_ = 0;
}
if (channel_stderr_) {
g_io_channel_shutdown(channel_stderr_, false, NULL);
g_io_channel_unref(channel_stderr_);
channel_stderr_ = 0;
}
}
// default command and its args. std::strings, not ustrings.
std::string command_exec_; // binary name. NOT affected by cleanup().
std::string command_args_; // args that always go with binary. NOT affected by cleanup().
bool running_; // child process is running now. NOT affected by cleanup().
int kill_signal_sent_; // command has been sent this signal to terminate
bool child_watch_handler_called_; // true after child_watch_handler callback, before stopped_cleanup().
GPid pid_; // int in Unix, pointer in win32
int waitpid_status_; // after the command is stopped, before cleanup, this will be available.
GTimer* timer_; // keep track of elapsed time since command execution. not used by this class, but may be handy.
int event_source_id_term;
int event_source_id_kill;
int fd_stdout_;
int fd_stderr_;
GIOChannel* channel_stdout_;
GIOChannel* channel_stderr_;
int channel_stdout_buffer_size_; // NOT affected by cleanup().
int channel_stderr_buffer_size_; // NOT affected by cleanup().
int event_source_id_stdout_;
int event_source_id_stderr_;
std::string str_stdout_; // NOT affected by cleanup().
std::string str_stderr_; // NOT affected by cleanup().
// signals
// convert command exit status to message string
exit_status_translator_func_t translator_func_; // NOT affected by cleanup().
void* translator_func_data_;
// "command exited" signal callback.
exited_callback_func_t exited_callback_; // NOT affected by cleanup().
void* exited_callback_data_;
};
#endif
-120
View File
@@ -1,120 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef APP_CMDEX_SYNC_GUI_H
#define APP_CMDEX_SYNC_GUI_H
#include <gtkmm/messagedialog.h>
#include <glibmm/timer.h>
#include "hz/noncopyable.h"
#include "cmdex_sync.h"
// CmdexSync with GUI support
// same as CmdexSync, but with GTK UI stuff.
// this one is noncopyable, because we don't copy the dialogs, etc...
class CmdexSyncGui : public CmdexSync, public hz::noncopyable {
public:
CmdexSyncGui(const std::string& cmd, const std::string& cmdargs)
: CmdexSync(cmd, cmdargs), execution_running_(false), should_abort_(false),
running_dialog_(0), running_dialog_shown_(false), running_dialog_abort_mode_(false)
{
signal_execute_tick.connect(sigc::mem_fun(*this, &CmdexSyncGui::execute_tick_func));
}
CmdexSyncGui()
: execution_running_(false), should_abort_(false),
running_dialog_(0), running_dialog_shown_(false), running_dialog_abort_mode_(false)
{
signal_execute_tick.connect(sigc::mem_fun(*this, &CmdexSyncGui::execute_tick_func));
}
~CmdexSyncGui()
{
delete running_dialog_;
}
virtual bool execute();
// UI callbacks may use this to abort execution.
void set_should_abort()
{
should_abort_ = true;
}
// create a dialog or return already existing one.
// the dialog will be auto-created and displayed on execute().
// you need the function only if you intend to modify it before execute().
Gtk::MessageDialog* create_running_dialog(Gtk::Window* parent = 0, const Glib::ustring& msg = "");
Gtk::MessageDialog* get_running_dialog()
{
return running_dialog_;
}
// this actually shows the dialog only after some time has passed,
// to avoid very quick show/hide.
void show_hide_dialog(bool show);
// called from ticker function in running mode, to show the dialog when requested time elapses.
void update_dialog_show_timer();
// switch the dialog to "Aborting..." mode
void set_running_dialog_abort_mode(bool aborting);
private:
// dialog callback.
void on_running_dialog_response(int response_id)
{
// Try to abort if Cancel was clicked
if (response_id == Gtk::RESPONSE_CANCEL)
set_should_abort();
}
// this function is called every time something happens
// with the executor.
bool execute_tick_func(tick_status_t status);
bool execution_running_;
bool should_abort_; // GUI callbacks may set this to abort the execution
Gtk::MessageDialog* running_dialog_;
bool running_dialog_shown_;
bool running_dialog_abort_mode_;
Glib::Timer running_dialog_timer_;
};
#endif
-143
View File
@@ -1,143 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef SELFTEST_H
#define SELFTEST_H
#include <string>
#include <glibmm/timer.h>
#include "hz/cstdint.h"
#include "hz/intrusive_ptr.h"
#include "storage_device.h"
#include "cmdex_sync.h"
class SelfTest : public hz::intrusive_ptr_referenced {
public:
enum test_t {
type_ioffline, // immediate offline, not supported yet
type_short,
type_long,
type_conveyance
};
static std::string get_test_name(test_t t)
{
switch (t) {
case type_ioffline: return "Immediate Offline Test";
case type_short: return "Short Self-test";
case type_long: return "Extended Self-test";
case type_conveyance: return "Conveyance Self-test";
};
return "[error]";
}
// The drive must have the capabilities present in properties.
SelfTest(StorageDeviceRefPtr drive, test_t type)
: drive_(drive), type_(type)
{
clear();
}
void clear() // clear results of previous test
{
status_ = StorageSelftestEntry::status_unknown;
remaining_percent_ = -1;
last_seen_percent_ = -1;
total_duration_ = -1;
poll_in_seconds_ = -1;
}
bool is_active() const
{
return (status_ == StorageSelftestEntry::status_in_progress);
}
// returns -1 if n/a or unknown.
int8_t get_remaining_percent() const
{
return remaining_percent_;
}
// Returns estimated time of completion for the test. returns -1 if n/a or unknown. 0 is a valid value.
int64_t get_remaining_seconds() const;
test_t get_test_type() const
{
return type_;
}
StorageSelftestEntry::status_t get_status() const
{
return status_;
}
// get the number of seconds after which the caller should call update().
int64_t get_poll_in_seconds() const
{
return poll_in_seconds_;
}
// gets a constant "test duration during idle" capability drive's stored capabilities. -1 if N/A.
int64_t get_min_duration_seconds() const;
// gets the current test type support status from drive's stored capabilities.
bool is_supported() const;
// These return an error message, or empty string if no error.
// start the test
std::string start(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0);
// abort the running test
std::string force_stop(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0);
// update status variables
std::string update(hz::intrusive_ptr<CmdexSync> smartctl_ex = 0);
private:
StorageDeviceRefPtr drive_;
test_t type_;
// status variables:
StorageSelftestEntry::status_t status_;
int8_t remaining_percent_; // 0 means unknown, -1 means n/a. Set to 100 on start.
int8_t last_seen_percent_; // to detect changes in percentage (needed for timer update)
mutable int64_t total_duration_; // total duration needed for the test, as reported by drive. constant. this is a cache.
int64_t poll_in_seconds_; // the user is asked to poll after this much seconds have passed.
Glib::Timer timer_; // counts time since the last percent change
};
typedef hz::intrusive_ptr<SelfTest> SelfTestPtr;
#endif
@@ -1,159 +0,0 @@
/**************************************************************************
Copyright:
(C) 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef STORAGE_DETECTOR_HELPERS_H
#define STORAGE_DETECTOR_HELPERS_H
#include <string>
#include <vector>
#include <glibmm.h>
#include "executor_factory.h"
#include "storage_device.h"
#include "rconfig/rconfig_mini.h"
#include "app_pcrecpp.h"
/// Get number of ports using tw_cli. Return -1 on error.
inline std::string tw_cli_get_drives(const std::string& dev, int scsi_host_no,
std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory, bool use_tw_cli_dev)
{
hz::intrusive_ptr<CmdexSync> executor = ex_factory->create_executor(ExecutorFactory::ExecutorTwCli);
std::string binary;
rconfig::get_data("system/tw_cli_binary", binary);
if (binary.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "tw_cli binary is not set in config.\n");
return "tw_cli binary is not specified in configuration.";
}
std::string command_options = hz::string_sprintf("/c%d show all", scsi_host_no);
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
for (std::size_t i = 0; i < binaries.size(); ++i) {
executor->set_command(Glib::shell_quote(binaries.at(i)), command_options);
if (!executor->execute() || !executor->get_error_msg().empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing tw_cli binary.\n");
} else {
break; // found it
}
}
// any_to_unix is needed for windows
std::string output = hz::string_trim_copy(hz::string_any_to_unix_copy(executor->get_stdout_str()));
if (output.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "tw_cli returned an empty output.\n");
return "tw_cli returned an empty output.";
}
// split to lines
std::vector<std::string> lines;
hz::string_split(output, '\n', lines, true);
pcrecpp::RE port_re = app_pcre_re("/^p([0-9])+[ \\t]+([^\\t\\n]+)/mi");
for (std::size_t i = 0; i < lines.size(); ++i) {
std::string port_str, status;
if (port_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &port_str, &status)) {
if (status != "NOT-PRESENT") {
int port = -1;
hz::string_is_numeric(port_str, port);
if (port != -1) {
if (use_tw_cli_dev) { // use "tw_cli/cx/py" device
drives.push_back(StorageDeviceRefPtr(new StorageDevice("tw_cli/c"
+ hz::number_to_string(scsi_host_no) + "/p" + hz::number_to_string(port))));
} else {
drives.push_back(StorageDeviceRefPtr(new StorageDevice(dev, "3ware," + hz::number_to_string(port))));
}
}
}
}
}
return std::string();
}
/// Return 3ware SCSI host numbers (same as /c switch to tw_cli)
/// \return error string on error
inline std::string tw_cli_get_controllers(ExecutorFactoryRefPtr ex_factory, std::vector<int>& controllers)
{
hz::intrusive_ptr<CmdexSync> executor = ex_factory->create_executor(ExecutorFactory::ExecutorTwCli);
std::string binary;
rconfig::get_data("system/tw_cli_binary", binary);
if (binary.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "tw_cli binary is not set in config.\n");
return "tw_cli binary is not specified in configuration.";
}
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
for (std::size_t i = 0; i < binaries.size(); ++i) {
executor->set_command(Glib::shell_quote(binaries.at(i)), "show");
if (!executor->execute() || !executor->get_error_msg().empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing tw_cli binary.\n");
} else {
break; // found it
}
}
// any_to_unix is needed for windows
std::string output = hz::string_trim_copy(hz::string_any_to_unix_copy(executor->get_stdout_str()));
if (output.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "tw_cli returned an empty output.\n");
return "tw_cli returned an empty output.";
}
// split to lines
std::vector<std::string> lines;
hz::string_split(output, '\n', lines, true);
pcrecpp::RE controller_re = app_pcre_re("/^c([0-9])+[ \\t]+/mi");
for (std::size_t i = 0; i < lines.size(); ++i) {
std::string controller_str;
if (controller_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &controller_str)) {
int controller = -1;
hz::string_is_numeric(controller_str, controller);
if (controller != -1) {
controllers.push_back(controller);
}
}
}
return std::string();
}
#endif
@@ -1,497 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#include "storage_detector_linux.h"
#if defined CONFIG_KERNEL_LINUX
#include <algorithm> // std::find
#include <cstdio> // std::fgets(), std::FILE
#include <cerrno> // ENXIO
#include "hz/debug.h"
#include "hz/fs_path_utils.h"
#include "hz/fs_file.h"
#include "rconfig/rconfig_mini.h"
#include "app_pcrecpp.h"
#include "storage_detector_helpers.h"
namespace {
// Linux 2.6 with udev. Scan /dev/disk/by-id - the directory entries there
// are symlinks to respective /dev devices. Some devices have multiple
// links pointing to them, so unique filter is needed.
/*
Sample listing:
------------------------------------------------------------
# ls -1 /dev/disk/by-id
ata-ST31000340AS_9QJ0FFG7
ata-ST31000340AS_9QJ0FFG7-part1
ata-ST31000340AS_9QJ0FFG7-part2
ata-ST3500630AS_9QG0R38D
ata-ST3500630AS_9QG0R38D-part1
scsi-SATA_ST31000340AS_9QJ0FFG7
scsi-SATA_ST31000340AS_9QJ0FFG7-part1
scsi-SATA_ST31000340AS_9QJ0FFG7-part2
scsi-SATA_ST3500630AS_9QG0R38D
scsi-SATA_ST3500630AS_9QG0R38D-part1
*/
/*
// We don't use udev anymore - not all distros have it, and e.g. Ubuntu
// has it all wrong (two symlinks (sda, sdb) pointing both to sdb).
inline std::string detect_drives_linux_udev_byid(std::vector<std::string>& devices)
{
debug_out_info("app", DBG_FUNC_MSG << "Detecting through device scan directory /dev/disk/by-id...\n");
std::string dev_dir; // this defaults to "/dev/disk/by-id"
if (!rconfig::get_data("system/linux_udev_byid_path", dev_dir) || dev_dir.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Device scan directory path is not set.\n");
return "Device scan directory path is not set.";
}
hz::Dir dir(dev_dir);
std::vector<std::string> all_devices;
if (!dir.list(all_devices, false)) { // this outputs to debug too.
std::string error_msg = dir.get_error_utf8();
if (!dir.exists()) {
debug_out_warn("app", DBG_FUNC_MSG << "Device scan directory doesn't exist.\n");
} else {
debug_out_error("app", DBG_FUNC_MSG << "Cannot list directory entries.\n");
}
return error_msg;
}
std::vector<std::string> blacklist;
blacklist.push_back("/-part[0-9]+$/");
// filter-out the ones with "partN" in them
for (unsigned int i = 0; i < all_devices.size(); ++i) {
std::string entry = all_devices[i];
if (entry == "." || entry == "..")
continue;
// platform blacklist
bool blacked = false;
for (std::vector<std::string>::const_iterator iter = blacklist.begin(); iter != blacklist.end(); ++iter) {
if (app_pcre_match(*iter, entry)) {
blacked = true;
break;
}
}
if (blacked)
continue;
hz::FsPath path = dev_dir + hz::DIR_SEPARATOR_S + all_devices[i];
// those are usually relative links, so find out where they are pointing to.
std::string link_dest;
if (path.get_link_destination(link_dest)) {
path = (hz::path_is_absolute(link_dest) ? link_dest : (dev_dir + hz::DIR_SEPARATOR_S + link_dest));
path.compress(); // compress in case there are ../-s.
}
// skip number-ended devices, in case we couldn't filter out the scan directory correctly
// (it's user-settable after all).
// if (app_pcre_match("/[0-9]+$/", path.str()))
// continue;
if (std::find(devices.begin(), devices.end(), path.str()) == devices.end()) // there may be duplicates
devices.push_back(path.str());
}
return std::string();
}
*/
// Procfs files don't support SEEK_END or ftello() (I think). Anyway, they can't
// be read through hz::File::get_contents, so use this function instead.
inline bool read_proc_file(hz::File& file, std::vector<std::string>& lines)
{
if (!file.open("rb")) // closed automatically
return false; // the error message is in File itself.
std::FILE* fp = file.get_handle();
if (!fp)
return false;
char line[256];
while (std::fgets(line, static_cast<int>(sizeof(line)), fp) != NULL) {
if (*line != '\0')
lines.push_back(line);
}
return true;
}
// Read /proc/partitions file. Return error message on error.
inline std::string read_proc_partitions_file(std::vector<std::string>& lines)
{
std::string path;
if (!rconfig::get_data("system/linux_proc_partitions_path", path) || path.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Partitions file path is not set.\n");
return "Partitions file path is not set.";
}
hz::File file(path);
if (!read_proc_file(file, lines)) { // this outputs to debug too
std::string error_msg = file.get_error_utf8(); // save before calling other file functions
if (!file.exists()) {
debug_out_warn("app", DBG_FUNC_MSG << "Partitions file doesn't exist.\n");
} else {
debug_out_error("app", DBG_FUNC_MSG << "Partitions file exists but cannot be read.\n");
}
return error_msg;
}
return std::string();
}
// Read /proc/partitions file. Return error message on error.
inline std::string read_proc_devices_file(std::vector<std::string>& lines)
{
std::string path;
if (!rconfig::get_data("system/linux_proc_devices_path", path) || path.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Devices file path is not set.\n");
return "Devices file path is not set.";
}
hz::File file(path);
if (!read_proc_file(file, lines)) { // this outputs to debug too
std::string error_msg = file.get_error_utf8(); // save before calling other file functions
if (!file.exists()) {
debug_out_warn("app", DBG_FUNC_MSG << "Devices file doesn't exist.\n");
} else {
debug_out_error("app", DBG_FUNC_MSG << "Devices file exists but cannot be read.\n");
}
return error_msg;
}
return std::string();
}
// Read /proc/partitions file. Return error message on error.
inline std::string read_proc_scsi_scsi_file(std::vector<std::string>& lines)
{
std::string path;
if (!rconfig::get_data("system/linux_proc_scsi_scsi_path", path) || path.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "SCSI file path is not set.\n");
return "SCSI file path is not set.";
}
hz::File file(path);
if (!read_proc_file(file, lines)) { // this outputs to debug too
std::string error_msg = file.get_error_utf8(); // save before calling other file functions
if (!file.exists()) {
debug_out_warn("app", DBG_FUNC_MSG << "SCSI file doesn't exist.\n");
} else {
debug_out_error("app", DBG_FUNC_MSG << "SCSI file exists but cannot be read.\n");
}
return error_msg;
}
return std::string();
}
/// Get number of ports by sequentially running smartctl on each port, until
/// one of the gives an error. Return -1 on error.
inline std::string smartctl_get_drives(const std::string& dev, const std::string& type,
int from, int to, std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
hz::intrusive_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorSmartctl);
for (int i = from; i <= to; ++i) {
std::string type_arg = hz::string_sprintf(type.c_str(), i);
StorageDeviceRefPtr drive(new StorageDevice(dev, type_arg));
// std::string error_msg = execute_smartctl(dev, "-d " + type_arg, "-i", smartctl_ex, output);
std::string error_msg = drive->fetch_basic_data_and_parse(smartctl_ex);
std::string output = drive->get_info_output();
// if we've reached smartctl port limit (older versions may have smaller limits), abort.
if (app_pcre_match("/VALID ARGUMENTS ARE/mi", output)) {
break;
}
if (!error_msg.empty()) {
debug_out_info("app", "Smartctl returned with an error: " << error_msg);
} else {
drives.push_back(drive);
}
}
return std::string();
}
// Linux (tested with 2.4 and 2.6) /proc/partitions. Parses the file, appends /dev to each entry.
// Note that file format changed from 2.4 to 2.6 (some statistics fields moved to another file).
// No /proc/partitions on freebsd, solaris or osx, afaik.
/*
Sample 1 (2.4, devfs, with statistics):
------------------------------------------------------------
# cat /proc/partitions
major minor #blocks name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq
3 0 60051600 ide/host0/bus0/target0/lun0/disc 72159 136746 1668720 467190 383039 658435 8342136 1659840 -429 17038808 22703194
3 1 1638598 ide/host0/bus0/target0/lun0/part1 0 0 0 0 0 0 0 0 0 0 0
3 2 1028160 ide/host0/bus0/target0/lun0/part2 0 0 0 0 0 0 0 0 0 0 0
3 3 3092512 ide/host0/bus0/target0/lun0/part3 0 0 0 0 0 0 0 0 0 0 0
3 4 1 ide/host0/bus0/target0/lun0/part4 0 0 0 0 0 0 0 0 0 0 0
3 5 514048 ide/host0/bus0/target0/lun0/part5 1458 7877 74680 9070 2140 18285 166272 42490 0 10100 52000
------------------------------------------------------------
Sample 2 (2.6):
------------------------------------------------------------
# cat /proc/partitions
major minor #blocks name
1 0 4096 ram0
8 0 156290904 sda
8 1 39070048 sda1
8 2 7560 sda2
8 3 1 sda3
------------------------------------------------------------
Sample 3 (2.6 on nokia n8xx, spaces may be missing):
------------------------------------------------------------
# cat /proc/partitions
major minor #blocks name
31 0 128 mtdblock0
31 1 384 mtdblock1
31 2 2048 mtdblock2
31 3 2048 mtdblock3
31 4 257536 mtdblock4
254 0 3932160 mmcblk0
254 1 3928064 mmcblk0p1
254 8 1966080 mmcblk1
254 9 2007032 mmcblk1p1
*/
inline std::string detect_drives_linux_proc_partitions(std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
debug_out_info("app", DBG_FUNC_MSG << "Detecting through /proc/partitions...\n");
std::vector<std::string> lines;
std::string error_msg = read_proc_partitions_file(lines);
if (!error_msg.empty()) {
return error_msg;
}
std::vector<std::string> blacklist;
// fixme: not sure about how partitions are visible with twa0.
blacklist.push_back("/d[a-z][0-9]+$/"); // sda1, hdb2 - partitions. twa0 and twe1 are drives, not partitions.
blacklist.push_back("/ram[0-9]+$/"); // ramdisks?
blacklist.push_back("/loop[0-9]*$/"); // not sure if loop devices go there, but anyway...
blacklist.push_back("/part[0-9]+$/"); // devfs had them
blacklist.push_back("/p[0-9]+$/"); // partitions are usually marked this way
blacklist.push_back("/md[0-9]*$/"); // linux software raid
blacklist.push_back("/dm-[0-9]*$/"); // linux device mapper
std::vector<std::string> devices;
for (std::size_t i = 0; i < lines.size(); ++i) {
std::string line = hz::string_trim_copy(lines[i]);
if (line.empty() || app_pcre_match("/^major/", line)) // file header
continue;
std::string dev;
if (!app_pcre_match("/^[ \\t]*[^ \\t\\n]+[ \\t]+[^ \\t\\n]+[ \\t]+[^ \\t\\n]+[ \\t]+([^ \\t\\n]+)/", line, &dev) || dev.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Cannot parse line \"" << line << "\".\n");
continue;
}
// platform blacklist
bool blacked = false;
for (std::vector<std::string>::const_iterator iter = blacklist.begin(); iter != blacklist.end(); ++iter) {
if (app_pcre_match(*iter, dev)) {
blacked = true;
break;
}
}
if (blacked)
continue;
std::string path = "/dev/" + dev; // let's just hope the it's /dev.
if (std::find(devices.begin(), devices.end(), path) == devices.end()) // there may be duplicates
devices.push_back(path);
}
hz::intrusive_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorSmartctl);
for (std::size_t i = 0; i < devices.size(); ++i) {
StorageDeviceRefPtr drive(new StorageDevice(devices.at(i)));
drive->fetch_basic_data_and_parse(smartctl_ex);
// 3ware controllers also export themselves as sd*. Smartctl detects that,
// so we can avoid adding them. Older smartctl (5.38) prints "AMCC", newer one
// prints "AMCC/3ware controller". It's better to search it this way.
if (!app_pcre_match("/try adding '-d 3ware,N'/im", drive->get_info_output())) {
drives.push_back(drive);
}
}
return std::string();
}
/**
Detect drives behind 3ware RAID controller.
3ware Linux:
Call as: smartctl -i -d 3ware,[0-127] /dev/twa[0-15] (or twe[0-15])
Use twe* for [678]xxx series, and twa* for 9xxx series.
Note: twe* devices are limited to [0-15] ports (not sure about this).
Note: /dev/tw* devices may not exist, they are created by smartctl on the first run.
Note: for twe*, /dev/sda may also exist (to be used with -d 3ware,N), we should
somehow detect and ignore them.
Note: when specifying non-existent port, either a "Device Read Identity Failed"
error, or a "blank" info may be returned.
Detection:
Grep /proc/devices for "twa" or "twe" (e.g. "251 twa"). Use this for /dev/tw* part.
Grep /proc/scsi/scsi for AMCC or 3ware (LSI too?), use number of matched lines N
for /dev/tw*[0, N-1].
For detecting the number of ports, use "tw_cli /cK show all", K being the controller
scsi number, which is displayed as scsiK in the scsi file.
If there's no tw_cli, we'll have to scan all the ports (up to supported maximum).
This is too slow however, so scan only 24.
Implementation notes: it seems that twe uses "3ware" and twa uses "AMCC".
We can't handle a situation with both twa and twe present, since we don't know
how they will be ordered for tw_cli.
*/
inline std::string detect_drives_linux_3ware(std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
std::vector<std::string> lines;
std::string error_msg = read_proc_devices_file(lines);
if (!error_msg.empty()) {
return error_msg;
}
bool twa_found = false;
bool twe_found = false;
// Check /proc/devices for twa or twe
for (std::size_t i = 0; i < lines.size(); ++i) {
std::string dev;
if (app_pcre_match("/^[ \\t]*[0-9]+[ \\t]+(tw[ae])/", hz::string_trim_copy(lines[i]), &dev)) {
debug_out_dump("app", DBG_FUNC_MSG << "Found " << dev << " entry in devices file.\n");
if (dev == "twa") {
twa_found = true;
} else if (dev == "twe") {
twe_found = true;
} else {
DBG_ASSERT(0); // error in regexp?
}
}
}
if (!twa_found && !twe_found) {
return std::string(); // no controllers
}
lines.clear();
error_msg = read_proc_scsi_scsi_file(lines);
if (!error_msg.empty()) {
return error_msg;
}
int num_controllers = 0;
int last_scsi_host = 0;
pcrecpp::RE host_re = app_pcre_re("^Host: scsi([0-9]+)");
for (std::size_t i = 0; i < lines.size(); ++i) {
// The format of this file is scsi host number on one line, vendor on another.
// debug_out_error("app", "SCSI Line: " << hz::string_trim_copy(lines[i]) << "\n");
std::string scsi_host_str;
if (host_re.PartialMatch(hz::string_trim_copy(lines[i]), &scsi_host_str)) {
// debug_out_dump("app", "SCSI Host " << scsi_host_str << " found.\n");
hz::string_is_numeric(scsi_host_str, last_scsi_host);
}
if (!app_pcre_match("/Vendor: (AMCC)|(3ware) /i", hz::string_trim_copy(lines[i]))) {
continue; // not a supported controller
}
debug_out_dump("app", "Found AMCC/3ware controller in SCSI file, SCSI host " << last_scsi_host << ".\n");
// We can't handle both twa and twe in one system, so assume twa by default.
// We can't map twaX to scsiY, so lets assume the relative order is the same.
std::string dev = std::string("/dev/") + (twa_found ? "twa" : "twe") + hz::number_to_string(num_controllers);
error_msg = tw_cli_get_drives(dev, last_scsi_host, drives, ex_factory, false);
if (!error_msg.empty()) { // no tw_cli
int max_ports = rconfig::get_data<int32_t>("system/linux_max_scan_ports");
max_ports = std::max(max_ports, 23); // 128 smartctl calls are too much (it's too slow). Settle for 24.
error_msg = smartctl_get_drives(dev, "3ware,%d", 0, max_ports, drives, ex_factory);
}
if (!error_msg.empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Couldn't get number of ports on a 3ware controller.\n");
}
++num_controllers;
}
if (num_controllers == 0) {
debug_out_warn("app", DBG_FUNC_MSG << "3ware entry found in devices file, but SCSI file contains no known entries.\n");
}
return error_msg;
}
} // anon ns
std::string detect_drives_linux(std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
std::vector<std::string> error_msgs;
std::string error_msg;
// Disable by-id detection - it's unreliable on broken systems.
// For example, on Ubuntu 8.04, /dev/disk/by-id contains two device
// links for two drives, but both point to the same sdb (instead of
// sda and sdb). Plus, there are no "*-partN" files (not that we need them).
// error_msg = detect_drives_linux_udev_byid(devices); // linux udev
error_msg = detect_drives_linux_proc_partitions(drives, ex_factory);
if (!error_msg.empty()) {
error_msgs.push_back(error_msg);
}
error_msg = detect_drives_linux_3ware(drives, ex_factory);
if (!error_msg.empty()) {
error_msgs.push_back(error_msg);
}
return hz::string_join(error_msgs, "\n");
}
#endif // CONFIG_KERNEL_LINUX
@@ -1,209 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#include "storage_detector_win32.h"
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
#include <windows.h> // CreateFileA(), CloseHandle(), etc...
#include <glibmm.h>
#include "hz/win32_tools.h"
#include "hz/string_sprintf.h"
#include "rconfig/rconfig_mini.h"
#include "app_pcrecpp.h"
#include "storage_detector_helpers.h"
/*
3ware Windows (XP so far, maybe the same under the others):
For 3ware 9xxx only.
Call as: smartctl -i sd[a-z],N
N is port, a-z is logical drive (unit) provided by controller.
N is limited to [0, 31] in the code.
The sd[a-z] device actually exists as \\.\PhysicalDrive[0-N].
No idea how to check if it's 3ware.
Call as: smarctl -i tw_cli/cx/py
This runs tw_cli tool and parses the output; controller x, port y.
tw_cli may be needed for older controllers / drivers.
In tw_cli mode only limited information-gathering is supported.
tw_cli (part of 3DM2) is automatically added to system PATH,
no need to look for it.
3DM2 install can be detected by checking:
HKEY_USERS\.DEFAULT\Software\3ware\3DM2, InstallPath
Another option for detection (whether it's 3ware) would be getting
\\.\PhysicalDrive0 properties, like smartctl does.
Newer (added after 5.39.1) smartctl supports --scan-open, which will give us:
/dev/sda,0 -d ata (opened)
/dev/sda,1 -d ata (opened)
-d 3ware is not needed under Windows. We should treat sda as pd0
and remove pd0 from PhysicalDrive-detected list.
Running smartctl on sda gives almost the same result as on sda,0.
Intel Matrix RAID (since smartmontools SVN version on 2011-02-04):
Call as: "/dev/csmi[0-9],N" where N is the port behind the logical
scsi controller "\\.\Scsi[0-9]:".
The prefix "/dev/" is optional.
This is detected (with /dev/ prefix) by --scan-open.
*/
/**
smartctl --scan-open output for win32 (3ware):
/dev/sda,0 -d ata (opened)
/dev/sda,1 -d ata (opened)
smartctl --scan-open output for linux:
/dev/sda -d sat # /dev/sda [SAT], ATA device
/dev/sdb -d sat # /dev/sdb [SAT], ATA device
/dev/sdc -d sat # /dev/sdc [SAT], ATA device
*/
namespace {
/// Run "smartctl --scan-open" and pick the devices which have
/// a port parameter. We don't pick the others because the may
/// conflict with pd* devices, and we like pd* better than sd*.
std::string get_scan_open_multiport_devices(std::vector<StorageDeviceRefPtr>& drives,
ExecutorFactoryRefPtr ex_factory, std::vector<int>& equivalent_pds)
{
hz::intrusive_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorSmartctl);
std::string smartctl_binary = get_smartctl_binary();
if (smartctl_binary.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "Smartctl binary is not set in config.\n");
return "Smartctl binary is not specified in configuration.";
}
std::string smartctl_def_options;
rconfig::get_data("system/smartctl_options", smartctl_def_options);
if (!smartctl_def_options.empty())
smartctl_def_options += " ";
smartctl_ex->set_command(Glib::shell_quote(smartctl_binary),
smartctl_def_options + "--scan-open");
if (!smartctl_ex->execute() || !smartctl_ex->get_error_msg().empty()) {
debug_out_warn("app", DBG_FUNC_MSG << "Error while executing smartctl binary.\n");
return smartctl_ex->get_error_msg();
}
// any_to_unix is needed for windows
std::string output = hz::string_trim_copy(hz::string_any_to_unix_copy(smartctl_ex->get_stdout_str()));
if (output.empty()) {
debug_out_error("app", DBG_FUNC_MSG << "Smartctl returned an empty output.\n");
return "Smartctl returned an empty output.";
}
// if we've reached smartctl port limit (older versions may have smaller limits), abort.
if (app_pcre_match("/UNRECOGNIZED OPTION/mi", output)) {
return "Smartctl doesn't support --scan-open switch.";
}
std::vector<std::string> lines;
hz::string_split(output, '\n', lines, true);
// /dev/sda,0 -d ata (opened)
// /dev/sda,1 -d ata (opened)
// /dev/sda -d sat # /dev/sda [SAT], ATA device
// /dev/sde,2 -d ata [ATA] (opened)
// we only pick the ones with ports
pcrecpp::RE port_re = app_pcre_re("/^(/dev/[a-z0-9]+),([0-9]+)[ \\t]+-d[ \\t]+([^ \\t\\n]+)/i");
pcrecpp::RE dev_re = app_pcre_re("/^/dev/sd([a-z])$/");
for (std::size_t i = 0; i < lines.size(); ++i) {
std::string dev, port_str, type;
if (port_re.PartialMatch(hz::string_trim_copy(lines.at(i)), &dev, &port_str, &type)) {
std::string letter;
if (dev_re.PartialMatch(dev, &letter)) {
// don't use pd* devices equivalent to these sd* devices.
equivalent_pds.push_back(letter.at(0) - 'a');
}
std::string full_dev = dev + "," + port_str;
drives.push_back(StorageDeviceRefPtr(new StorageDevice(full_dev, type)));
}
}
return std::string();
}
}
// smartctl accepts various variants, the most straight being pdN,
// (or /dev/pdN, /dev/ being optional) where N comes from
// "\\.\PhysicalDriveN" (winnt only).
// http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx
std::string detect_drives_win32(std::vector<StorageDeviceRefPtr>& drives, ExecutorFactoryRefPtr ex_factory)
{
std::vector<int> used_pds;
std::string error_msg = get_scan_open_multiport_devices(drives, ex_factory, used_pds);
bool multiport_found = !drives.empty();
for (int drive_num = 0; ; ++drive_num) {
std::string name = hz::string_sprintf("\\\\.\\PhysicalDrive%d", drive_num);
// If the drive is openable, then it's there.
// NOTE: Administrative privileges are required to open it.
// Yes, CreateFile() is open, not create. Yes, it's silly (ah, win32...).
// We don't use any long/unopenable files here, so use the ANSI version.
HANDLE h = CreateFileA(name.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
// The numbers seem to be consecutive, so break on first invalid.
if (h == INVALID_HANDLE_VALUE)
break;
CloseHandle(h);
if (std::find(used_pds.begin(), used_pds.end(), drive_num) == used_pds.end()) {
std::string dev = hz::string_sprintf("pd%d", drive_num);
drives.push_back(new StorageDevice(dev));
}
}
// If smartctl --scan-open returns no "sd*,port"-style devices,
// check if 3dm2 is installed and execute "tw_cli show" to get
// the controllers, then use the tw_cli variant of smartctl.
if (!multiport_found) {
std::string inst_path;
hz::win32_get_registry_value_string(HKEY_USERS, ".DEFAULT\\Software\\3ware\\3DM2", "InstallPath", inst_path);
if (!inst_path.empty()) {
std::vector<int> controllers;
error_msg = 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) {
// don't specify device, it's ignored in tw_cli mode
tw_cli_get_drives("", controllers.at(i), drives, ex_factory, true);
}
}
}
return std::string();
}
#endif // CONFIG_KERNEL_FAMILY_WINDOWS
-422
View File
@@ -1,422 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef STORAGE_PROPERTY_H
#define STORAGE_PROPERTY_H
#include <string>
#include <vector>
#include <iosfwd>
#include "hz/optional_value.h"
#include "hz/cstdint.h"
// holds one block of "capabilities" subsection
// (only for non-time-interval blocks).
class StorageCapability {
public:
StorageCapability() : flag_value(0x0)
{ }
typedef std::vector<std::string> strvalue_list_t;
std::string reported_flag_value; // original flag value
uint16_t flag_value; // flag value. this is one or sometimes two bytes (maybe more?)
std::string reported_strvalue; // original flag descriptions
strvalue_list_t strvalues;
};
std::ostream& operator<< (std::ostream& os, const StorageCapability& p);
// holds one line of "attributes" subsection
class StorageAttribute {
public:
enum attr_t {
attr_type_unknown,
attr_type_prefail, // reported: Pre-fail
attr_type_oldage // reported: Old_age
};
static std::string get_attr_type_name(attr_t a)
{
switch (a) {
case attr_type_unknown: return "[unknown]";
case attr_type_prefail: return "pre-failure";
case attr_type_oldage: return "old age";
};
return "[error]";
}
enum update_t {
update_type_unknown,
update_type_always, // reported: Always
update_type_offline // reported: Offline
};
static std::string get_update_type_name(update_t a)
{
switch (a) {
case update_type_unknown: return "[unknown]";
case update_type_always: return "continuously";
case update_type_offline: return "on offline data collect.";
};
return "[error]";
}
enum fail_time_t {
fail_time_unknown,
fail_time_none, // reported: -
fail_time_past, // reported: In_the_past
fail_time_now // reported: FAILING_NOW
};
static std::string get_fail_time_name(fail_time_t a)
{
switch (a) {
case fail_time_unknown: return "[unknown]";
case fail_time_none: return "never";
case fail_time_past: return "in the past";
case fail_time_now: return "now";
};
return "[error]";
}
StorageAttribute() : id(-1), attr_type(attr_type_unknown), update_type(update_type_unknown),
when_failed(fail_time_unknown), raw_value_int(0)
{ }
int32_t id; ///< Attribute ID (most vendors agree on this)
std::string flag; ///< Some have it in 0xXXXX format, others in "PO--C-" format (some WD drives?).
hz::OptionalValue<uint8_t> value; ///< Normalized value. May be unset ("---").
hz::OptionalValue<uint8_t> worst; ///< Worst ever value. May be unset ("---").
hz::OptionalValue<uint8_t> threshold; ///< Threshold for normalized value. May be unset ("---").
attr_t attr_type;
update_t update_type;
fail_time_t when_failed;
std::string raw_value; ///< as presented by smartctl (formatted).
int64_t raw_value_int; ///< same as raw_value, but parsed as int. original value is 6 bytes I think.
};
std::ostream& operator<< (std::ostream& os, const StorageAttribute& p);
// holds one error block of "error log" subsection
class StorageErrorBlock {
public:
StorageErrorBlock() : error_num(0), lifetime_hours(0)
{ }
static std::string get_readable_error_types(const std::vector<std::string>& types);
uint32_t error_num; // error number
uint32_t lifetime_hours; // when it occurred
std::string device_state; // "active or idle", standby, etc...
std::vector<std::string> reported_types; // e.g. array of reported strings, e.g. "UNC".
std::string type_more_info; // more info on error type (e.g. "at LBA = 0x0253eac0 = 39054016")
};
std::ostream& operator<< (std::ostream& os, const StorageErrorBlock& b);
// Holds one entry of selftest_log subsection.
// Also, holds "Self-test execution status" capability's "internal" section version.
class StorageSelftestEntry {
public:
enum status_t {
status_unknown, // initial state
status_completed_no_error,
status_aborted_by_host,
status_interrupted,
status_fatal_or_unknown, // error
status_compl_unknown_failure, // error
status_compl_electrical_failure, // error
status_compl_servo_failure, // error
status_compl_read_failure, // error
status_compl_handling_damage, // error
status_in_progress,
status_reserved
};
enum status_severity_t {
severity_none,
severity_warn,
severity_error
};
static std::string get_status_name(status_t s)
{
switch (s) {
case status_unknown: return "[unknown]";
case status_completed_no_error: return "Completed without error";
case status_aborted_by_host: return "Manually aborted";
case status_interrupted: return "Interrupted (host reset)";
case status_fatal_or_unknown: return "Fatal or unknown error";
case status_compl_unknown_failure: return "Completed with unknown failure";
case status_compl_electrical_failure: return "Completed with electrical failure";
case status_compl_servo_failure: return "Completed with servo/seek failure";
case status_compl_read_failure: return "Completed with read failure";
case status_compl_handling_damage: return "Completed: handling damage";
case status_in_progress: return "In progress";
case status_reserved: return "Unknown / reserved state";
};
return "[error]";
}
static status_severity_t get_status_severity(status_t s)
{
switch (s) {
case status_unknown: return severity_none;
case status_completed_no_error: return severity_none;
case status_aborted_by_host: return severity_warn;
case status_interrupted: return severity_warn;
case status_fatal_or_unknown: return severity_error;
case status_compl_unknown_failure: return severity_error;
case status_compl_electrical_failure: return severity_error;
case status_compl_servo_failure: return severity_error;
case status_compl_read_failure: return severity_error;
case status_compl_handling_damage: return severity_error;
case status_in_progress: return severity_none;
case status_reserved: return severity_none;
};
return severity_none;
}
StorageSelftestEntry() : test_num(0), status(status_unknown),
remaining_percent(-1), lifetime_hours()
{ }
std::string get_status_str() const
{
return (status == status_unknown ? status_str : get_status_name(status));
}
// test number. always starts from 1. larger means older or newer, depending on model.
uint32_t test_num; // 0 for capability.
std::string type; // Extended offline, Short offline, Conveyance offline, etc... . capability: unused.
std::string status_str; // Self-test routine in progress, Completed without error, etc... (as reported by log or capability)
status_t status; // same as above, but from enum
int8_t remaining_percent; // %. 0% for completed, 90% for started. -1 if n/a.
uint32_t lifetime_hours; // when it happened. capability: unused.
std::string lba_of_first_error; // "-" or value (format?). capability: unused.
};
std::ostream& operator<< (std::ostream& os, const StorageSelftestEntry& b);
class StorageProperty {
public:
// value types
enum value_type_t {
value_type_unknown, // empty value
value_type_string, // string value
value_type_integer, // int64
value_type_bool, // enabled / disabled, available / not available. passed / not passed.
value_type_time_length, // in seconds. e.g. 300 seconds.
value_type_capability, // for "capabilities" subsection (non-time-interval blocks only)
value_type_attribute, // for "attributes" subsection
value_type_error_block, // for "error_log" subsection
value_type_selftest_entry // for "selftest_log" subsection
};
static std::string get_value_type_name(value_type_t type)
{
switch(type) {
case value_type_unknown: return "empty";
case value_type_string: return "string";
case value_type_integer: return "integer";
case value_type_bool: return "bool";
case value_type_time_length: return "time_length";
case value_type_capability: return "capability";
case value_type_attribute: return "attribute";
case value_type_error_block: return "error_block";
case value_type_selftest_entry: return "selftest_entry";
}
return "[error]";
}
// sections in output
enum section_t {
section_unknown, // use when searching in all sections
section_info, // Short info (--info)
section_data, // SMART DATA
section_internal // internal application-specific data
};
static std::string get_section_name(section_t s)
{
switch(s) {
case section_unknown: return "unknown";
case section_info: return "info";
case section_data: return "data";
case section_internal: return "internal";
}
return "[error]";
}
// subsections in smart data section
enum subsection_t {
subsection_unknown, // use when searching in all subsections
subsection_health, // overall-health (-H, --health)
subsection_capabilities, // General SMART Values, aka Capabilities (-c, --capabilities)
subsection_attributes, // Attributes (-A, --attributes). These need decoding.
subsection_error_log, // Error Log (-l error)
subsection_selftest_log, // Self-test log (-l selftest)
subsection_selective_selftest_log // Selective self-test log and settings
};
static std::string get_subsection_name(subsection_t s)
{
switch(s) {
case subsection_unknown: return "unknown";
case subsection_health: return "health";
case subsection_capabilities: return "capabilities";
case subsection_attributes: return "attributes";
case subsection_error_log: return "error_log";
case subsection_selftest_log: return "selftest_log";
case subsection_selective_selftest_log: return "selective_selftest_log";
}
return "[error]";
}
enum warning_t {
warning_none,
warning_notice, // a known attribute is somewhat disturbing, but no smart error
warning_warn, // smart warning is raised by old-age attribute
warning_alert // smart warning is raised by pre-fail attribute, and similar errors
};
StorageProperty()
: section(section_unknown), subsection(subsection_unknown),
value_type(value_type_unknown), warning(warning_none)
{
// value_from_db = false;
value_integer = 0; // this should nullify all union members
}
bool empty() const // empty object - no value set.
{
return (value_type == value_type_unknown);
}
void dump(std::ostream& os, int internal_offset = 0) const;
std::string format_value(bool add_reported_too = false) const;
std::string get_description(bool clean = false) const
{
if (clean)
return this->description;
return (this->description.empty() ? "No description available" : this->description);
}
void set_description(const std::string& descr)
{
this->description = descr;
}
void set_name(const std::string& rep_name, const std::string& gen_name = "", const std::string& read_name = "")
{
this->reported_name = rep_name;
this->generic_name = (gen_name.empty() ? this->reported_name : gen_name);
this->readable_name = (read_name.empty() ? this->reported_name : read_name);
}
// property name as reported by smartctl.
std::string reported_name;
// property name. may be same as reported_name, or something more program-identifiable.
std::string generic_name;
// property name. may be same as reported_name, or something more user-readable. possibly translatable.
std::string readable_name;
std::string description; // description. for tooltips, etc...
section_t section;
subsection_t subsection;
// bool empty_value; // the property has an empty value
// bool value_from_db; // value retrieved from the database, not the drive
std::string reported_value; // string representation of the value as reported
std::string readable_value; // user-friendly readable representation of value. if empty, use others.
value_type_t value_type;
std::string value_string;
std::string value_version;
union {
int64_t value_integer;
bool value_bool;
uint64_t value_time_length; // always in seconds
};
StorageCapability value_capability;
StorageAttribute value_attribute;
StorageErrorBlock value_error_block;
StorageSelftestEntry value_selftest_entry;
warning_t warning; // warning severity
std::string warning_reason; // reason (displayable)
};
inline std::ostream& operator<< (std::ostream& os, const StorageProperty& p)
{
p.dump(os);
return os;
}
#endif
File diff suppressed because it is too large Load Diff
@@ -1,20 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef STORAGE_PROPERTY_DESCR_H
#define STORAGE_PROPERTY_DESCR_H
#include "storage_property.h"
bool storage_property_autoset_description(StorageProperty& p);
StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p);
#endif
-123
View File
@@ -1,123 +0,0 @@
/**************************************************************************
Copyright:
(C) 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef TW_CLI_EXECUTOR_H
#define TW_CLI_EXECUTOR_H
#include "cmdex.h"
#include "cmdex_sync.h"
/// Executor for tw_cli (3ware utility)
template<class ExecutorSync>
class TwCliExecutorGeneric : public ExecutorSync {
public:
TwCliExecutorGeneric(const std::string& cmd, const std::string& cmdargs)
: ExecutorSync(cmd, cmdargs)
{
this->construct();
}
TwCliExecutorGeneric()
{
this->construct();
}
virtual ~TwCliExecutorGeneric()
{ }
protected:
void construct()
{
ExecutorSync::cmdex_.set_exit_status_translator(&TwCliExecutorGeneric::translate_exit_status, NULL);
this->set_error_header("An error occurred while executing tw_cli:\n\n");
}
static std::string translate_exit_status(int status, void* user_data)
{
return std::string();
}
// import the last error from cmdex_ and clear all errors there
virtual void import_error()
{
Cmdex& cmdex = this->get_command_executor();
cmdex.errors_lock();
Cmdex::error_list_t errors = cmdex.get_errors(false); // these are not clones
hz::ErrorBase* e = 0;
// find the last relevant error.
// note: const_reverse_iterator doesn't work on gcc 3, so don't do it.
for (Cmdex::error_list_t::reverse_iterator iter = errors.rbegin(); iter != errors.rend(); ++iter) {
// ignore iochannel errors, they may mask the real errors
if ((*iter)->get_type() != "giochannel" && (*iter)->get_type() != "custom") {
e = (*iter)->clone();
break;
}
}
cmdex.clear_errors(false); // and clear them
cmdex.errors_unlock();
if (e) { // if error is present, alert the user
on_error_warn(e);
}
}
// The warnings are already printed via debug_* in cmdex.
virtual void on_error_warn(hz::ErrorBase* e)
{
if (!e)
return;
// import the error only if it's relevant.
std::string error_type = e->get_type();
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
if (error_type == "giochannel" || error_type == "custom") {
return;
}
this->set_error_msg(e->get_message());
}
};
typedef TwCliExecutorGeneric<CmdexSync> TwCliExecutor;
typedef hz::intrusive_ptr<TwCliExecutor> TwCliExecutorRefPtr;
typedef TwCliExecutorGeneric<CmdexSyncGui> TwCliExecutorGui;
typedef hz::intrusive_ptr<TwCliExecutorGui> TwCliExecutorGuiRefPtr;
#endif
-106
View File
@@ -1,106 +0,0 @@
/**************************************************************************
Copyright:
(C) 2008 - 2011 Alexander Shaduri <ashaduri 'at' gmail.com>
License: See LICENSE_gsmartcontrol.txt
***************************************************************************/
#ifndef GSC_EXECUTOR_LOG_WINDOW_H
#define GSC_EXECUTOR_LOG_WINDOW_H
#include <vector>
#include <cstddef> // std::size_t
#include <gtkmm/window.h>
#include <gtkmm/liststore.h>
#include <gtkmm/treeselection.h>
#include <gtkmm/treemodelcolumn.h>
#include "applib/app_ui_res_utils.h"
#include "applib/cmdex_sync.h"
// use create() / destroy() with this class instead of new / delete!
class GscExecutorLogWindow : public AppUIResWidget<GscExecutorLogWindow, false> {
public:
// name of glade/ui file without a .glade/.ui extension and quotes
APP_UI_RES_DATA_INIT(gsc_executor_log_window);
// glade/gtkbuilder needs this constructor
GscExecutorLogWindow(BaseObjectType* gtkcobj, const app_ui_res_ref_t& ref_ui);
virtual ~GscExecutorLogWindow()
{ }
// Show this window and select the last entry
void show_last();
protected:
// Data
std::vector<CmdexSyncCommandInfoRefPtr> entries;
Glib::RefPtr<Gtk::ListStore> list_store;
Glib::RefPtr<Gtk::TreeSelection> selection;
Gtk::TreeModelColumn<std::size_t> col_num;
Gtk::TreeModelColumn<std::string> col_command;
Gtk::TreeModelColumn<CmdexSyncCommandInfoRefPtr> col_entry;
void clear_view_widgets(); // clear entries and textviews
// -------------------- Callbacks
// Attached to external source
void on_command_output_received(const CmdexSyncCommandInfo& info);
// ---------- override virtual methods
bool on_delete_event_before(GdkEventAny* e)
{
this->hide(); // hide only, don't destroy
return true; // event handled, don't call default virtual handler
}
// ---------- other callbacks
void on_window_close_button_clicked()
{
this->hide(); // hide only, don't destroy
}
void on_window_save_current_button_clicked();
void on_window_save_all_button_clicked();
void on_clear_command_list_button_clicked();
void on_tree_selection_changed();
};
#endif

Some files were not shown because too many files have changed in this diff Show More