CHANGELOG for smartmontools
-$Id: CHANGELOG 2951 2009-10-08 23:43:46Z samm2 $
+$Id: CHANGELOG 2993 2009-12-04 17:29:50Z chrfranke $
The most recent version of this file is:
http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
<DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
- [AS] Linux: Autodetect DELL PERC and MegaRAID controllers.
- Hiding debug messages coming from megaraid code.
+ [CF] Linux: Add workaround for Adaptec series 2, 5 and 5Z controllers
+ with firmware >= 17380. Patch was provided by Phil Wilson, see:
+ http://linux.adaptec.com/2009/07/24/using-smartmontools-538-with-series-255z-controllers-with-firmware-17380-onwards
+
+ [CF] configure.in: Add '-fno-strict-aliasing' to CXXFLAGS if supported.
+ This suppresses gcc 4.4.1 warnings on Linux and avoids possible
+ unsafe optimizations (ticket #23).
+ Patch was provided by Manfred Schwarb.
+
+ [CF] Avoid truncation of configure arguments in '-V' output.
+
+ [AS] Added USB IDs of WD Passport USB Portable
+
+ [CF] Linux: Fix segfault in 3ware interface (ticket #22).
+
+ [MS] knowndrives.cpp updates:
+ - Hitachi Deskstar 7K2000
+ - Seagate Momentus 7200 FDE.2 series
+
+ [CF] Add USB ID of WD My Passport 070A.
+ knowndrives.cpp update:
+ - WD My Passport hard drive (USB interface)
+
+ [CF] smartd: Write 'worst' attribute value to '.state' file also.
+ This allows to use state persistence with 'raw64' attributes.
+
+ [CF] Rework ATA SMART attribute check in smartctl and smartd.
+ smartd: Ignore normalized attribute value and threshold
+ if 'raw64' or 'hex64' format is selected.
+
+ [CF] Add USB IDs of Iomega LPHD080-0, 2 Genesys Logic bridges and
+ Initio 316000.
+
+ [MS] knowndrives.cpp update: Hitachi Travelstar 5K320 series
+
+ [CF] smartctl: Ignore normalized attribute value and threshold
+ if 'raw64' or 'hex64' format is selected.
+
+ [CF] knowndrives.cpp updates:
+ - add OCZ-Vertex raw64 attributes
+ - add OCZ-Agility
+ Thanks to Marcin Marszalek for the patch.
+
+ [CF] Add '-v ID,hex*' print formats. Fix '-v N,FORMAT,NAME' parsing.
+
+ [CF] Add '-v ID,raw64[,...]' print format based on a patch provided
+ by Marcin Marszalek.
+
+ [CF] Add '-v ID,RAW_FORMAT[,ATTR_NAME]' option. This allows to add new
+ attributes without the need to enhance the '-v' option.
+ Rework attribute name and raw value formatting.
+
+ [CF] Fix auto_ptr initialization in linux_scsi_device::autodetect_open().
+
+ [CF] Remove duplicate function smart_device_list::add().
+ Replace calls with push_back().
+
+ [MS] attribute update:
+ trim attribute names to 23 chars
+
+ [CF] Add smart pointer class template to manage device object pointers.
+ Remove related 'delete' calls and 'try/catch' blocks.
+
+ [CF] do_release: Replace generation of '*.asc' by '*.md5' and '*.sha1'.
+
+ [MS] attribute updates:
+ - change attributes 202,204,205 to the meanings as found in wdidle3.exe
+ retain old entries as comments (possible Fujitsu use)
+ - add attribute 240 as found in Fujitsu MHY2xxxBH
+
+ [MS] attributes updates:
+ - attributes 225, 232 and 233 for Intel X25-E SSD
+ - non-conflicting attributes extracted from wdidle3.exe
+ (thanks to Franc Zabkar and Dan Lukes)
+
+ [CF] Update Windows and ./configure info in INSTALL file.
+
+ [CF] Update 'do_release' script for SVN.
+
+ [MS] knowndrives.cpp updates:
+ - Western Digital MyPassport Essential hard drive (USB interface)
+ - Seagate Momentus 7200.4 series
+ - Western Digital Raptor X
+ - Intel X25-E SSD
+
+ [CF] knowndrives.cpp updates:
+ - New Seagate 7200.11 firmware version
+ - Update IBM link
+
+ [CF] smartctl: Use printf() instead of pout() for exception error
+ messages to avoid access to bogus 'con->dont_print'.
+
+ [CF] smartd: Add missing help texts for '-A', '-B' and '-s'.
+
+ [CF] Add missing check for log page 0x11 support to smartctl
+ '-l sataphy' option.
+
+ [CF] Add USB ID of Freecom Hard Drive XS.
+
+ [AS] Linux: Autodetect DELL PERC and MegaRAID controllers.
+ Hiding debug messages coming from megaraid code.
[AS] Linux: Fixed SATA drives support on megaraid device (see ticket #15).
[AS] FreeBSD: cam_get_umassno rewritten using XPT_PATH_INQ
- [AS] FreeBSD: do not open/close cam device on every request for SCSI
+ [AS] FreeBSD: do not open/close cam device on every request for SCSI
disks. Use com->camdev both for SCSI and ATAPICAM.
[AS] FreeBSD: added support for the ada disks, based on agapon patch
Smartmontools installation instructions
=======================================
-$Id: INSTALL 2925 2009-10-02 20:45:54Z chrfranke $
+$Id: INSTALL 2967 2009-10-23 21:45:56Z chrfranke $
Please also see the smartmontools home page:
http://smartmontools.sourceforge.net/
E) Cygwin
- The code was tested on Cygwin 1.5.7, 1.5.11 and 1.5.18-22. It should
- also work on other recent releases.
+ The code was tested on Cygwin 1.5.25-15 and 1.7.0-62. It should also
+ work on other recent releases.
Release 1.5.15 or later is recommended for Cygwin smartd. Older versions
do not provide syslogd support.
F) Windows
- The code was tested on Windows 98SE, NT4(SP5,SP6), 2000(SP4),
- XP(no SP,SP1a,SP2) and Vista RC 1. It should also work on Windows
- 95(OSR2), 98, ME and 2003.
+ The code was tested on Windows 98SE, ME, NT4(SP5,SP6), 2000(SP4),
+ XP(up to SP3), 2003 and Vista.
+
+ -- Windows 9x/ME
On 9x/ME, only standard (legacy) IDE/ATA devices 0-3 are supported.
The driver SMARTVSD.VXD must be present in WINDOWS\SYSTEM\IOSUBSYS
installation of some versions of Windows is the WINDOWS\SYSTEM folder.
In this case, move SMARTVSD.VXD to WINDOWS\SYSTEM\IOSUBSYS and reboot
(http://support.microsoft.com/kb/265854/en-us).
- SMARTVSD.VXD may also be missing in a new installation
- (http://support.microsoft.com/kb/199886/en-us).
SMARTVSD.VXD relies on the standard IDE port driver ESDI_506.PDR.
If the system uses a vendor specific driver, access of SMART data
- is not possible on 9x/ME. This is the case if e.g. the optional
- "IDE miniport driver" is installed on a system with VIA chipset.
+ is not possible.
Some ATA controllers (e.g. Promise) provided a custom SMARTVSD.VXD
for their Win9x/ME driver. To access SMART data from both the legacy
all occurrences of the string "SMARTVSD" with "SMARTVSE". Then reinstall
the original Windows SMARTVSD.VXD.
- On NT4/2000/XP/2003, ATA or SATA devices are supported if the device
- driver implements the SMART IOCTL.
+ To access SCSI and USB devices, an installed ASPI interface (WNASPI32.DLL)
+ is required. The code was tested with Adaptec Windows ASPI drivers 4.71.2.
+ (http://www.adaptec.com/en-US/support/_eol/scsi_sw/ASPI-4.70/)
+ Links to other ASPI drivers can be found at http://www.nu2.nu/aspi/.
+
+ -- Windows NT4/2000/XP/2003/Vista
- The IDE/ATA read log command (smartctl -l, --log, -a, --all) is
- not supported by the SMART IOCTL of NT4/2000/XP. Undocumented
- and possibly buggy system calls are used for this purpose,
- see WARNINGS file for details.
+ ATA or SATA devices are supported if the device driver implements
+ the SMART IOCTLs or IOCTL_IDE_PASS_THROUGH or IOCTL_ATA_PASS_THROUGH.
+ The ATA SMART READ LOG command (smartctl -l, --log, -a, --all) is not
+ supported if only the SMART IOCTLs are implemented.
- SCSI devices are supported on all versions of Windows. An installed
- ASPI interface (WNASPI32.DLL) is required to access SCSI devices.
- The code was tested with Adaptec Windows ASPI drivers 4.71.2.
- (http://www.adaptec.com/en-US/support/scsi_soft/ASPI/ASPI-4.70/)
- Links to other ASPI drivers can be found at http://www.nu2.nu/aspi/.
+ SCSI and USB devices are accessed through SPTI. Special driver support
+ is not required.
- 3ware 9000 RAID controllers are supported using new features available
+ 3ware 9000 RAID controllers are supported using features available
in the Windows driver release 9.4.0 (3wareDrv.sys 3.0.2.70) or later.
Older drivers provide SMART access to the first physical drive (port)
of each logical drive (unit). If driver support is not available
nodes for 3ware/AMCC controllers, this option ensures that the nodes are created
with correct SELinux file contexts.
--enable-drivedb --disable-drivedb Enables default drive database file '${drivedbdir}/drivedb.h'
---with-drivedbdir ${prefix}/share/smartmontools/drivedb.h Directory for 'drivedb.h' (specifying this option implies --enable-drivedb)
+--with-drivedbdir ${prefix}/share/smartmontools Directory for 'drivedb.h' (implies --enable-drivedb)
--enable-savestates --disable-savestates Enables default smartd state files '${savestates}MODEL-SERIAL.ata.state'
---with-savestates ${prefix}/var/lib/smartmontools/smartd. Prefix for smartd state files (specifying this option implies --enable-savestates)
+--with-savestates ${prefix}/var/lib/smartmontools/smartd. Prefix for smartd state files (implies --enable-savestates)
+--enable-attributelog --disable-attributelog Enables default smartd attribute log files
+--with-attributelog ${prefix}/var/lib/smartmontools/attrlog. Prefix for smartd attribute log files (implies --enable-attributelog)
Here's an example:
If you set --prefix=/home/joe and none of the other four
smartmontools NEWS
------------------
-$Id: NEWS 2956 2009-10-11 00:21:15Z samm2 $
+$Id: NEWS 2989 2009-11-30 20:17:14Z chrfranke $
The most up-to-date version of this file is:
http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
-----------------------------------------------------------
- Sourcecode repository moved from CVS to SVN
- Support for USB devices with Cypress, JMicron and Sunplus USB bridges
-- USB device type autodetection for some devices on Linux,Windows and FreeBSD
- (http://smartmontools.wiki.sourceforge.net/overview_USB-Support)
+- USB device type autodetection for some devices on Linux, Windows and FreeBSD
+ (http://sourceforge.net/apps/trac/smartmontools/wiki/Supported_USB-Devices)
- Support for Areca controllers on Linux
- Support for MegaRAID controllers on Linux
- Support for HighPoint RocketRAID controllers on FreeBSD
Error Log
- smartctl option '-l xselftest' to print ATA SMART Extended Self-test Log
- smartctl option '-l sataphy' to print SATA Phy Event Counters
+- smartctl option '-l sasphy' to print SAS device phy information
- smartctl options '-l gplog,...' and '-l smartlog,...' to print any log page
+- smartctl option '-x' to print all extended info if available
- smartctl prints SCSI load/unload cycle counts
- Improve display of huge raw values of some SMART attributes
- Option '-d sat+TYPE' to use SAT with controllers which require '-d TYPE'
+- Option '-v ID,RAW_FORMAT,ATTR_NAME' to add new vendor specific attributes
+- Support for SSD drives using 64-bit raw attributes
- Many additions to drive database
- New simplified syntax for drive database
- Option '-B FILE' to read drive database from a file
- smartd can now handle attributes 197 and 198 with increasing raw values
- smartd logs changes of self-test execution status
- smartd directive '-n powermode,N' to limit the number of skipped checks
+- smartd flag '!' for '-r' and '-R' directives to log changes as critical
- smartd supports scheduled Selective Self-Tests
-- Self-tests scheduled during downtime are run after next startup
-- Option '-s PREFIX' to store smartd internal state until next startup
-- Configure option to enable the above by default
+- Self-tests scheduled during system downtime or disk standby are run after
+ next startup
+- smartd option '-s PREFIX' to store smartd internal state until next startup
+- smartd option '-A PREFIX' to log attributes at each check cycle
+- Configure options to enable the above by default
- Change to an object oriented interface to access ATA and SCSI devices
- Linux, Win32 and FreeBSD modules migrated to new interface
- Rework of smartd data structures
- Checkin date and SVN revision and optional BUILD_INFO printed in version info
-- Better support for gSmartControl on Windows
+- Better support for GSmartControl on Windows
- SELinux fixes to 3ware device node creation
- Fix CCISS file descriptor leak on FreeBSD
- Compile fixes for Solaris and FreeBSD
TODO list for smartmontools:
-$Id: TODO 2845 2009-07-18 13:25:18Z chrfranke $
+$Id: TODO 2966 2009-10-23 21:05:16Z chrfranke $
USB devices under Linux
-----------------------
Packaging
---------
-Rework 'do_release' script for SVN.
-
Under freebsd and solaris, the following are wrong:
smartd.conf: has linux device paths
smart*.in : man pages have (mostly) linux device paths
#include "utility.h"
#include "dev_ata_cmd_set.h" // for parsed_ata_device
-const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 2928 2009-10-03 16:24:53Z chrfranke $"
+const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 2983 2009-11-14 21:41:41Z chrfranke $"
ATACMDS_H_CVSID;
// for passing global control variables
6 /* 0x0022 WARNING: */
};
-// When you add additional items to this list, you should then:
-// 0 -- update this list
-// 1 -- if needed, modify ataPrintSmartAttribRawValue()
-// 2 - if needed, modify ataPrintSmartAttribName()
-// 3 -- add drive in question into builtin_knowndrives[] table in knowndrives.cpp
-// 4 -- update smartctl.8
-// 5 -- update smartd.8
-// 6 -- do "make smartd.conf.5" to update smartd.conf.5
-// 7 -- update CHANGELOG file
-
-struct vendor_attr_arg_entry
-{
- unsigned char id; // attribute ID, 0 for all
- const char * name; // attribute name
- unsigned char val; // value for attribute defs array
-};
-
-// The order of these entries is (only) relevant for '-v help' output.
-const vendor_attr_arg_entry vendor_attribute_args[] = {
- { 9,"halfminutes", 4},
- { 9,"minutes", 1},
- { 9,"seconds", 3},
- { 9,"temp", 2},
- {192,"emergencyretractcyclect", 1},
- {193,"loadunload", 1},
- {194,"10xCelsius", 1},
- {194,"unknown", 2},
- {197,"increasing", 1},
- {198,"offlinescanuncsectorct", 2},
- {198,"increasing", 1},
- {200,"writeerrorcount", 1},
- {201,"detectedtacount", 1},
- {220,"temp", 1},
- { 0,"raw8", 253},
- { 0,"raw16", 254},
- { 0,"raw48", 255},
-};
-
-const unsigned num_vendor_attribute_args = sizeof(vendor_attribute_args)/sizeof(vendor_attribute_args[0]);
-
// Get ID and increase flag of current pending or offline
// uncorrectable attribute.
-unsigned char get_unc_attr_id(bool offline, const unsigned char * defs,
+unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
bool & increase)
{
unsigned char id = (!offline ? 197 : 198);
- increase = (defs[id] == 1);
+ increase = !!(defs[id].flags & ATTRFLAG_INCREASING);
return id;
}
+#if 0 // TODO: never used
// This are the meanings of the Self-test failure checkpoint byte.
// This is in the self-test log at offset 4 bytes into the self-test
// descriptor and in the SMART READ DATA structure at byte offset
return NULL;
}
}
+#endif
+
+
+// Table of raw print format names
+struct format_name_entry
+{
+ const char * name;
+ ata_attr_raw_format format;
+};
+
+const format_name_entry format_names[] = {
+ {"raw8" , RAWFMT_RAW8},
+ {"raw16" , RAWFMT_RAW16},
+ {"raw48" , RAWFMT_RAW48},
+ {"hex48" , RAWFMT_HEX48},
+ {"raw64" , RAWFMT_RAW64},
+ {"hex64" , RAWFMT_HEX64},
+ {"raw16(raw16)" , RAWFMT_RAW16_OPT_RAW16},
+ {"raw16(avg16)" , RAWFMT_RAW16_OPT_AVG16},
+ {"raw24/raw24" , RAWFMT_RAW24_RAW24},
+ {"sec2hour" , RAWFMT_SEC2HOUR},
+ {"min2hour" , RAWFMT_MIN2HOUR},
+ {"halfmin2hour" , RAWFMT_HALFMIN2HOUR},
+ {"tempminmax" , RAWFMT_TEMPMINMAX},
+ {"temp10x" , RAWFMT_TEMP10X},
+};
+
+const unsigned num_format_names = sizeof(format_names)/sizeof(format_names[0]);
+
+// Table to map old to new '-v' option arguments
+const char * map_old_vendor_opts[][2] = {
+ { "9,halfminutes" , "9,halfmin2hour,Power_On_Half_Minutes"},
+ { "9,minutes" , "9,min2hour,Power_On_Minutes"},
+ { "9,seconds" , "9,sec2hour,Power_On_Seconds"},
+ { "9,temp" , "9,tempminmax,Temperature_Celsius"},
+ {"192,emergencyretractcyclect" , "192,raw48,Emerg_Retract_Cycle_Ct"},
+ {"193,loadunload" , "193,raw24/raw24"},
+ {"194,10xCelsius" , "194,temp10x,Temperature_Celsius_x10"},
+ {"194,unknown" , "194,raw48,Unknown_Attribute"},
+ {"197,increasing" , "197,raw48+,Total_Pending_Sectors"}, // '+' sets flag
+ {"198,offlinescanuncsectorct" , "198,raw48,Offline_Scan_UNC_SectCt"},
+ {"198,increasing" , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
+ {"200,writeerrorcount" , "200,raw48,Write_Error_Count"},
+ {"201,detectedtacount" , "201,raw48,Detected_TA_Count"},
+ {"220,temp" , "220,raw48,Temperature_Celsius"},
+};
+
+const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);
-// This is a utility function for parsing pairs like "9,minutes" or
-// "220,temp", and putting the correct flag into the attributedefs
-// array. Returns 1 if problem, 0 if pair has been recongized.
-int parse_attribute_def(const char * pair, unsigned char * defs)
+// Parse vendor attribute display def (-v option).
+// Return false on error.
+bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
+ ata_vendor_def_prior priority)
{
- int id = 0, nc = -1;
- char name[32+1];
- if (pair[0] == 'N') {
- // "N,name"
- if (!(sscanf(pair, "N,%32s%n", name, &nc) == 1 && nc == (int)strlen(pair)))
- return 1;
+ // Map old -> new options
+ unsigned i;
+ for (i = 0; i < num_old_vendor_opts; i++) {
+ if (!strcmp(opt, map_old_vendor_opts[i][0])) {
+ opt = map_old_vendor_opts[i][1];
+ break;
+ }
+ }
+
+ // Parse option
+ int len = strlen(opt);
+ int id = 0, n1 = -1, n2 = -1;
+ char fmtname[32+1], attrname[32+1];
+ if (opt[0] == 'N') {
+ // "N,format"
+ if (!( sscanf(opt, "N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
+ && (n1 == len || n2 == len)))
+ return false;
}
else {
- // "attr,name"
- if (!( sscanf(pair, "%d,%32s%n", &id, name, &nc) == 2
- && 1 <= id && id <= 255 && nc == (int)strlen(pair)))
- return 1;
+ // "id,format[+][,name]"
+ if (!( sscanf(opt, "%d,%32[^,]%n,%32[^,]%n", &id, fmtname, &n1, attrname, &n2) >= 2
+ && 1 <= id && id <= 255 && (n1 == len || n2 == len)))
+ return false;
}
+ if (n1 == len)
+ attrname[0] = 0;
- // Find pair
- unsigned i;
+ unsigned flags = 0;
+ // For "-v 19[78],increasing" above
+ if (fmtname[strlen(fmtname)-1] == '+') {
+ fmtname[strlen(fmtname)-1] = 0;
+ flags = ATTRFLAG_INCREASING;
+ }
+
+ // Find format name
for (i = 0; ; i++) {
- if (i >= num_vendor_attribute_args)
- return 1; // Not found
- if ( (!vendor_attribute_args[i].id || vendor_attribute_args[i].id == id)
- && !strcmp(vendor_attribute_args[i].name, name) )
+ if (i >= num_format_names)
+ return false; // Not found
+ if (!strcmp(fmtname, format_names[i].name))
break;
}
+ ata_attr_raw_format format = format_names[i].format;
+
+ // 64-bit formats use the normalized value bytes.
+ if (format == RAWFMT_RAW64 || format == RAWFMT_HEX64)
+ flags |= ATTRFLAG_NO_NORMVAL;
if (!id) {
- // "N,name" -> set all entries
- for (int j = 0; j < MAX_ATTRIBUTE_NUM; j++)
- defs[j] = vendor_attribute_args[i].val;
+ // "N,format" -> set format for all entries
+ for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
+ if (defs[i].priority >= priority)
+ continue;
+ if (attrname[0])
+ defs[i].name = attrname;
+ defs[i].priority = priority;
+ defs[i].raw_format = format;
+ defs[i].flags = flags;
+ }
+ }
+ else if (defs[id].priority <= priority) {
+ // "id,format[,name]"
+ if (attrname[0])
+ defs[id].name = attrname;
+ defs[id].raw_format = format;
+ defs[id].priority = priority;
+ defs[id].flags = flags;
}
- else
- // "attr,name"
- defs[id] = vendor_attribute_args[i].val;
- return 0;
+ return true;
}
+
// Return a multiline string containing a list of valid arguments for
// parse_attribute_def(). The strings are preceeded by tabs and followed
// (except for the last) by newlines.
std::string create_vendor_attribute_arg_list()
{
std::string s;
- for (unsigned i = 0; i < num_vendor_attribute_args; i++) {
- if (i > 0)
- s += '\n';
- if (!vendor_attribute_args[i].id)
- s += "\tN,";
- else
- s += strprintf("\t%d,", vendor_attribute_args[i].id);
- s += vendor_attribute_args[i].name;
- }
+ unsigned i;
+ for (i = 0; i < num_format_names; i++)
+ s += strprintf("%s\tN,%s[,ATTR_NAME]",
+ (i>0 ? "\n" : ""), format_names[i].name);
+ for (i = 0; i < num_old_vendor_opts; i++)
+ s += strprintf("\n\t%s", map_old_vendor_opts[i][0]);
return s;
}
return data->offline_data_collection_capability & 0x40;
}
+// Get attribute state
+ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
+ const ata_smart_threshold_entry & thre,
+ const ata_vendor_attr_defs & defs)
+{
+ if (!attr.id)
+ return ATTRSTATE_NON_EXISTING;
+ // Normalized values (current,worst,threshold) not valid
+ // if specified by '-v' option.
+ // (Some SSD disks uses these bytes to store raw value).
+ if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL)
+ return ATTRSTATE_NO_NORMVAL;
-// Loop over all valid attributes. If they are prefailure attributes
-// and are at or below the threshold value, then return the ID of the
-// first failing attribute found. Return 0 if all prefailure
-// attributes are in bounds. The spec says "Bit 0
-// -Pre-failure/advisory - If the value of this bit equals zero, an
-// attribute value less than or equal to its corresponding attribute
-// threshold indicates an advisory condition where the usage or age of
-// the device has exceeded its intended design life period. If the
-// value of this bit equals one, an atribute value less than or equal
-// to its corresponding attribute threshold indicates a pre-failure
-// condition where imminent loss of data is being predicted."
-
-
-// onlyfailed=0 : are or were any age or prefailure attributes <= threshold
-// onlyfailed=1: are any prefailure attributes <= threshold now
-int ataCheckSmart(const ata_smart_values * data,
- const ata_smart_thresholds_pvt * thresholds,
- int onlyfailed)
-{
- // loop over all attributes
- for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++){
-
- // pointers to disk's values and vendor's thresholds
- const ata_smart_attribute * disk = data->vendor_attributes+i;
- const ata_smart_threshold_entry * thre = thresholds->thres_entries+i;
-
- // consider only valid attributes
- if (disk->id && thre->id){
- int failednow,failedever;
-
- failednow =disk->current <= thre->threshold;
- failedever=disk->worst <= thre->threshold;
-
- if (!onlyfailed && failedever)
- return disk->id;
-
- if (onlyfailed && failednow && ATTRIBUTE_FLAGS_PREFAILURE(disk->flags))
- return disk->id;
- }
- }
- return 0;
-}
+ // No threshold if thresholds cannot be read.
+ if (!thre.id && !thre.threshold)
+ return ATTRSTATE_NO_THRESHOLD;
+ // Bad threshold if id's don't match
+ if (attr.id != thre.id)
+ return ATTRSTATE_BAD_THRESHOLD;
+ // Don't report a failed attribute if its threshold is 0.
+ // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
+ // threshold (Later ATA versions declare all thresholds as "obsolete").
+ // In practice, threshold value 0 is often used for usage attributes.
+ if (!thre.threshold)
+ return ATTRSTATE_OK;
-// This checks the n'th attribute in the attribute list, NOT the
-// attribute with id==n. If the attribute does not exist, or the
-// attribute is > threshold, then returns zero. If the attribute is
-// <= threshold (failing) then we the attribute number if it is a
-// prefail attribute. Else we return minus the attribute number if it
-// is a usage attribute.
-int ataCheckAttribute(const ata_smart_values * data,
- const ata_smart_thresholds_pvt * thresholds,
- int n)
-{
- if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !data || !thresholds)
- return 0;
-
- // pointers to disk's values and vendor's thresholds
- const ata_smart_attribute * disk = data->vendor_attributes+n;
- const ata_smart_threshold_entry * thre = thresholds->thres_entries+n;
+ // Failed now if current value is below threshold
+ if (attr.current <= thre.threshold)
+ return ATTRSTATE_FAILED_NOW;
- if (!disk || !thre)
- return 0;
-
- // consider only valid attributes, check for failure
- if (!disk->id || !thre->id || (disk->id != thre->id) || disk->current> thre->threshold)
- return 0;
-
- // We have found a failed attribute. Return positive or negative?
- if (ATTRIBUTE_FLAGS_PREFAILURE(disk->flags))
- return disk->id;
- else
- return -1*(disk->id);
-}
+ // Failed in the passed if worst value is below threshold
+ if (attr.worst <= thre.threshold)
+ return ATTRSTATE_FAILED_PAST;
+ return ATTRSTATE_OK;
+}
-// Print temperature value and Min/Max value if present
-static void ataPrintTemperatureValue(char *out, const unsigned char *raw, const unsigned *word)
+// Get default raw value print format
+static ata_attr_raw_format get_default_raw_format(unsigned char id)
{
- out+=sprintf(out, "%u", word[0]);
- if (!word[1] && !word[2])
- return; // No Min/Max
+ switch (id) {
+ case 3: // Spin-up time
+ return RAWFMT_RAW16_OPT_AVG16;
- unsigned lo = ~0, hi = ~0;
- if (!raw[3]) {
- // 00 HH 00 LL 00 TT (IBM)
- hi = word[2]; lo = word[1];
- }
- else if (!word[2]) {
- // 00 00 HH LL 00 TT (Maxtor)
- hi = raw[3]; lo = raw[2];
+ case 5: // Reallocated sector count
+ case 196: // Reallocated event count
+ return RAWFMT_RAW16_OPT_RAW16;
+
+ case 190: // Temperature
+ case 194:
+ return RAWFMT_TEMPMINMAX;
+
+ default:
+ return RAWFMT_RAW48;
}
- if (lo > hi) {
- unsigned t = lo; lo = hi; hi = t;
+}
+
+// Get attribute raw value.
+uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
+ const ata_vendor_attr_defs & defs)
+{
+ // Get 48 bit raw value
+ const unsigned char * raw = attr.raw;
+ uint64_t rawvalue;
+ rawvalue = raw[0]
+ | ( raw[1] << 8)
+ | ( raw[2] << 16)
+ | ((uint64_t)raw[3] << 24)
+ | ((uint64_t)raw[4] << 32)
+ | ((uint64_t)raw[5] << 40);
+
+ if (defs[attr.id].flags & ATTRFLAG_NO_NORMVAL) {
+ // Some SSD vendors use bytes 3-10 from the Attribute
+ // Data Structure to store a 64-bit raw value.
+ rawvalue <<= 8;
+ rawvalue |= attr.worst;
+ rawvalue <<= 8;
+ rawvalue |= attr.current;
}
- if (lo <= word[0] && word[0] <= hi)
- sprintf(out, " (Lifetime Min/Max %u/%u)", lo, hi);
- else
- sprintf(out, " (%u %u %u %u)", raw[5], raw[4], raw[3], raw[2]);
+ return rawvalue;
}
-// This routine prints the raw value of an attribute as a text string
-// into out. It also returns this 48-bit number as a long long. The
-// array defs[] contains non-zero values if particular attributes have
-// non-default interpretations.
+// Format attribute raw value.
+std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
+ const ata_vendor_attr_defs & defs)
+{
+ // Get 48 bit or64 bit raw value
+ uint64_t rawvalue = ata_get_attr_raw_value(attr, defs);
-int64_t ataPrintSmartAttribRawValue(char *out,
- const ata_smart_attribute * attribute,
- const unsigned char * defs){
- int64_t rawvalue;
+ // Get 16 bit words
+ const unsigned char * raw = attr.raw;
unsigned word[3];
- int j;
- unsigned char select;
-
- // convert the six individual bytes to a long long (8 byte) integer.
- // This is the value that we'll eventually return.
- rawvalue = 0;
- for (j=0; j<6; j++) {
- // This looks a bit roundabout, but is necessary. Don't
- // succumb to the temptation to use raw[j]<<(8*j) since under
- // the normal rules this will be promoted to the native type.
- // On a 32 bit machine this might then overflow.
- int64_t temp;
- temp = attribute->raw[j];
- temp <<= 8*j;
- rawvalue |= temp;
- }
-
- // convert quantities to three two-byte words
- for (j=0; j<3; j++){
- word[j] = attribute->raw[2*j+1];
- word[j] <<= 8;
- word[j] |= attribute->raw[2*j];
- }
-
- // if no data array, Attributes have default interpretations
- if (defs)
- select=defs[attribute->id];
- else
- select=0;
-
- // Print six one-byte quantities.
- if (select==253){
- for (j=0; j<5; j++)
- out+=sprintf(out, "%d ", attribute->raw[5-j]);
- out+=sprintf(out, "%d ", attribute->raw[0]);
- return rawvalue;
- }
-
- // Print three two-byte quantities
- if (select==254){
- out+=sprintf(out, "%d %d %d", word[2], word[1], word[0]);
- return rawvalue;
- }
-
- // Print one six-byte quantity
- if (select==255){
- out+=sprintf(out, "%"PRIu64, rawvalue);
- return rawvalue;
- }
+ word[0] = raw[0] | (raw[1] << 8);
+ word[1] = raw[2] | (raw[3] << 8);
+ word[2] = raw[4] | (raw[5] << 8);
- // This switch statement is where we handle Raw attributes
- // that are stored in an unusual vendor-specific format,
- switch (attribute->id){
- // Spin-up time
- case 3:
- out+=sprintf(out, "%d", word[0]);
- // if second nonzero then it stores the average spin-up time
- if (word[1])
- out+=sprintf(out, " (Average %d)", word[1]);
+ // Get print format
+ ata_attr_raw_format format = defs[attr.id].raw_format;
+ if (format == RAWFMT_DEFAULT)
+ format = get_default_raw_format(attr.id);
+
+ // Print
+ std::string s;
+ switch (format) {
+ case RAWFMT_RAW8:
+ s = strprintf("%d %d %d %d %d %d",
+ raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]);
break;
- // reallocated sector count
- case 5:
- out+=sprintf(out, "%u", word[0]);
+
+ case RAWFMT_RAW16:
+ s = strprintf("%u %u %u", word[2], word[1], word[0]);
+ break;
+
+ case RAWFMT_RAW48:
+ s = strprintf("%"PRIu64, rawvalue);
+ break;
+
+ case RAWFMT_HEX48:
+ s = strprintf("0x%012"PRIx64, rawvalue);
+ break;
+
+ case RAWFMT_RAW64:
+ s = strprintf("%"PRIu64, rawvalue);
+ break;
+
+ case RAWFMT_HEX64:
+ s = strprintf("0x%016"PRIx64, rawvalue);
+ break;
+
+ case RAWFMT_RAW16_OPT_RAW16:
+ s = strprintf("%u", word[0]);
if (word[1] || word[2])
- out+=sprintf(out, " (%u, %u)", word[2], word[1]);
+ s += strprintf(" (%u, %u)", word[2], word[1]);
break;
- // Power on time
- case 9:
- if (select==1){
+
+ case RAWFMT_RAW16_OPT_AVG16:
+ s = strprintf("%u", word[0]);
+ if (word[1])
+ s += strprintf(" (Average %u)", word[1]);
+ break;
+
+ case RAWFMT_RAW24_RAW24:
+ s = strprintf("%d/%d",
+ raw[0] | (raw[1]<<8) | (raw[2]<<16),
+ raw[3] | (raw[4]<<8) | (raw[5]<<16));
+ break;
+
+ case RAWFMT_MIN2HOUR:
+ {
// minutes
- int64_t temp=word[0]+(word[1]<<16);
- int64_t tmp1=temp/60;
- int64_t tmp2=temp%60;
- out+=sprintf(out, "%"PRIu64"h+%02"PRIu64"m", tmp1, tmp2);
+ int64_t temp = word[0]+(word[1]<<16);
+ int64_t tmp1 = temp/60;
+ int64_t tmp2 = temp%60;
+ s = strprintf("%"PRIu64"h+%02"PRIu64"m", tmp1, tmp2);
if (word[2])
- out+=sprintf(out, " (%u)", word[2]);
+ s += strprintf(" (%u)", word[2]);
}
- else if (select==3){
+ break;
+
+ case RAWFMT_SEC2HOUR:
+ {
// seconds
- int64_t hours=rawvalue/3600;
- int64_t minutes=(rawvalue-3600*hours)/60;
- int64_t seconds=rawvalue%60;
- out+=sprintf(out, "%"PRIu64"h+%02"PRIu64"m+%02"PRIu64"s", hours, minutes, seconds);
- }
- else if (select==4){
- // 30-second counter
- int64_t tmp1=rawvalue/120;
- int64_t tmp2=(rawvalue-120*tmp1)/2;
- out+=sprintf(out, "%"PRIu64"h+%02"PRIu64"m", tmp1, tmp2);
+ int64_t hours = rawvalue/3600;
+ int64_t minutes = (rawvalue-3600*hours)/60;
+ int64_t seconds = rawvalue%60;
+ s = strprintf("%"PRIu64"h+%02"PRIu64"m+%02"PRIu64"s", hours, minutes, seconds);
}
- else
- // hours
- out+=sprintf(out, "%"PRIu64, rawvalue); //stored in hours
break;
- // Temperature
- case 190:
- ataPrintTemperatureValue(out, attribute->raw, word);
- break;
- // Load unload cycles
- case 193:
- if (select==1){
- // loadunload
- long load =attribute->raw[0] + (attribute->raw[1]<<8) + (attribute->raw[2]<<16);
- long unload=attribute->raw[3] + (attribute->raw[4]<<8) + (attribute->raw[5]<<16);
- out+=sprintf(out, "%lu/%lu", load, unload);
+
+ case RAWFMT_HALFMIN2HOUR:
+ {
+ // 30-second counter
+ int64_t hours = rawvalue/120;
+ int64_t minutes = (rawvalue-120*hours)/2;
+ s += strprintf("%"PRIu64"h+%02"PRIu64"m", hours, minutes);
}
- else
- // associated
- out+=sprintf(out, "%"PRIu64, rawvalue);
break;
+
+ case RAWFMT_TEMPMINMAX:
// Temperature
- case 194:
- if (select==1){
- // ten times temperature in Celsius
- int deg=word[0]/10;
- int tenths=word[0]%10;
- out+=sprintf(out, "%d.%d", deg, tenths);
+ s = strprintf("%u", word[0]);
+ if (word[1] || word[2]) {
+ unsigned lo = ~0, hi = ~0;
+ if (!raw[3]) {
+ // 00 HH 00 LL 00 TT (IBM)
+ hi = word[2]; lo = word[1];
+ }
+ else if (!word[2]) {
+ // 00 00 HH LL 00 TT (Maxtor)
+ hi = raw[3]; lo = raw[2];
+ }
+ if (lo > hi) {
+ unsigned t = lo; lo = hi; hi = t;
+ }
+ if (lo <= word[0] && word[0] <= hi)
+ s += strprintf(" (Lifetime Min/Max %u/%u)", lo, hi);
+ else
+ s += strprintf(" (%d %d %d %d)", raw[5], raw[4], raw[3], raw[2]);
}
- else if (select==2)
- // unknown attribute
- out+=sprintf(out, "%"PRIu64, rawvalue);
- else
- ataPrintTemperatureValue(out, attribute->raw, word);
break;
- // reallocated event count
- case 196:
- out+=sprintf(out, "%u", word[0]);
- if (word[1] || word[2])
- out+=sprintf(out, " (%u, %u)", word[2], word[1]);
+
+ case RAWFMT_TEMP10X:
+ // ten times temperature in Celsius
+ s = strprintf("%d.%d", word[0]/10, word[0]%10);
break;
+
default:
- out+=sprintf(out, "%"PRIu64, rawvalue);
+ s = "?"; // Should not happen
+ break;
}
-
- // Return the full value
- return rawvalue;
-}
-
-// Note some attribute names appear redundant because different
-// manufacturers use different attribute IDs for an attribute with the
-// same name. The variable val should contain a non-zero value if a particular
-// attributes has a non-default interpretation.
-void ataPrintSmartAttribName(char * out, unsigned char id, const unsigned char * definitions){
- const char *name;
- unsigned char val;
-
- // If no data array, use default interpretations
- if (definitions)
- val=definitions[id];
- else
- val=0;
+ return s;
+}
- switch (id){
-
+// Attribute names shouldn't be longer than 23 chars, otherwise they break the
+// output of smartctl.
+static const char * get_default_attr_name(unsigned char id)
+{
+ switch (id) {
case 1:
- name="Raw_Read_Error_Rate";
- break;
+ return "Raw_Read_Error_Rate";
case 2:
- name="Throughput_Performance";
- break;
+ return "Throughput_Performance";
case 3:
- name="Spin_Up_Time";
- break;
+ return "Spin_Up_Time";
case 4:
- name="Start_Stop_Count";
- break;
+ return "Start_Stop_Count";
case 5:
- name="Reallocated_Sector_Ct";
- break;
+ return "Reallocated_Sector_Ct";
case 6:
- name="Read_Channel_Margin";
- break;
+ return "Read_Channel_Margin";
case 7:
- name="Seek_Error_Rate";
- break;
+ return "Seek_Error_Rate";
case 8:
- name="Seek_Time_Performance";
- break;
+ return "Seek_Time_Performance";
case 9:
- switch (val) {
- case 1:
- name="Power_On_Minutes";
- break;
- case 2:
- name="Temperature_Celsius";
- break;
- case 3:
- name="Power_On_Seconds";
- break;
- case 4:
- name="Power_On_Half_Minutes";
- break;
- default:
- name="Power_On_Hours";
- break;
- }
- break;
+ return "Power_On_Hours";
case 10:
- name="Spin_Retry_Count";
- break;
+ return "Spin_Retry_Count";
case 11:
- name="Calibration_Retry_Count";
- break;
+ return "Calibration_Retry_Count";
case 12:
- name="Power_Cycle_Count";
- break;
+ return "Power_Cycle_Count";
case 13:
- name="Read_Soft_Error_Rate";
- break;
+ return "Read_Soft_Error_Rate";
case 175:
- name="Program_Fail_Count_Chip";
- break;
+ return "Program_Fail_Count_Chip";
case 176:
- name="Erase_Fail_Count_Chip";
- break;
+ return "Erase_Fail_Count_Chip";
case 177:
- name="Wear_Leveling_Count";
- break;
+ return "Wear_Leveling_Count";
case 178:
- name="Used_Rsvd_Blk_Cnt_Chip";
- break;
+ return "Used_Rsvd_Blk_Cnt_Chip";
case 179:
- name="Used_Rsvd_Blk_Cnt_Tot";
- break;
+ return "Used_Rsvd_Blk_Cnt_Tot";
case 180:
- name="Unused_Rsvd_Blk_Cnt_Tot";
- break;
+ return "Unused_Rsvd_Blk_Cnt_Tot";
case 181:
- name="Program_Fail_Cnt_Total";
- break;
+ return "Program_Fail_Cnt_Total";
case 182:
- name="Erase_Fail_Count_Total";
- break;
+ return "Erase_Fail_Count_Total";
case 183:
- name="Runtime_Bad_Block";
- break;
+ return "Runtime_Bad_Block";
case 184:
- name="End-to-End_Error";
- break;
+ return "End-to-End_Error";
case 187:
- name="Reported_Uncorrect";
- break;
+ return "Reported_Uncorrect";
case 188:
- name="Command_Timeout";
- break;
+ return "Command_Timeout";
case 189:
- name="High_Fly_Writes";
- break;
+ return "High_Fly_Writes";
case 190:
// Western Digital uses this for temperature.
// It's identical to Attribute 194 except that it
// is typically 55C. So if this attribute has failed
// in the past, it indicates that the drive temp exceeded
// 55C sometime in the past.
- name="Airflow_Temperature_Cel";
- break;
+ return "Airflow_Temperature_Cel";
case 191:
- name="G-Sense_Error_Rate";
- break;
+ return "G-Sense_Error_Rate";
case 192:
- switch (val) {
- case 1:
- // Fujitsu
- name="Emergency_Retract_Cycle_Ct";
- break;
- default:
- name="Power-Off_Retract_Count";
- break;
- }
- break;
+ return "Power-Off_Retract_Count";
case 193:
- name="Load_Cycle_Count";
- break;
+ return "Load_Cycle_Count";
case 194:
- switch (val){
- case 1:
- // Samsung SV1204H with RK100-13 firmware
- name="Temperature_Celsius_x10";
- break;
- case 2:
- // for disks with no temperature Attribute
- name="Unknown_Attribute";
- break;
- default:
- name="Temperature_Celsius";
- break;
- }
- break;
+ return "Temperature_Celsius";
case 195:
- // Fujitsu name="ECC_On_The_Fly_Count";
- name="Hardware_ECC_Recovered";
- break;
+ // Fujitsu: "ECC_On_The_Fly_Count";
+ return "Hardware_ECC_Recovered";
case 196:
- name="Reallocated_Event_Count";
- break;
+ return "Reallocated_Event_Count";
case 197:
- switch (val) {
- default:
- name="Current_Pending_Sector";
- break;
- case 1:
- // Not reset after sector reallocation
- name="Total_Pending_Sectors";
- break;
- }
- break;
+ return "Current_Pending_Sector";
case 198:
- switch (val){
- default:
- name="Offline_Uncorrectable";
- break;
- case 1:
- // Not reset after sector reallocation
- name="Total_Offl_Uncorrectabl"/*e*/;
- break;
- case 2:
- // Fujitsu
- name="Off-line_Scan_UNC_Sector_Ct";
- break;
- }
- break;
+ return "Offline_Uncorrectable";
case 199:
- name="UDMA_CRC_Error_Count";
- break;
+ return "UDMA_CRC_Error_Count";
case 200:
- switch (val) {
- case 1:
- // Fujitsu MHS2020AT
- name="Write_Error_Count";
- break;
- default:
- // Western Digital
- name="Multi_Zone_Error_Rate";
- break;
- }
- break;
+ // Western Digital
+ return "Multi_Zone_Error_Rate";
case 201:
- switch (val) {
- case 1:
- // Fujitsu
- name="Detected_TA_Count";
- break;
- default:
- name="Soft_Read_Error_Rate";
- break;
- }
- break;
+ return "Soft_Read_Error_Rate";
case 202:
- // Fujitsu
- name="TA_Increase_Count";
- // Maxtor: Data Address Mark Errors
- break;
+ // Fujitsu: "TA_Increase_Count"
+ return "Data_Address_Mark_Errs";
case 203:
// Fujitsu
- name="Run_Out_Cancel";
+ return "Run_Out_Cancel";
// Maxtor: ECC Errors
- break;
case 204:
- // Fujitsu
- name="Shock_Count_Write_Opern";
- // Maxtor: Soft ECC Correction
- break;
+ // Fujitsu: "Shock_Count_Write_Opern"
+ return "Soft_ECC_Correction";
case 205:
- // Fujitsu
- name="Shock_Rate_Write_Opern";
- // Maxtor: Thermal Aspirates
- break;
+ // Fujitsu: "Shock_Rate_Write_Opern"
+ return "Thermal_Asperity_Rate";
case 206:
// Fujitsu
- name="Flying_Height";
- break;
+ return "Flying_Height";
case 207:
// Maxtor
- name="Spin_High_Current";
- break;
+ return "Spin_High_Current";
case 208:
// Maxtor
- name="Spin_Buzz";
- break;
+ return "Spin_Buzz";
case 209:
// Maxtor
- name="Offline_Seek_Performnce";
- break;
+ return "Offline_Seek_Performnce";
case 220:
- switch (val) {
- case 1:
- name="Temperature_Celsius";
- break;
- default:
- name="Disk_Shift";
- break;
- }
- break;
+ return "Disk_Shift";
case 221:
- name="G-Sense_Error_Rate";
- break;
+ return "G-Sense_Error_Rate";
case 222:
- name="Loaded_Hours";
- break;
+ return "Loaded_Hours";
case 223:
- name="Load_Retry_Count";
- break;
+ return "Load_Retry_Count";
case 224:
- name="Load_Friction";
- break;
+ return "Load_Friction";
case 225:
- name="Load_Cycle_Count";
- break;
+ return "Load_Cycle_Count";
case 226:
- name="Load-in_Time";
- break;
+ return "Load-in_Time";
case 227:
- name="Torq-amp_Count";
- break;
+ return "Torq-amp_Count";
case 228:
- name="Power-off_Retract_Count";
- break;
+ return "Power-off_Retract_Count";
case 230:
// seen in IBM DTPA-353750
- name="Head_Amplitude";
- break;
+ return "Head_Amplitude";
case 231:
- name="Temperature_Celsius";
- break;
+ return "Temperature_Celsius";
+ case 232:
+ // seen in Intel X25-E SSD
+ return "Available_Reservd_Space";
+ case 233:
+ // seen in Intel X25-E SSD
+ return "Media_Wearout_Indicator";
case 240:
- name="Head_Flying_Hours";
- break;
+ return "Head_Flying_Hours";
+ case 241:
+ return "Total_LBAs_Written";
+ case 242:
+ return "Total_LBAs_Read";
case 250:
- name="Read_Error_Retry_Rate";
- break;
+ return "Read_Error_Retry_Rate";
+ case 254:
+ return "Free_Fall_Sensor";
default:
- name="Unknown_Attribute";
- break;
+ return "Unknown_Attribute";
}
- sprintf(out,"%3hu %s",(short int)id,name);
- return;
}
-// Returns raw value of Attribute with ID==id. This will be in the
-// range 0 to 2^48-1 inclusive. If the Attribute does not exist,
-// return -1.
-int64_t ATAReturnAttributeRawValue(unsigned char id, const ata_smart_values * data)
+// Get attribute name
+std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs)
+{
+ if (!defs[id].name.empty())
+ return defs[id].name;
+ else
+ return get_default_attr_name(id);
+}
+
+// Find attribute index for attribute id, -1 if not found.
+int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
{
- // valid Attribute IDs are in the range 1 to 255 inclusive.
- if (!id || !data)
+ if (!id)
return -1;
-
- // loop over Attributes to see if there is one with the desired ID
for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
- const ata_smart_attribute * ap = data->vendor_attributes + i;
- if (ap->id == id) {
- // we've found the desired Attribute. Return its value
- int64_t rawvalue=0;
- int j;
-
- for (j=0; j<6; j++) {
- // This looks a bit roundabout, but is necessary. Don't
- // succumb to the temptation to use raw[j]<<(8*j) since under
- // the normal rules this will be promoted to the native type.
- // On a 32 bit machine this might then overflow.
- int64_t temp;
- temp = ap->raw[j];
- temp <<= 8*j;
- rawvalue |= temp;
- } // loop over j
- return rawvalue;
- } // found desired Attribute
- } // loop over Attributes
-
- // fall-through: no such Attribute found
+ if (smartval.vendor_attributes[i].id == id)
+ return i;
+ }
return -1;
}
// Return Temperature Attribute raw value selected according to possible
// non-default interpretations. If the Attribute does not exist, return 0
-unsigned char ATAReturnTemperatureValue(const ata_smart_values * data, const unsigned char * defs)
+unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
{
for (int i = 0; i < 3; i++) {
static const unsigned char ids[3] = {194, 9, 220};
unsigned char id = ids[i];
- unsigned char select = (defs ? defs[id] : 0);
- int64_t raw; unsigned temp;
- if (!( (id == 194 && select <= 1) // ! -v 194,unknown
- || (id == 9 && select == 2) // -v 9,temp
- || (id == 220 && select == 1))) // -v 220,temp
+ const ata_attr_raw_format format = defs[id].raw_format;
+ if (!( (id == 194 && format == RAWFMT_DEFAULT)
+ || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
continue;
- raw = ATAReturnAttributeRawValue(id, data);
- if (raw < 0)
+ int idx = ata_find_attr_index(id, *data);
+ if (idx < 0)
continue;
- temp = (unsigned short)raw; // ignore possible min/max values in high words
- if (id == 194 && select == 1) // -v 194,10xCelsius
+ uint64_t raw = ata_get_attr_raw_value(data->vendor_attributes[idx], defs);
+ unsigned temp = (unsigned short)raw; // ignore possible min/max values in high words
+ if (format == RAWFMT_TEMP10X) // -v N,temp10x
temp = (temp+5) / 10;
if (!(0 < temp && temp <= 255))
continue;
#ifndef ATACMDS_H_
#define ATACMDS_H_
-#define ATACMDS_H_CVSID "$Id: atacmds.h 2859 2009-07-23 18:55:06Z chrfranke $"
+#define ATACMDS_H_CVSID "$Id: atacmds.h 2983 2009-11-14 21:41:41Z chrfranke $"
#include "dev_interface.h" // ata_device
: num_spans(0), pending_time(0), scan_after_select(0) { }
};
+// Priority for vendor attribute defs
+enum ata_vendor_def_prior
+{
+ PRIOR_DEFAULT,
+ PRIOR_DATABASE,
+ PRIOR_USER
+};
+
+// Raw attribute value print formats
+enum ata_attr_raw_format
+{
+ RAWFMT_DEFAULT,
+ RAWFMT_RAW8,
+ RAWFMT_RAW16,
+ RAWFMT_RAW48,
+ RAWFMT_HEX48,
+ RAWFMT_RAW64,
+ RAWFMT_HEX64,
+ RAWFMT_RAW16_OPT_RAW16,
+ RAWFMT_RAW16_OPT_AVG16,
+ RAWFMT_RAW24_RAW24,
+ RAWFMT_SEC2HOUR,
+ RAWFMT_MIN2HOUR,
+ RAWFMT_HALFMIN2HOUR,
+ RAWFMT_TEMPMINMAX,
+ RAWFMT_TEMP10X,
+};
+
+// Attribute flags
+enum {
+ ATTRFLAG_INCREASING = 0x01, // Value not reset (for reallocated/pending counts)
+ ATTRFLAG_NO_NORMVAL = 0x02 // Normalized value not valid
+};
+
+// Vendor attribute display defs for all attribute ids
+class ata_vendor_attr_defs
+{
+public:
+ struct entry
+ {
+ std::string name; // Attribute name, empty for default
+ ata_attr_raw_format raw_format; // Raw value print format
+ ata_vendor_def_prior priority; // Setting priority
+ unsigned flags; // ATTRFLAG_*
+
+ entry()
+ : raw_format(RAWFMT_DEFAULT),
+ priority(PRIOR_DEFAULT),
+ flags(0)
+ { }
+ };
+
+ entry & operator[](unsigned char id)
+ { return m_defs[id]; }
+
+ const entry & operator[](unsigned char id) const
+ { return m_defs[id]; }
+
+private:
+ entry m_defs[256];
+};
+
// Get information from drive
int ataReadHDIdentity(ata_device * device, struct ata_identify_device *buf);
// -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see
int ataIsSmartEnabled(const ata_identify_device * drive);
-/* Check SMART for Threshold failure */
-// onlyfailed=0 : are or were any age or prefailure attributes <= threshold
-// onlyfailed=1: are any prefailure attributes <= threshold now
-int ataCheckSmart(const ata_smart_values * data, const ata_smart_thresholds_pvt * thresholds, int onlyfailed);
-
int ataSmartStatus2(ata_device * device);
int isSmartErrorLogCapable(const ata_smart_values * data, const ata_identify_device * identity);
int TestTime(const ata_smart_values * data, int testtype);
-// Prints the raw value (with appropriate formatting) into the
-// character string out.
-int64_t ataPrintSmartAttribRawValue(char *out,
- const ata_smart_attribute * attribute,
- const unsigned char * defs);
-
-// Prints Attribute Name for standard SMART attributes. Writes a
-// 30 byte string with attribute name into output
-void ataPrintSmartAttribName(char * out, unsigned char id, const unsigned char * definitions);
-
-// This checks the n'th attribute in the attribute list, NOT the
-// attribute with id==n. If the attribute does not exist, or the
-// attribute is > threshold, then returns zero. If the attribute is
-// <= threshold (failing) then we the attribute number if it is a
-// prefail attribute. Else we return minus the attribute number if it
-// is a usage attribute.
-int ataCheckAttribute(const ata_smart_values * data,
- const ata_smart_thresholds_pvt * thresholds,
- int n);
+// Attribute state
+enum ata_attr_state
+{
+ ATTRSTATE_NON_EXISTING, // No such Attribute
+ ATTRSTATE_NO_NORMVAL, // Normalized value not valid
+ ATTRSTATE_BAD_THRESHOLD, // Threshold not valid
+ ATTRSTATE_NO_THRESHOLD, // Unknown or no threshold
+ ATTRSTATE_OK, // Never failed
+ ATTRSTATE_FAILED_PAST, // Failed in the past
+ ATTRSTATE_FAILED_NOW // Failed now
+};
+
+// Get attribute state
+ata_attr_state ata_get_attr_state(const ata_smart_attribute & attr,
+ const ata_smart_threshold_entry & thre,
+ const ata_vendor_attr_defs & defs);
+
+// Get attribute raw value.
+uint64_t ata_get_attr_raw_value(const ata_smart_attribute & attr,
+ const ata_vendor_attr_defs & defs);
+
+// Format attribute raw value.
+std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
+ const ata_vendor_attr_defs & defs);
+
+// Get attribute name
+std::string ata_get_smart_attr_name(unsigned char id,
+ const ata_vendor_attr_defs & defs);
// External handler function, for when a checksum is not correct. Can
// simply return if no action is desired, or can print error messages
// Structure with the incorrect checksum.
void checksumwarning(const char *string);
-// Returns raw value of Attribute with ID==id. This will be in the
-// range 0 to 2^48-1 inclusive. If the Attribute does not exist,
-// return -1.
-int64_t ATAReturnAttributeRawValue(unsigned char id, const ata_smart_values * data);
+// Find attribute index for attribute id, -1 if not found.
+int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval);
// Return Temperature Attribute raw value selected according to possible
// non-default interpretations. If the Attribute does not exist, return 0
-unsigned char ATAReturnTemperatureValue(const ata_smart_values * data, const unsigned char * defs);
+unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs);
// This are the meanings of the Self-test failure checkpoint byte.
#define MAX_ATTRIBUTE_NUM 256
-// function to parse pairs like "9,minutes" or "220,temp". See end of
-// extern.h for definition of defs[]. Returns 0 if pair recognized,
-// else 1 if there is a problem.
-int parse_attribute_def(const char * pair, unsigned char * defs);
+// Parse vendor attribute display def (-v option).
+// Return false on error.
+bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
+ ata_vendor_def_prior priority);
// Get ID and increase flag of current pending or offline
// uncorrectable attribute.
-unsigned char get_unc_attr_id(bool offline, const unsigned char * defs,
+unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
bool & increase);
// Return a multiline string containing a list of valid arguments for
#include "utility.h"
#include "knowndrives.h"
-const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 2860 2009-07-23 20:27:28Z chrfranke $"
+const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 2983 2009-11-14 21:41:41Z chrfranke $"
ATAPRINT_H_CVSID;
// for passing global control variables
pout("recommended polling time: \t Not Supported.\n");
}
+// Check SMART attribute table for Threshold failure
+// onlyfailed=0: are or were any age or prefailure attributes <= threshold
+// onlyfailed=1: are any prefailure attributes <= threshold now
+static int find_failed_attr(const ata_smart_values * data,
+ const ata_smart_thresholds_pvt * thresholds,
+ const ata_vendor_attr_defs & defs, int onlyfailed)
+{
+ for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
+ const ata_smart_attribute & attr = data->vendor_attributes[i];
+
+ ata_attr_state state = ata_get_attr_state(attr,
+ thresholds->thres_entries[i], defs);
+
+ if (!onlyfailed) {
+ if (state >= ATTRSTATE_FAILED_PAST)
+ return attr.id;
+ }
+ else {
+ if (state == ATTRSTATE_FAILED_NOW && ATTRIBUTE_FLAGS_PREFAILURE(attr.flags))
+ return attr.id;
+ }
+ }
+ return 0;
+}
+
// onlyfailed=0 : print all attribute values
// onlyfailed=1: just ones that are currently failed and have prefailure bit set
// onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set
static void PrintSmartAttribWithThres(const ata_smart_values * data,
const ata_smart_thresholds_pvt * thresholds,
- const unsigned char * attributedefs,
+ const ata_vendor_attr_defs & defs,
int onlyfailed)
{
- int needheader=1;
- char rawstring[64];
-
+ bool needheader = true;
+
// step through all vendor attributes
for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
- const char *status;
- const ata_smart_attribute * disk = data->vendor_attributes+i;
- const ata_smart_threshold_entry * thre = thresholds->thres_entries+i;
-
- // consider only valid attributes (allowing some screw-ups in the
- // thresholds page data to slip by)
- if (disk->id){
- const char *type, *update;
- char attributename[64];
-
- // Don't report a failed attribute if its threshold is 0.
- // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing"
- // threshold (Later ATA versions declare all thresholds as "obsolete").
- // In practice, threshold value 0 is often used for usage attributes or
- // appears if the thresholds cannot be read.
- bool failednow = (thre->threshold > 0 && disk->current <= thre->threshold);
- bool failedever = (thre->threshold > 0 && disk->worst <= thre->threshold);
-
- // These break out of the loop if we are only printing certain entries...
- if (onlyfailed==1 && (!ATTRIBUTE_FLAGS_PREFAILURE(disk->flags) || !failednow))
- continue;
-
- if (onlyfailed==2 && !failedever)
- continue;
-
- // print header only if needed
- if (needheader){
- if (!onlyfailed){
- pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
- pout("Vendor Specific SMART Attributes with Thresholds:\n");
- }
- pout("ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n");
- needheader=0;
- }
-
- // is this Attribute currently failed, or has it ever failed?
- if (failednow)
- status="FAILING_NOW";
- else if (failedever)
- status="In_the_past";
- else
- status=" -";
+ const ata_smart_attribute & attr = data->vendor_attributes[i];
+ const ata_smart_threshold_entry & thre = thresholds->thres_entries[i];
- // Print name of attribute
- ataPrintSmartAttribName(attributename, disk->id, attributedefs);
- pout("%-28s",attributename);
+ // Check attribute and threshold
+ ata_attr_state state = ata_get_attr_state(attr, thre, defs);
+ if (state == ATTRSTATE_NON_EXISTING)
+ continue;
- // printing line for each valid attribute
- type=ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)?"Pre-fail":"Old_age";
- update=ATTRIBUTE_FLAGS_ONLINE(disk->flags)?"Always":"Offline";
+ // These break out of the loop if we are only printing certain entries...
+ if (onlyfailed == 1 && !(ATTRIBUTE_FLAGS_PREFAILURE(attr.flags) && state == ATTRSTATE_FAILED_NOW))
+ continue;
- pout("0x%04x %.3d %.3d %.3d %-10s%-9s%-12s",
- (int)disk->flags, (int)disk->current, (int)disk->worst,
- (int)thre->threshold, type, update, status);
+ if (onlyfailed == 2 && state < ATTRSTATE_FAILED_PAST)
+ continue;
- // print raw value of attribute
- ataPrintSmartAttribRawValue(rawstring, disk, attributedefs);
- pout("%s\n", rawstring);
-
- // Print a warning if there is inconsistency here and
- // threshold info is not empty.
- if (disk->id != thre->id && (thre->id || thre->threshold)) {
- char atdat[64],atthr[64];
- ataPrintSmartAttribName(atdat, disk->id, attributedefs);
- ataPrintSmartAttribName(atthr, thre->id, attributedefs);
- pout("%-28s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",atdat);
- pout("%-28s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",atthr);
+ // print header only if needed
+ if (needheader) {
+ if (!onlyfailed) {
+ pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber);
+ pout("Vendor Specific SMART Attributes with Thresholds:\n");
}
+ pout("ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE\n");
+ needheader = false;
+ }
+
+ // Format value, worst, threshold
+ std::string valstr, threstr;
+ if (state > ATTRSTATE_NO_NORMVAL)
+ valstr = strprintf("%.3d %.3d", attr.current, attr.worst);
+ else
+ valstr = "--- ---";
+ if (state > ATTRSTATE_NO_THRESHOLD)
+ threstr = strprintf("%.3d", thre.threshold);
+ else
+ threstr = "---";
+
+ // Print line for each valid attribute
+ std::string attrname = ata_get_smart_attr_name(attr.id, defs);
+ pout("%3d %-24s0x%04x %-9s %-3s %-10s%-9s%-12s%s\n",
+ attr.id, attrname.c_str(), attr.flags,
+ valstr.c_str(), threstr.c_str(),
+ (ATTRIBUTE_FLAGS_PREFAILURE(attr.flags)? "Pre-fail" : "Old_age"),
+ (ATTRIBUTE_FLAGS_ONLINE(attr.flags)? "Always" : "Offline"),
+ (state == ATTRSTATE_FAILED_NOW ? "FAILING_NOW" :
+ state == ATTRSTATE_FAILED_PAST ? "In_the_past" :
+ " -" ),
+ ata_format_attr_raw_value(attr, defs).c_str());
+
+ // Print a warning if there is inconsistency here
+ if (state == ATTRSTATE_BAD_THRESHOLD) {
+ pout("%3d %-24s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n",
+ attr.id, attrname.c_str());
+ pout("%3d %-24s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n",
+ thre.id, ata_get_smart_attr_name(thre.id, defs).c_str());
}
}
if (!needheader) pout("\n");
}
// Use preset vendor attribute options unless user has requested otherwise.
- unsigned char attributedefs[256];
- memcpy(attributedefs, options.attributedefs, sizeof(attributedefs));
+ ata_vendor_attr_defs attribute_defs = options.attribute_defs;
unsigned char fix_firmwarebug = options.fix_firmwarebug;
if (!options.ignore_presets)
- apply_presets(&drive, attributedefs, fix_firmwarebug, options.fix_swapped_id);
+ apply_presets(&drive, attribute_defs, fix_firmwarebug, options.fix_swapped_id);
// Print most drive identity information if requested
bool known = false;
case 0:
// The case where the disk health is OK
pout("SMART overall-health self-assessment test result: PASSED\n");
- if (ataCheckSmart(&smartval, &smartthres,0)){
+ if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 0)){
if (options.smart_vendor_attrib)
pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
else {
PRINT_ON(con);
pout("Please note the following marginal Attributes:\n");
- PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs, 2);
+ PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2);
}
returnval|=FAILAGE;
}
pout("SMART overall-health self-assessment test result: FAILED!\n"
"Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
PRINT_OFF(con);
- if (ataCheckSmart(&smartval, &smartthres,1)){
+ if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 1)){
returnval|=FAILATTR;
if (options.smart_vendor_attrib)
pout("See vendor-specific Attribute list for failed Attributes.\n\n");
else {
PRINT_ON(con);
pout("Failed Attributes:\n");
- PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs, 1);
+ PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1);
}
}
else
case -1:
default:
// The case where something went wrong with HDIO_DRIVE_TASK ioctl()
- if (ataCheckSmart(&smartval, &smartthres,1)){
+ if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 1)){
PRINT_ON(con);
pout("SMART overall-health self-assessment test result: FAILED!\n"
"Drive failure expected in less than 24 hours. SAVE ALL DATA.\n");
else {
PRINT_ON(con);
pout("Failed Attributes:\n");
- PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs, 1);
+ PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1);
}
}
else {
pout("SMART overall-health self-assessment test result: PASSED\n");
- if (ataCheckSmart(&smartval, &smartthres,0)){
+ if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 0)){
if (options.smart_vendor_attrib)
pout("See vendor-specific Attribute list for marginal Attributes.\n\n");
else {
PRINT_ON(con);
pout("Please note the following marginal Attributes:\n");
- PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs, 2);
+ PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2);
}
returnval|=FAILAGE;
}
// Print vendor-specific attributes
if (options.smart_vendor_attrib) {
PRINT_ON(con);
- PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs,
+ PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs,
(con->printing_switchable ? 2 : 0));
PRINT_OFF(con);
}
ata_smart_log_directory smartlogdir_buf, gplogdir_buf;
const ata_smart_log_directory * smartlogdir = 0, * gplogdir = 0;
- if ( options.gp_logdir || options.smart_logdir
- || options.sataphy || options.smart_ext_error_log
+ if ( options.gp_logdir
+ || options.smart_logdir
+ || options.smart_ext_error_log
|| options.smart_ext_selftest_log
- || !options.log_requests.empty() ) {
+ || options.sataphy
+ || !options.log_requests.empty() ) {
PRINT_ON(con);
if (isGeneralPurposeLoggingCapable(&drive))
pout("General Purpose Logging (GPL) feature set supported\n");
bool need_smart_logdir = options.smart_logdir;
bool need_gp_logdir = ( options.gp_logdir
|| options.smart_ext_error_log
- || options.smart_ext_selftest_log);
+ || options.smart_ext_selftest_log
+ || options.sataphy );
unsigned i;
for (i = 0; i < options.log_requests.size(); i++) {
if (options.log_requests[i].gpl)
// Print SATA Phy Event Counters
if (options.sataphy) {
- unsigned char log_11[512] = {0, };
- unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
- if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1))
- failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
- else
- PrintSataPhyEventCounters(log_11, options.sataphy_reset);
+ unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true);
+ if (!nsectors)
+ pout("SATA Phy Event Counters (GP Log 0x11) not supported\n");
+ else if (nsectors != 1)
+ pout("SATA Phy Event Counters with %u sectors not supported\n", nsectors);
+ else {
+ unsigned char log_11[512] = {0, };
+ unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
+ if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1))
+ failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+ else
+ PrintSataPhyEventCounters(log_11, options.sataphy_reset);
+ }
}
// START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN
#ifndef ATAPRINT_H_
#define ATAPRINT_H_
-#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.43 2009/07/07 19:28:29 chrfranke Exp $\n"
+#define ATAPRINT_H_CVSID "$Id: ataprint.h 2975 2009-10-29 22:52:38Z chrfranke $\n"
#include <vector>
unsigned char fix_firmwarebug; // FIX_*, see atacmds.h
bool fix_swapped_id; // Fix swapped ID strings returned by some buggy drivers
- // The i'th entry in this array will modify the printed meaning of
- // the i'th SMART attribute. The default definitions of the
- // Attributes are obtained by having the array be all zeros. If
- // attributedefs[i] is nonzero, it means that the i'th attribute has
- // a non-default meaning. See the ataPrintSmartAttribName and
- // and parse_attribute_def functions.
- unsigned char attributedefs[256];
+ ata_vendor_attr_defs attribute_defs; // -v options
bool ignore_presets; // Ignore presets from drive database
bool show_presets; // Show presets and exit
ignore_presets(false),
show_presets(false),
powermode(0)
- { memset(attributedefs, 0, sizeof(attributedefs)); }
+ { }
};
int ataPrintMain(ata_device * device, const ata_print_options & options);
#
-# $Id: configure.in 2927 2009-10-03 16:08:34Z chrfranke $
+# $Id: configure.in 2992 2009-12-04 17:05:21Z chrfranke $
#
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(smartctl.cpp)
smartmontools_configure_date=`date -u +'%Y-%m-%d %T %Z'`
-smartmontools_cvs_tag=`echo '$Id: configure.in 2927 2009-10-03 16:08:34Z chrfranke $'`
-smartmontools_release_date=2008/03/10
-smartmontools_release_time="10:44:07 GMT"
+smartmontools_cvs_tag=`echo '$Id: configure.in 2992 2009-12-04 17:05:21Z chrfranke $'`
+smartmontools_release_date=2009-11-30
+smartmontools_release_time="20:24:12 UTC"
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args", [smartmontools Configure Arguments])
AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_DATE, "$smartmontools_configure_date", [smartmontools Configure Date])
AM_CONDITIONAL(OS_WIN32_MINGW, [echo $host_os | grep '^mingw' > /dev/null])
AM_CONDITIONAL(OS_FREEBSD, [echo $host_os | grep '^freebsd' > /dev/null])
-dnl Add -Wall and -W if using gcc and its not already specified.
-if test "x$GCC" = "xyes"; then
+dnl Add -Wall and -W if using g++ and its not already specified.
+if test "$GXX" = "yes"; then
if test -z "`echo "$CXXFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
CXXFLAGS="$CXXFLAGS -Wall"
fi
# MinGW uses MSVCRT.DLL which uses printf format "%I64d" and not "%lld" for int64_t
CXXFLAGS="$CXXFLAGS -Wno-format";;
esac
+
+ # Disable strict aliasing rules by default (see ticket #23).
+ if test -z "`echo "$CXXFLAGS" | grep "\-f[[no-]]*strict-aliasing" 2> /dev/null`" ; then
+ AC_MSG_CHECKING([whether g++ supports -fno-strict-aliasing])
+ ac_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="-fno-strict-aliasing"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ [gcc_have_fno_strict_aliasing=yes], [gcc_have_fno_strict_aliasing=no])
+ CXXFLAGS="$ac_save_CXXFLAGS"
+ if test "$gcc_have_fno_strict_aliasing" = "yes"; then
+ CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
+ fi
+ AC_MSG_RESULT([$gcc_have_fno_strict_aliasing])
+ fi
+
else
dnl We are NOT using gcc, so enable host-specific compiler flags
case "${host}" in
#include <stdexcept>
-const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 2971 2009-10-26 22:05:54Z chrfranke $"
DEV_INTERFACE_H_CVSID;
/////////////////////////////////////////////////////////////////////////////
// Recurse to allocate base device, default is standard SCSI
if (!*basetype)
basetype = "scsi";
- dev = get_smart_device(name, basetype);
- if (!dev) {
+ smart_device_auto_ptr basedev( get_smart_device(name, basetype) );
+ if (!basedev) {
set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg());
return 0;
}
// Result must be SCSI
- if (!dev->is_scsi()) {
- delete dev;
+ if (!basedev->is_scsi()) {
set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype);
return 0;
}
// Attach SAT tunnel
- try {
- ata_device * satdev = get_sat_device(sattype.c_str(), dev->to_scsi());
- if (!satdev) {
- delete dev;
- return 0;
- }
- return satdev;
- }
- catch (...) {
- delete dev; throw;
- }
+ ata_device * satdev = get_sat_device(sattype.c_str(), basedev->to_scsi());
+ if (!satdev)
+ return 0;
+ basedev.release();
+ return satdev;
}
else {
#ifndef DEV_INTERFACE_H
#define DEV_INTERFACE_H
-#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 2915 2009-09-18 21:17:37Z chrfranke $\n"
+#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 2973 2009-10-26 22:38:19Z chrfranke $\n"
#include <stdarg.h>
+#include <stdexcept>
#include <string>
#include <vector>
}
+/////////////////////////////////////////////////////////////////////////////
+/// Smart pointer class for device pointers
+
+template <class Dev>
+class any_device_auto_ptr
+{
+public:
+ typedef Dev device_type;
+
+ /// Construct from optional pointer to device
+ /// and optional pointer to base device.
+ explicit any_device_auto_ptr(device_type * dev = 0,
+ smart_device * base_dev = 0)
+ : m_dev(dev), m_base_dev(base_dev) { }
+
+ /// Destructor deletes device object.
+ ~any_device_auto_ptr() throw()
+ { reset(); }
+
+ /// Assign a new pointer.
+ /// Throws if a pointer is already assigned.
+ void operator=(device_type * dev)
+ {
+ if (m_dev)
+ fail();
+ m_dev = dev;
+ }
+
+ /// Delete device object and clear the pointer.
+ void reset()
+ {
+ if (m_dev) {
+ if (m_base_dev && m_dev->owns(m_base_dev))
+ m_dev->release(m_base_dev);
+ delete m_dev;
+ }
+ m_dev = 0;
+ }
+
+ /// Return the pointer and release ownership.
+ device_type * release()
+ {
+ device_type * dev = m_dev;
+ m_dev = 0;
+ return dev;
+ }
+
+ /// Replace the pointer.
+ /// Used to call dev->autodetect_open().
+ void replace(device_type * dev)
+ { m_dev = dev; }
+
+ /// Return the pointer.
+ device_type * get() const
+ { return m_dev; }
+
+ /// Pointer dereferencing.
+ device_type & operator*() const
+ { return *m_dev; }
+
+ /// Pointer dereferencing.
+ device_type * operator->() const
+ { return m_dev; }
+
+ /// For (ptr != 0) check.
+ operator bool() const
+ { return !!m_dev; }
+
+ /// For (ptr == 0) check.
+ bool operator !() const
+ { return !m_dev; }
+
+private:
+ device_type * m_dev;
+ smart_device * m_base_dev;
+
+ void fail() const
+ { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
+
+ // Prevent copy/assignment
+ any_device_auto_ptr(const any_device_auto_ptr<Dev> &);
+ void operator=(const any_device_auto_ptr<Dev> &);
+};
+
+typedef any_device_auto_ptr<smart_device> smart_device_auto_ptr;
+typedef any_device_auto_ptr<ata_device> ata_device_auto_ptr;
+typedef any_device_auto_ptr<scsi_device> scsi_device_auto_ptr;
+
+
/////////////////////////////////////////////////////////////////////////////
// smart_device_list
}
- void add(smart_device * dev)
- { m_list.push_back(dev); }
-
void push_back(smart_device * dev)
{ m_list.push_back(dev); }
+ void push_back(smart_device_auto_ptr & dev)
+ {
+ m_list.push_back(dev.get());
+ dev.release();
+ }
+
smart_device * at(unsigned i)
{ return m_list.at(i); }
*
* Home page of code is: http://smartmontools.sourceforge.net
*
- * Copyright (C) 2008 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "dev_interface.h"
#include "dev_ata_cmd_set.h"
-const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp 2973 2009-10-26 22:38:19Z chrfranke $"
DEV_INTERFACE_H_CVSID;
extern smartmonctrl * con; // con->reportscsiioctl
int avail_len = req_buff[4] + 5;
int len = (avail_len < req_len ? avail_len : req_len);
if (len < 36)
- return this;
+ return this;
// Use INQUIRY to detect type
- smart_device * newdev = 0;
- try {
- // 3ware ?
- if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
- close();
+
+ // 3ware ?
+ if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
+ close();
#if defined(_WIN32) || defined(__CYGWIN__)
- set_err(EINVAL, "AMCC/3ware controller, please try changing device to %s,N", get_dev_name());
+ set_err(EINVAL, "AMCC/3ware controller, please try changing device to %s,N", get_dev_name());
#else
- set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
- "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
+ set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
+ "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
#endif
- return this;
- }
+ return this;
+ }
- // Marvell ?
- if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) { // TODO: Linux-specific?
- //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
- close();
- newdev = new legacy_marvell_device(smi(), get_dev_name(), get_req_type());
- newdev->open(); // TODO: Can possibly pass open fd
- delete this;
- return newdev;
- }
+ // Marvell ?
+ if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) { // TODO: Linux-specific?
+ //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
+ close();
+ smart_device_auto_ptr newdev(
+ new legacy_marvell_device(smi(), get_dev_name(), get_req_type()),
+ this
+ );
+ newdev->open(); // TODO: Can possibly pass open fd
+ delete this;
+ return newdev.release();
+ }
- // SAT or USB ?
- newdev = smi()->autodetect_sat_device(this, req_buff, len);
+ // SAT or USB ?
+ {
+ smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
if (newdev)
// NOTE: 'this' is now owned by '*newdev'
return newdev;
}
- catch (...) {
- // Cleanup if exception occurs after newdev was allocated
- delete newdev;
- throw;
- }
// Nothing special found
return this;
static void free_devnames(char * * devnames, int numdevs)
{
- static const char version[] = "$Id: dev_legacy.cpp 2915 2009-09-18 21:17:37Z chrfranke $";
+ static const char version[] = "$Id: dev_legacy.cpp 2973 2009-10-26 22:38:19Z chrfranke $";
for (int i = 0; i < numdevs; i++)
FreeNonZero(devnames[i], -1,__LINE__, version);
FreeNonZero(devnames, (sizeof (char*) * numdevs),__LINE__, version);
for (i = 0; i < numata; i++) {
ata_device * atadev = get_ata_device(atanames[i], type);
if (atadev)
- devlist.add(atadev);
+ devlist.push_back(atadev);
}
free_devnames(atanames, numata);
for (i = 0; i < numscsi; i++) {
scsi_device * scsidev = get_scsi_device(scsinames[i], type);
if (scsidev)
- devlist.add(scsidev);
+ devlist.push_back(scsidev);
}
free_devnames(scsinames, numscsi);
return true;
-#!/bin/bash -ev
+#!/bin/bash
#
# do a smartmontools release
-# (C) 2003-6 Bruce Allen <ballen4705@users.sourceforge.net>,
-# Guido Guenther <agx@sigxcpu.org>
-# $Id: do_release 2845 2009-07-18 13:25:18Z chrfranke $
-
-echo 'TODO: Rework this script for SVN.'
-exit 1
+# (C) 2003-9 Bruce Allen <ballen4705@users.sourceforge.net>,
+# Guido Guenther <agx@sigxcpu.org>
+# Christian Franke <smartmontools-support@lists.sourceforge.net>
+# $Id: do_release 2970 2009-10-26 18:36:22Z chrfranke $
# Notes on generating releases:
# (1) update NEWS
# (2) update CHANGELOG -- put in release number
# (3) update release number in configure.in
-# (4) to test, set USECVS below to 0
-# (5) when satisfied, set USECVS below to 1
-
-USECVS=1
-
-KEYID=0x841ABAE8
-
-setup_cvs()
-{
- CVS_SERVER=fakevalue
- unset CVS_SERVER || echo "can't unset CVS_SERVER=$CVS_SERVER"
- CVS_RSH=ssh
- CVSROOT=:ext:ballen4705@smartmontools.cvs.sourceforge.net:/cvsroot/smartmontools
-}
+# (4) to test, run without '--commit'
+# (5) when satisfied, add option '--commit'
-get_release()
-{
- VERSION=`grep 'AC_INIT' configure.in | awk '{ print $2 }' | sed s/,//g`
- RELEASE="RELEASE_${VERSION//\./_}"
- echo "Version: $VERSION"
- echo "Release: $RELEASE"
-}
+set -e
inc_release()
{
echo "New Release: $NEW_RELEASE"
}
-# run automake/autoconf
-if [ -f Makefile ] ; then
- make distcheck || exit 1
- make clean
- make distclean
- rm -f Makefile configure
+COMMIT=
+RC=
+
+case "$1" in
+ --commit) COMMIT=yes; shift ;;
+esac
+
+case "$*" in
+ RC[1-9]) RC="$1" ;;
+ FINAL) ;;
+ *) echo "Usage: $0 [--commit] RC[1-9]|FINAL"; exit 1 ;;
+esac
+
+# Check workdir
+case "`/bin/pwd`" in
+ */trunk/smartmontools) ;;
+ *) echo "not run from trunk checkout"; exit 1 ;;
+esac
+
+if [ ! -d ../../tags ]; then
+ echo "tags directory missing"; exit 1
+fi
+
+REV=`(cd ../.. && svnversion)` || exit 1
+if [ -z "`echo "$REV" | sed -n '/^[0-9][0-9]*$/p'`" ]; then
+ echo "Working directory not clean: $REV"; exit 1
+fi
+
+# Get release number
+VERSION=`sed -n 's|^AC_INIT[^,]*, *\([0-9.]*\) *,.*$|\1|p' configure.in`
+if [ -z "$VERSION" ]; then
+ echo "AC_INIT not found in configure.in"; exit 1
fi
+VERSIONRC="$VERSION"
+RELEASE="RELEASE_${VERSION//\./_}"
-smartmontools_release_date=`date -u +"%Y/%m/%d"`
+if [ "$RC" ]; then
+ VERSIONRC="${VERSION}-${RC/#RC/rc}"
+ RELEASE="${RELEASE}_${RC}"
+fi
+
+if [ -e "../../tags/$RELEASE" ]; then
+ echo "tags/$RELEASE exists"; exit 1
+fi
+
+echo "r$REV: Release $VERSIONRC $RELEASE"
+set -v
+
+# Update timestamp
+smartmontools_release_date=`date -u +"%Y-%m-%d"`
smartmontools_release_time=`date -u +"%T %Z"`
cat configure.in | sed "s|smartmontools_release_date=.*|smartmontools_release_date=${smartmontools_release_date}|" > configure.tmp
cat configure.tmp | sed "s|smartmontools_release_time=.*|smartmontools_release_time=\"${smartmontools_release_time}\"|" > configure.in
rm -f configure.tmp
-./autogen.sh
-
-get_release
-
-# tag CVS version
-if [ $USECVS -ne 0 ] ; then
- setup_cvs
- cvs commit -m "Release $VERSION $RELEASE"
- cvs tag -d $RELEASE
- cvs tag $RELEASE
+# Create tag and commit
+cd ../..
+if [ "$COMMIT" = "yes" ]; then
+ svn mkdir tags/$RELEASE
+ svn copy trunk/smartmontools tags/$RELEASE/smartmontools
+ svn commit -m "Release $VERSIONRC $RELEASE"
fi
+cd trunk/smartmontools
+
+# Build
+./autogen.sh
-# build .tar.gz
-rm -rf build
mkdir build
cd build
../configure
make distcheck || exit 1
+make maintainer-clean
cd ..
-# increase release number:
-inc_release
-if [ $USECVS -ne 0 ] ; then
- perl -p -i.bak -e "s/$PERL_OLD/$PERL_NEW/" configure.in
-fi
+TARFILE=smartmontools-$VERSIONRC.tar.gz
-cp -f build/smartmontools-$VERSION.tar.gz .
-if [ "$KEYID" ]; then
- gpg --default-key $KEYID --armor --detach-sign ./smartmontools-$VERSION.tar.gz
+mv -f build/smartmontools-$VERSION.tar.gz $TARFILE
+rm -rvf build
+
+md5sum $TARFILE > $TARFILE.md5
+sha1sum $TARFILE > $TARFILE.sha1
+
+# Increase release number
+if [ -z "$RC" ]; then
+ inc_release
+ if [ "$COMMIT" = "yes" ]; then
+ perl -p -i.bak -e "s/$PERL_OLD/$PERL_NEW/" configure.in
+ # svn commit -m "Bump release number to $NEW_VERSION" configure.in
+ fi
fi
-# cleanup
-rm -rf autom4te.cache build/ config.h.in Makefile.in examplescripts/Makefile.in \
- depcomp mkinstalldirs install-sh configure config.guess config.sub \
- aclocal.m4 missing *.bak
#include <stdexcept>
-const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.207 2009/07/04 23:24:37 manfred99 Exp $"
+const char *knowndrives_c_cvsid="$Id: knowndrives.cpp 2986 2009-11-16 22:43:50Z manfred99 $"
ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
#define MODEL_STRING_LENGTH 40
"", "", ""
},
{ "OCZ Vertex SSD",
- "OCZ-VERTEX.*",
- "", "", ""
+ "OCZ[ -]VERTEX.*",
+ "", "",
+ " -v 9,raw64"
+ " -v 12,raw64"
+ " -v 184,raw64,Initial_Bad_Block_Count"
+ " -v 195,raw64,Program_Failure_Blk_Ct"
+ " -v 196,raw64,Erase_Failure_Blk_Ct"
+ " -v 197,raw64,Read_Failure_Blk_Ct"
+ " -v 198,raw64,Read_Sectors_Tot_Ct"
+ " -v 199,raw64,Write_Sectors_Tot_Ct"
+ " -v 200,raw64,Read_Commands_Tot_Ct"
+ " -v 201,raw64,Write_Commands_Tot_Ct"
+ " -v 202,raw64,Error_Bits_Flash_Tot_Ct"
+ " -v 203,raw64,Corr_Read_Errors_Tot_Ct"
+ " -v 204,raw64,Bad_Block_Full_Flag"
+ " -v 205,raw64,Max_PE_Count_Spec"
+ " -v 206,raw64,Min_Erase_Count"
+ " -v 207,raw64,Max_Erase_Count"
+ " -v 208,raw64,Average_Erase_Count"
+ " -v 209,raw64,Remaining_Lifetime_Perc"
+ },
+ { "OCZ Agility SSD",
+ "OCZ[ -]AGILITY",
+ "", "",
+ " -v 9,raw64"
+ " -v 12,raw64"
+ " -v 184,raw64,Initial_Bad_Block_Count"
+ " -v 195,raw64,Program_Failure_Blk_Ct"
+ " -v 196,raw64,Erase_Failure_Blk_Ct"
+ " -v 197,raw64,Read_Failure_Blk_Ct"
+ " -v 198,raw64,Read_Sectors_Tot_Ct"
+ " -v 199,raw64,Write_Sectors_Tot_Ct"
+ " -v 200,raw64,Read_Commands_Tot_Ct"
+ " -v 201,raw64,Write_Commands_Tot_Ct"
+ " -v 202,raw64,Error_Bits_Flash_Tot_Ct"
+ " -v 203,raw64,Corr_Read_Errors_Tot_Ct"
+ " -v 204,raw64,Bad_Block_Full_Flag"
+ " -v 205,raw64,Max_PE_Count_Spec"
+ " -v 206,raw64,Min_Erase_Count"
+ " -v 207,raw64,Max_Erase_Count"
+ " -v 208,raw64,Average_Erase_Count"
+ " -v 209,raw64,Remaining_Lifetime_Perc"
+ },
+ { "Intel X25-E SSD",
+ "SSDSA2SH(032|064)G1.* INTEL",
+ "", "",
+ "-v 225,raw48,Host_Writes_Count"
},
{ "Transcend Solid-State Drive",
"TS(8|16|32|64|128)GSSD25-(M|S)",
"",
"IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
"Please see http://www.geocities.com/dtla_update/index.html#rel and\n"
- "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
- "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
+ "http://www.ibm.com/pc/support/site.wss/MIGR-42215.html",
""
},
{ "IBM Deskstar 40GV & 75GXP series (A5AA/A6AA firmware)",
"",
"IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
"Please see http://www.geocities.com/dtla_update/ and\n"
- "http://www-3.ibm.com/pc/support/site.wss/document.do?lndocid=MIGR-42215 or\n"
- "http://www-1.ibm.com/support/docview.wss?uid=psg1MIGR-42215",
+ "http://www.ibm.com/pc/support/site.wss/MIGR-42215.html",
""
},
{ "", // ExcelStor J240, J340, J360, J680, and J880
},
{ "Fujitsu MHY2 BH series",
"FUJITSU MHY2(04|06|08|10|12|16|20|25)0BH.*",
- "", "", ""
+ "", "",
+ "-v 240,raw48,Transfer_Error_Rate"
},
{ "Fujitsu MHW2 BH series",
"FUJITSU MHW2(04|06|08|10|12|16)0BH.*",
"(Hitachi |HITACHI )?HTS5425(80|12|16|20|25)K9(A3|SA)00",
"", "", ""
},
+ { "Hitachi Travelstar 5K320 series",
+ "(Hitachi |HITACHI )?HT(S|E)5432(80|12|16|25|32)L9(A300|SA01)",
+ "", "", ""
+ },
{ "Hitachi Travelstar 7K60",
"(Hitachi )?HTS726060M9AT00",
"", "", ""
"(Hitachi )?HDT7210((16|25)SLA380|(32|50|64|75|10)SLA360)",
"", "", ""
},
+ { "Hitachi Deskstar 7K2000",
+ "Hitachi HDS722020ALA330",
+ "", "", ""
+ },
{ "Hitachi Ultrastar 7K1000",
"(Hitachi )?HUA7210(50|75|10)KLA330",
"", "", ""
"ST9((80|120|160)411|(250|320)421)ASG?",
"", "", ""
},
+ { "Seagate Momentus 7200.4 series",
+ "ST9(160412|250410|320423|500420)ASG?",
+ "", "", ""
+ },
+ { "Seagate Momentus 7200 FDE.2 series",
+ "ST9((160413|25041[12]|320426|50042[12])AS|(16041[89]|2504[16]4|32042[67]|500426)ASG)",
+ "", "", ""
+ },
{ "Seagate Medalist 1010, 1721, 2120, 3230 and 4340", // ATA2, with -t permissive
"ST3(1010|1721|2120|3230|4340)A",
"", "", ""
},
{ "Seagate Barracuda 7200.11 family", // fixed firmware
"ST3(160813|320[68]13|640[36]23|1000333|1500341)AS?",
- "SD1B", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
+ "SD[12]B", // http://seagate.custkb.com/seagate/crm/selfservice/search.jsp?DocId=207957
"", ""
},
{ "Seagate Barracuda 7200.11 family", // buggy firmware
"WDC WD((360|740|800)GD|(360|740|1500)ADF[DS])-.*",
"", "", ""
},
+ { "Western Digital Raptor X",
+ "WDC WD1500AHFD-.*",
+ "", "", ""
+ },
{ "Western Digital VelociRaptor family",
"WDC WD((1500|3000)B|3000G)LFS-.*",
"", "", ""
"WDC WD(8|12|16|25|32)00B[EJ]KT-.*",
"", "", ""
},
+ { "Western Digital My Passport Essential hard drive (USB interface)",
+ "WDC WD3200BMVU-.*",
+ "", "", ""
+ },
+ { "Western Digital My Passport hard drive (USB interface)",
+ "WDC WD3200BMVV-.*",
+ "", "", ""
+ },
{ "Quantum Bigfoot series",
"QUANTUM BIGFOOT TS10.0A",
"", "", ""
}
// Parse '-v' and '-F' options in preset string, return false on error.
-static bool parse_presets(const char * presets, unsigned char * opts, unsigned char & fix_firmwarebug)
+static bool parse_presets(const char * presets, ata_vendor_attr_defs & defs,
+ unsigned char & fix_firmwarebug)
{
for (int i = 0; ; ) {
i += strspn(presets+i, " \t");
if (!(sscanf(presets+i, "-%c %40[^ ]%n", &opt, arg, &len) >= 2 && len > 0))
return false;
if (opt == 'v') {
- // Parse "-v N,option"
- unsigned char newopts[MAX_ATTRIBUTE_NUM] = {0, };
- if (parse_attribute_def(arg, newopts))
+ // Parse "-v N,format[,name]"
+ if (!parse_attribute_def(arg, defs, PRIOR_DATABASE))
return false;
- // Set only if not set by user
- for (int j = 0; j < MAX_ATTRIBUTE_NUM; j++)
- if (newopts[j] && !opts[j])
- opts[j] = newopts[j];
}
else if (opt == 'F') {
unsigned char fix;
unsigned char fix_firmwarebug = 0;
bool first_preset = true;
if (*dbentry->presets) {
- unsigned char opts[MAX_ATTRIBUTE_NUM] = {0,};
- if (!parse_presets(dbentry->presets, opts, fix_firmwarebug)) {
+ ata_vendor_attr_defs defs;
+ if (!parse_presets(dbentry->presets, defs, fix_firmwarebug)) {
pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
errcnt++;
}
for (int i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
- char out[256];
- if (opts[i]) {
- ataPrintSmartAttribName(out, i, opts);
+ if (defs[i].priority != PRIOR_DEFAULT) {
// Use leading zeros instead of spaces so that everything lines up.
- out[0] = (out[0] == ' ') ? '0' : out[0];
- out[1] = (out[1] == ' ') ? '0' : out[1];
- pout("%-*s %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "", out);
+ pout("%-*s %03d %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "",
+ i, ata_get_smart_attr_name(i, defs).c_str());
first_preset = false;
}
}
// (if any) for the given drive in knowndrives[]. Values that have
// already been set in opts will not be changed. Returns false if drive
// not recognized.
-bool apply_presets(const ata_identify_device *drive, unsigned char * opts,
+bool apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs & defs,
unsigned char & fix_firmwarebug, bool fix_swapped_id)
{
// get the drive's model/firmware strings
if (*dbentry->presets) {
// Apply presets
- if (!parse_presets(dbentry->presets, opts, fix_firmwarebug))
+ if (!parse_presets(dbentry->presets, defs, fix_firmwarebug))
pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
}
return true;
break;
case 4:
if (!token.value.empty()) {
- unsigned char opts[MAX_ATTRIBUTE_NUM] = {0, }; unsigned char fix = 0;
- if (!parse_presets(token.value.c_str(), opts, fix)) {
+ ata_vendor_attr_defs defs; unsigned char fix = 0;
+ if (!parse_presets(token.value.c_str(), defs, fix)) {
pout("%s(%d): Syntax error in preset option string\n", path, token.line);
ok = false;
}
#ifndef KNOWNDRIVES_H_
#define KNOWNDRIVES_H_
-#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h,v 1.23 2009/04/16 21:24:08 chrfranke Exp $\n"
+#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 2975 2009-10-29 22:52:38Z chrfranke $\n"
/* Structure used to store settings for specific drives in knowndrives[]. The
* elements are used in the following ways:
// (if any) for the given drive in knowndrives[]. Values that have
// already been set in opts will not be changed. Also sets options in
// con. Returns false if drive not recognized.
-bool apply_presets(const ata_identify_device * drive, unsigned char * opts,
+bool apply_presets(const ata_identify_device * drive, ata_vendor_attr_defs & defs,
unsigned char & fix_firmwarebug, bool fix_swapped_id);
// Read drive database from file.
#define PATHINQ_SETTINGS_SIZE 128
#endif
-static __unused const char *filenameandversion="$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $";
+static __unused const char *filenameandversion="$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $";
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $" \
ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
extern smartmonctrl * con;
// global variable holding byte count of allocated memory
long long bytes;
-const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $"
+const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 2973 2009-10-26 22:38:19Z chrfranke $"
DEV_INTERFACE_H_CVSID;
extern smartmonctrl * con; // con->reportscsiioctl
return this;
// Use INQUIRY to detect type
- smart_device * newdev = 0;
- try {
- // 3ware ?
- if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
- close();
- set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
- "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
- return this;
- }
- // SAT or USB ?
- newdev = smi()->autodetect_sat_device(this, req_buff, len);
+ // 3ware ?
+ if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
+ close();
+ set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
+ "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
+ return this;
+ }
+
+ // SAT or USB ?
+ {
+ smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
if (newdev)
// NOTE: 'this' is now owned by '*newdev'
return newdev;
}
- catch (...) {
- // Cleanup if exception occurs after newdev was allocated
- delete newdev;
- throw;
- }
// Nothing special found
return this;
for (i = 0; i < numata; i++) {
ata_device * atadev = get_ata_device(atanames[i], type);
if (atadev)
- devlist.add(atadev);
+ devlist.push_back(atadev);
}
for (i = 0; i < numscsi; i++) {
if(!*type) { // try USB autodetection if no type specified
smart_device * smartdev = autodetect_smart_device(scsinames[i]);
if(smartdev)
- devlist.add(smartdev);
+ devlist.push_back(smartdev);
}
else {
scsi_device * scsidev = get_scsi_device(scsinames[i], type);
if (scsidev)
- devlist.add(scsidev);
+ devlist.push_back(scsidev);
}
}
return true;
#define ARGUSED(x) ((void)(x))
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 2951 2009-10-08 23:43:46Z samm2 $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 2993 2009-12-04 17:29:50Z chrfranke $" \
ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
/* for passing global control variables */
#define SG_IO_RESP_SENSE_LEN 64 /* large enough see buffer */
#define LSCSI_DRIVER_MASK 0xf /* mask out "suggestions" */
#define LSCSI_DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */
+#define LSCSI_DID_ERROR 0x7 /* Need to work around aacraid driver quirk */
#define LSCSI_DRIVER_TIMEOUT 0x6
#define LSCSI_DID_TIME_OUT 0x3
#define LSCSI_DID_BUS_BUSY 0x2
(LSCSI_DID_TIME_OUT == io_hdr.host_status))
return -ETIMEDOUT;
else
- return -EIO; /* catch all */
+ /* Check for DID_ERROR - workaround for aacraid driver quirk */
+ if (LSCSI_DID_ERROR != io_hdr.host_status) {
+ return -EIO; /* catch all if not DID_ERR */
+ }
}
if (0 != masked_driver_status) {
if (LSCSI_DRIVER_TIMEOUT == masked_driver_status)
smart_device * linux_megaraid_device::autodetect_open()
{
+ int report = con->reportscsiioctl;
+
// Open device
if (!open())
return this;
if (len < 36)
return this;
- printf("Got MegaRAID inquiry.. %s\n", req_buff+8);
+ if (report)
+ printf("Got MegaRAID inquiry.. %s\n", req_buff+8);
// Use INQUIRY to detect type
- smart_device * newdev = 0;
- try {
+ {
// SAT or USB ?
- newdev = smi()->autodetect_sat_device(this, req_buff, len);
+ ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
if (newdev)
// NOTE: 'this' is now owned by '*newdev'
return newdev;
}
- catch (...) {
- // Cleanup if exception occurs after newdev was allocated
- delete newdev;
- throw;
- }
// Nothing special found
return this;
// Emulate SMART STATUS CHECK drive reply
// smartctl fail to work without this
if(iop->cmnd[2]==0x2c) {
- iop->resp_sense_len=22;
- iop->sensep[0]=0x72; // response code
- iop->sensep[7]=0x0e; // no idea what it is, copied from sat device answer
- iop->sensep[8]=0x09; //
- iop->sensep[17]=0x4f; // lm
- iop->sensep[19]=0xc2; // lh
+ iop->resp_sense_len=22; // copied from real response
+ iop->sensep[0]=0x72; // descriptor format
+ iop->sensep[7]=0x0e; // additional length
+ iop->sensep[8]=0x09; // description pointer
+ iop->sensep[17]=0x4f; // low cylinder GOOD smart status
+ iop->sensep[19]=0xc2; // high cylinder GOOD smart status
}
return true;
}
passthru->size++;
}
else
- set_err(EINVAL);
+ return set_err(EINVAL);
// Now send the command down through an ioctl()
int ioctlreturn;
}
// Return register values
- {
+ if (passthru) {
ata_out_regs_48bit & r = out.out_regs;
r.error = passthru->features;
r.sector_count_16 = passthru->sector_count;
int avail_len = req_buff[4] + 5;
int len = (avail_len < req_len ? avail_len : req_len);
if (len < 36)
- return this;
+ return this;
// Use INQUIRY to detect type
- smart_device * newdev = 0;
- try {
- // 3ware ?
- if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
- close();
- set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
- "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
- return this;
- }
- // DELL?
- if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
- close();
- set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
- return this;
- }
-
- // Marvell ?
- if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) {
- //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
- close();
- newdev = new linux_marvell_device(smi(), get_dev_name(), get_req_type());
- newdev->open(); // TODO: Can possibly pass open fd
- delete this;
- return newdev;
- }
- // SAT or USB ?
- newdev = smi()->autodetect_sat_device(this, req_buff, len);
+ // 3ware ?
+ if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
+ close();
+ set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
+ "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
+ return this;
+ }
+
+ // DELL?
+ if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
+ close();
+ set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
+ return this;
+ }
+
+ // Marvell ?
+ if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) {
+ //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
+ close();
+ smart_device_auto_ptr newdev(
+ new linux_marvell_device(smi(), get_dev_name(), get_req_type())
+ );
+ newdev->open(); // TODO: Can possibly pass open fd
+ delete this;
+ return newdev.release();
+ }
+
+ // SAT or USB ?
+ {
+ smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
if (newdev)
// NOTE: 'this' is now owned by '*newdev'
return newdev;
}
- catch (...) {
- // Cleanup if exception occurs after newdev was allocated
- delete newdev;
- throw;
- }
// Nothing special found
return this;
else
dev = new linux_ata_device(this, name, req_type);
if (dev) // autodetect_smart_device() may return nullptr.
- devlist.add(dev);
+ devlist.push_back(dev);
}
}
// Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_win32.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char *os_XXXX_c_cvsid="$Id: os_win32.cpp 2973 2009-10-26 22:38:19Z chrfranke $"
ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
if (!(devmap & (1 << i)))
continue;
sprintf(name, "/dev/hd%c", 'a'+i);
- devlist.add( new win_ata_device(this, name, "ata") );
+ devlist.push_back( new win_ata_device(this, name, "ata") );
}
return true;
}
for (int pi = 0; pi < 32; pi++) {
if (vers_ex.dwDeviceMapEx & (1L << pi)) {
sprintf(name, "/dev/sd%c,%u", 'a'+i, pi);
- devlist.add( new win_ata_device(this, name, "ata") );
+ devlist.push_back( new win_ata_device(this, name, "ata") );
}
}
continue;
// Driver supports SMART_GET_VERSION or STORAGE_QUERY_PROPERTY returns ATA/SATA
sprintf(name, "/dev/sd%c", 'a'+i);
- devlist.add( new win_ata_device(this, name, "ata") );
+ devlist.push_back( new win_ata_device(this, name, "ata") );
}
return true;
pout(" ID %u: Device Type=0x%02x\n", id, srb.t.devtype);
char name[20];
sprintf(name, "/dev/scsi%u%u", ad, id);
- devlist.add( new win_aspi_device(this, name, "scsi") );
+ devlist.push_back( new win_aspi_device(this, name, "scsi") );
}
else if (con->reportscsiioctl)
pout(" ID %u: Device Type=0x%02x (ignored)\n", id, srb.t.devtype);
continue;
// STORAGE_QUERY_PROPERTY returned SCSI/SAS/...
sprintf(name, "/dev/sd%c", 'a'+i);
- devlist.add( new win_scsi_device(this, name, "scsi") );
+ devlist.push_back( new win_scsi_device(this, name, "scsi") );
}
return true;
}
#include "dev_ata_cmd_set.h" // ata_device_with_command_set
#include "dev_tunnelled.h" // tunnelled_device<>
-const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 2923 2009-09-24 20:10:38Z chrfranke $";
+const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 2988 2009-11-29 16:21:07Z samm2 $";
/* for passing global control variables */
extern smartmonctrl *con;
if (!scsidev->is_open())
return 0;
- ata_device * atadev = 0;
- try {
- // SAT ?
- if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) { // TODO: Linux-specific?
- atadev = new sat_device(this, scsidev, "");
- if (has_sat_pass_through(atadev))
- return atadev; // Detected SAT
- atadev->release(scsidev);
- delete atadev;
- }
-
-/* The new usbcypress_device(this, scsidev, "", 0x24) sends vendor specific comand to non-cypress devices.
- * It's dangerous as other device may interpret such command as own valid vendor specific command.
- * I commented it out untill problem resolved
- */
-#if 0
- // USB ?
- {
- atadev = new usbcypress_device(this, scsidev, "", 0x24);
- if (has_usbcypress_pass_through(atadev,
- (inqdata && inqsize >= 36 ? (const char*)inqdata + 8 : 0),
- (inqdata && inqsize >= 36 ? (const char*)inqdata + 16 : 0) ))
- return atadev; // Detected USB
- atadev->release(scsidev);
- delete atadev;
- }
-#endif
- }
- catch (...) {
- if (atadev) {
- atadev->release(scsidev);
- delete atadev;
- }
- throw;
+ // SAT ?
+ if (inqdata && inqsize >= 36 && !memcmp(inqdata + 8, "ATA ", 8)) { // TODO: Linux-specific?
+ ata_device_auto_ptr atadev( new sat_device(this, scsidev, "") , scsidev);
+ if (has_sat_pass_through(atadev.get()))
+ return atadev.release(); // Detected SAT
}
return 0;
{ 0x04fc, 0x0c15, 0xf615, d_sunplus }, // SunPlus SPDIF215
{ 0x04fc, 0x0c25, 0x0103, d_sunplus }, // SunPlus SPDIF225 (USB+SATA->SATA)
// Iomega
+ { 0x059b, 0x0272, -1, d_cypress }, // Iomega LPHD080-0
{ 0x059b, 0x0275, 0x0001, d_unsup }, // Iomega MDHD500-U
// LaCie
{ 0x059f, 0x0651, -1, d_unsup }, // LaCie hard disk (FA Porsche design)
{ 0x059f, 0x1018, -1, d_sat }, // LaCie hard disk (Neil Poulton design)
// In-System Design
{ 0x05ab, 0x0060, 0x1101, d_cypress }, // In-System/Cypress ISD-300A1
+ // Genesys Logic
+ { 0x05e3, 0x0702, -1, d_unsup }, // Genesys Logic GL881E
+ { 0x05e3, 0x0718, 0x0041, d_sat }, // Genesys Logic ? (TODO: requires '-T permissive')
// Prolific
{ 0x067b, 0x3507, 0x0001, d_unsup }, // Prolific PL3507
+ // Freecom
+ { 0x07ab, 0xfc8e, 0x010f, d_sunplus }, // Freecom Hard Drive XS
// Toshiba
{ 0x0930, 0x0b09, -1, d_sunplus }, // Toshiba PX1396E-3T01 (similar to Dura Micro 501)
// Seagate
{ 0x0d49, 0x7410, 0x0122, d_sat }, // Maxtor Basics Desktop
{ 0x0d49, 0x7450, 0x0122, d_sat }, // Maxtor Basics Portable
// Western Digital
+ { 0x1058, 0x0702, 0x0104, d_sat }, // WD My Passport Portable
{ 0x1058, 0x0704, 0x0175, d_sat }, // WD My Passport Essential
{ 0x1058, 0x0705, 0x0175, d_sat }, // WD My Passport Elite
+ { 0x1058, 0x070a, 0x1028, d_sat }, // WD My Passport 070A
{ 0x1058, 0x0906, 0x0012, d_sat }, // WD My Book ES
{ 0x1058, 0x1001, 0x0104, d_sat }, // WD Elements Desktop
{ 0x1058, 0x1003, 0x0175, d_sat }, // WD Elements Desktop WDE1UBK...
{ 0x1058, 0x1100, 0x0165, d_sat }, // WD My Book Essential
{ 0x1058, 0x1102, 0x1028, d_sat }, // WD My Book
// Initio
+ { 0x13fd, 0x0540, -1, d_unsup }, // Initio 316000
{ 0x13fd, 0x1240, 0x0104, d_sat }, // Initio ? (USB->SATA)
{ 0x13fd, 0x1340, 0x0208, d_sat }, // Initio ? (USB+SATA->SATA)
// JMicron
.ig
Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- $Id: smartctl.8.in 2922 2009-09-22 16:27:33Z chrfranke $
+ $Id: smartctl.8.in 2978 2009-10-30 23:20:39Z chrfranke $
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
(SATA Phy Event Counters) to file log.bin.
.TP
-.B \-v N,OPTION, \-\-vendorattribute=N,OPTION
-[ATA only] Sets a vendor\-specific display OPTION for Attribute N. This
-option may be used multiple times. Valid arguments to this option are:
+.B \-v ID,FORMAT[,NAME], \-\-vendorattribute=ID,FORMAT[,NAME]
+[ATA only] Sets a vendor\-specific raw value print FORMAT and
+optional NAME for Attribute ID.
+This option may be used multiple times.
-.I help
+The Attribute ID can be in the range 1 to 255. If \'N\' is specified as
+ID, the settings for all Attributes are changed. The NAME is a string of
+letters, digits and underscore.
+
+.I \-v help
\- Prints (to STDOUT) a list of all valid arguments to this option,
then exits.
-.I 9,minutes
-\- Raw Attribute number 9 is power\-on time in minutes. Its raw value
+Valid arguments for FORMAT are:
+
+.I raw8
+\- Print the Raw value as six 8\-bit unsigned base\-10 integers.
+This may be useful for decoding the meaning of the Raw value.
+
+.I raw16
+\- Print the Raw value as three 16\-bit unsigned base\-10 integers.
+This may be useful for decoding the meaning of the Raw value.
+
+.I raw48
+\- Print the Raw value as a 48\-bit unsigned base\-10 integer.
+This is the default for most attributes.
+
+.I hex48
+\- Print the Raw value as a 12 digit hexadecimal number.
+This may be useful for decoding the meaning of the Raw value.
+
+.I raw64
+\- Print the Raw value as a 64\-bit unsigned base\-10 integer.
+This includes two bytes from the normalized and worst attribute value.
+This new raw format is used by some recent SSD devices.
+
+.I hex64
+\- Print the Raw value as a 16 digit hexadecimal number.
+This includes two bytes from the normalized and worst attribute value.
+This new raw format is used by some recent SSD devices.
+
+.I min2hour
+\- Raw Attribute is power\-on time in minutes. Its raw value
will be displayed in the form "Xh+Ym". Here X is hours, and Y is
minutes in the range 0\-59 inclusive. Y is always printed with two
digits, for example "06" or "31" or "00".
-.I 9,seconds
-\- Raw Attribute number 9 is power\-on time in seconds. Its raw value
+.I sec2hour
+\- Raw Attribute is power\-on time in seconds. Its raw value
will be displayed in the form "Xh+Ym+Zs". Here X is hours, Y is
minutes in the range 0\-59 inclusive, and Z is seconds in the range
0\-59 inclusive. Y and Z are always printed with two digits, for
example "06" or "31" or "00".
-.I 9,halfminutes
-\- Raw Attribute number 9 is power\-on time, measured in units of 30
+.I halfmin2hour
+\- Raw Attribute is power\-on time, measured in units of 30
seconds. This format is used by some Samsung disks. Its raw value
will be displayed in the form "Xh+Ym". Here X is hours, and Y is
minutes in the range 0\-59 inclusive. Y is always printed with two
digits, for example "06" or "31" or "00".
-.I 9,temp
-\- Raw Attribute number 9 is the disk temperature in Celsius.
+.I tempminmax
+\- Raw Attribute is the disk temperature in Celsius. Info about
+Lifetime Min/Max temperature is printed if available. This is the
+default for Attributes 190 and 194.
-.I 192,emergencyretractcyclect
-\- Raw Attribute number 192 is the Emergency Retract Cycle Count.
+.I temp10x
+\- Raw Attribute is ten times the disk temperature in Celsius.
-.I 193,loadunload
-\- Raw Attribute number 193 contains two values. The first is the
+.I raw16(raw16)
+\- Print the raw attribute as a 16\-bit value and two optional
+16\-bit values if these words are nonzero. This is the default
+for Attributes 5 and 196.
+
+.I raw16(avg16)
+\- Raw attribute is spin-up time. It is printed as a 16-bit value
+and an optional "Average" 16-bit value if the word is nonzero.
+This is the default for Attribute 3.
+
+.I raw24/raw24
+\- Raw Attribute contains two 24\-bit values. The first is the
number of load cycles. The second is the number of unload cycles.
The difference between these two values is the number of times that
the drive was unexpectedly powered off (also called an emergency
emergency unload is equivalent to that created by one hundred normal
unloads.
+The following old arguments to \'\-v\' are also still valid:
+
+.I 9,minutes
+\- same as:
+.I 9,min2hour,Power_On_Minutes.
+
+.I 9,seconds
+\- same as:
+.I 9,sec2hour,Power_On_Seconds.
+
+.I 9,halfminutes
+\- same as:
+.I 9,halfmin2hour,Power_On_Half_Minutes.
+
+.I 9,temp
+\- same as:
+.I 9,tempminmax,Temperature_Celsius.
+
+.I 192,emergencyretractcyclect
+\- same as:
+.I 192,raw48,Emerg_Retract_Cycle_Ct
+
+.I 193,loadunload
+\- same as:
+.I 193,raw24/raw24.
+
.I 194,10xCelsius
-\- Raw Attribute number 194 is ten times the disk temperature in
-Celsius. This is used by some Samsung disks (example: model SV1204H
-with RK100\-13 firmware).
+\- same as:
+.I 194,temp10x,Temperature_Celsius_x10.
.I 194,unknown
-\- Raw Attribute number 194 is NOT the disk temperature, and its
-interpretation is unknown. This is primarily useful for the \-P
-(presets) option.
+\- same as:
+.I 194,raw48,Unknown_Attribute.
.I 197,increasing
-\- Raw Attribute number 197 (Current Pending Sector Count) is not
-reset if uncorrectable sectors are reallocated.
+\- same as:
+.I 197,raw48,Total_Pending_Sectors.
+Also means that Attribute number 197 (Current Pending Sector Count)
+is not reset if uncorrectable sectors are reallocated
+(see \fBsmartd.conf\fP(5) man page).
.I 198,increasing
-\- Raw Attribute number 198 (Offline Uncorrectable Sector Count) is not
-reset if uncorrectable sectors are reallocated.
+\- same as:
+.I 198,raw48,Total_Offl_Uncorrectabl.
+Also means that Attribute number 198 (Offline Uncorrectable Sector Count)
+is not reset if uncorrectable sectors are reallocated
+(see \fBsmartd.conf\fP(5) man page).
.I 198,offlinescanuncsectorct
-\- Raw Attribute number 198 is the Offline Scan UNC Sector Count.
+\- same as:
+.I 198,raw48,Offline_Scan_UNC_SectCt.
.I 200,writeerrorcount
-\- Raw Attribute number 200 is the Write Error Count.
+\- same as:
+.I 200,raw48,Write_Error_Count.
.I 201,detectedtacount
-\- Raw Attribute number 201 is the Detected TA Count.
+\- same as:
+.I 201,raw48,Detected_TA_Count.
.I 220,temp
-\- Raw Attribute number 220 is the disk temperature in Celsius.
+\- same as:
+.I 220,raw48,Temperature_Celsius.
Note: a table of hard drive models, listing which Attribute
corresponds to temperature, can be found at:
\fBhttp://www.guzu.net/linux/hddtemp.db\fP
-.I N,raw8
-\- Print the Raw value of Attribute N as six 8\-bit unsigned base\-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw8\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw8\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw16
-\- Print the Raw value of Attribute N as three 16\-bit unsigned base\-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw16\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw16\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw48
-\- Print the Raw value of Attribute N as a 48\-bit unsigned base\-10
-integer. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw48\' prints Raw values for ALL Attributes in
-this form. The form (for example) \'123,raw48\' only prints the Raw
-value for Attribute 123 in this form.
-
.TP
.B \-F TYPE, \-\-firmwarebug=TYPE
[ATA only] Modifies the behavior of \fBsmartctl\fP to compensate for some
.SH
SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 2922 2009-09-22 16:27:33Z chrfranke $
+$Id: smartctl.8.in 2978 2009-10-30 23:20:39Z chrfranke $
.\" Local Variables:
.\" mode: nroff
.\" End:
#include "smartctl.h"
#include "utility.h"
-const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 2975 2009-10-29 22:52:38Z chrfranke $"
CONFIG_H_CVSID EXTERN_H_CVSID SMARTCTL_H_CVSID;
// This is a block containing all the "control variables". We declare
create_vendor_attribute_arg_list().c_str());
EXIT(0);
}
- if (parse_attribute_def(optarg, ataopts.attributedefs))
+ if (!parse_attribute_def(optarg, ataopts.attribute_defs, PRIOR_USER))
badarg = true;
break;
case 'P':
if (!smi())
return 1;
- int retval = 0;
+ // define control block for external functions
+ smartmonctrl control;
+ con=&control;
- smart_device * dev = 0;
- try {
- // define control block for external functions
- smartmonctrl control;
- con=&control;
-
- // Parse input arguments
- ata_print_options ataopts;
- scsi_print_options scsiopts;
- const char * type = parse_options(argc, argv, ataopts, scsiopts);
-
- // '-d test' -> Report result of autodetection
- bool print_type_only = (type && !strcmp(type, "test"));
- if (print_type_only)
- type = 0;
-
- const char * name = argv[argc-1];
-
- if (!strcmp(name,"-")) {
- // Parse "smartctl -r ataioctl,2 ..." output from stdin
- if (type || print_type_only) {
- pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n");
- UsageSummary();
- return FAILCMD;
- }
- dev = get_parsed_ata_device(smi(), name);
- }
- else
- // get device of appropriate type
- dev = smi()->get_smart_device(name, type);
+ // Parse input arguments
+ ata_print_options ataopts;
+ scsi_print_options scsiopts;
+ const char * type = parse_options(argc, argv, ataopts, scsiopts);
- if (!dev) {
- pout("%s: %s\n", name, smi()->get_errmsg());
- if (type)
- printvalidarglistmessage('d');
- else
- pout("Smartctl: please specify device type with the -d option.\n");
+ // '-d test' -> Report result of autodetection
+ bool print_type_only = (type && !strcmp(type, "test"));
+ if (print_type_only)
+ type = 0;
+
+ const char * name = argv[argc-1];
+
+ smart_device_auto_ptr dev;
+ if (!strcmp(name,"-")) {
+ // Parse "smartctl -r ataioctl,2 ..." output from stdin
+ if (type || print_type_only) {
+ pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n");
UsageSummary();
return FAILCMD;
}
+ dev = get_parsed_ata_device(smi(), name);
+ }
+ else
+ // get device of appropriate type
+ dev = smi()->get_smart_device(name, type);
+
+ if (!dev) {
+ pout("%s: %s\n", name, smi()->get_errmsg());
+ if (type)
+ printvalidarglistmessage('d');
+ else
+ pout("Smartctl: please specify device type with the -d option.\n");
+ UsageSummary();
+ return FAILCMD;
+ }
- if (print_type_only)
- // Report result of first autodetection
- pout("%s: Device of type '%s' [%s] detected\n",
- dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev));
-
- // Open device
- {
- // Save old info
- smart_device::device_info oldinfo = dev->get_info();
-
- // Open with autodetect support, may return 'better' device
- dev = dev->autodetect_open();
+ if (print_type_only)
+ // Report result of first autodetection
+ pout("%s: Device of type '%s' [%s] detected\n",
+ dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get()));
- // Report if type has changed
- if ((type || print_type_only) && oldinfo.dev_type != dev->get_dev_type())
- pout("%s: Device open changed type from '%s' to '%s'\n",
- dev->get_info_name(), oldinfo.dev_type.c_str(), dev->get_dev_type());
- }
- if (!dev->is_open()) {
- pout("Smartctl open device: %s failed: %s\n", dev->get_info_name(), dev->get_errmsg());
- delete dev;
- return FAILDEV;
- }
+ // Open device
+ {
+ // Save old info
+ smart_device::device_info oldinfo = dev->get_info();
- // now call appropriate ATA or SCSI routine
- if (print_type_only)
- pout("%s: Device of type '%s' [%s] opened\n",
- dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev));
- else if (dev->is_ata())
- retval = ataPrintMain(dev->to_ata(), ataopts);
- else if (dev->is_scsi())
- retval = scsiPrintMain(dev->to_scsi(), scsiopts);
- else
- // we should never fall into this branch!
- pout("%s: Neither ATA nor SCSI device\n", dev->get_info_name());
+ // Open with autodetect support, may return 'better' device
+ dev.replace( dev->autodetect_open() );
- dev->close();
- delete dev;
+ // Report if type has changed
+ if ((type || print_type_only) && oldinfo.dev_type != dev->get_dev_type())
+ pout("%s: Device open changed type from '%s' to '%s'\n",
+ dev->get_info_name(), oldinfo.dev_type.c_str(), dev->get_dev_type());
}
- catch (...) {
- delete dev;
- throw;
+ if (!dev->is_open()) {
+ pout("Smartctl open device: %s failed: %s\n", dev->get_info_name(), dev->get_errmsg());
+ return FAILDEV;
}
+
+ // now call appropriate ATA or SCSI routine
+ int retval = 0;
+ if (print_type_only)
+ pout("%s: Device of type '%s' [%s] opened\n",
+ dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev.get()));
+ else if (dev->is_ata())
+ retval = ataPrintMain(dev->to_ata(), ataopts);
+ else if (dev->is_scsi())
+ retval = scsiPrintMain(dev->to_scsi(), scsiopts);
+ else
+ // we should never fall into this branch!
+ pout("%s: Neither ATA nor SCSI device\n", dev->get_info_name());
+
+ dev->close();
return retval;
}
}
catch (const std::bad_alloc & /*ex*/) {
// Memory allocation failed (also thrown by std::operator new)
- pout("Smartctl: Out of memory\n");
+ printf("Smartctl: Out of memory\n");
status = FAILCMD;
}
catch (const std::exception & ex) {
// Other fatal errors
- pout("Smartctl: Exception: %s\n", ex.what());
+ printf("Smartctl: Exception: %s\n", ex.what());
status = FAILCMD;
}
return status;
.ig
Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-$Id: smartd.8.in 2921 2009-09-20 19:19:32Z samm2 $
+$Id: smartd.8.in 2977 2009-10-30 22:29:05Z chrfranke $
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
[NEW EXPERIMENTAL SMARTD FEATURE] Read the drive database from FILE.
The new database replaces the built in database by default. If \'+\' is
specified, then the new entries prepend the built in entries.
-Please see the \fBsmartctl\fP man page for further details.
+Please see the \fBsmartctl\fP(8) man page for further details.
.TP
.B \-c FILE, \-\-configfile=FILE
SATA disks hosted by the Areca controller appear to \fBsmartd\fP as
normal ATA devices. Hence all the ATA directives can be used for
these disks. Areca firmware version 1.46 or later which supports
-smartmontools must be used; Please see the \fBsmartctl\fP man page for
-further details.
+smartmontools must be used; Please see the \fBsmartctl\fP(8) man page
+for further details.
.TP
.B \-d TYPE
address \fBany\fP of the physical disks (3ware ports), error and log
messages will make the most sense if you always list the 3ware SCSI
logical device corresponding to the particular physical disks. Please
-see the \fBsmartctl\fP man page for further details.
+see the \fBsmartctl\fP(8) man page for further details.
ATA disks behind 3ware controllers may alternatively be accessed via a
character device interface /dev/twe0-15 (3ware 6000/7000/8000
controllers) and /dev/twa0-15 (3ware 9000 series controllers). Note
that the 9000 series controllers may \fBonly\fP be accessed using the
character device interface /dev/twa0-15 and not the SCSI device
-interface /dev/sd?. Please see the \fBsmartctl\fP man page for
+interface /dev/sd?. Please see the \fBsmartctl\fP(8) man page for
further details.
Note that older 3w-xxxx drivers do not pass the \'Enable Autosave\'
[Please see the \fBsmartctl \-F\fP command-line option.]
.TP
-.B \-v N,OPTION
-Modifies the labeling for Attribute N, for disks which use
-non-standard Attribute definitions. This is useful in connection with
-the Attribute tracking/reporting Directives.
-
-This Directive may appear multiple times. Valid arguments to this
-Directive are:
+.B \-v ID,FORMAT[,NAME]
+[ATA only] Sets a vendor\-specific raw value print FORMAT and
+optional NAME for Attribute ID.
+This directive may be used multiple times.
+Please see \fBsmartctl -v\fP command-line option for further details.
-.I 9,minutes
-\- Raw Attribute number 9 is power-on time in minutes. Its raw value
-will be displayed in the form \'Xh+Ym\'. Here X is hours, and Y is
-minutes in the range 0-59 inclusive. Y is always printed with two
-digits, for example \'06\' or \'31\' or \'00\'.
-
-.I 9,seconds
-\- Raw Attribute number 9 is power-on time in seconds. Its raw value
-will be displayed in the form \'Xh+Ym+Zs\'. Here X is hours, Y is
-minutes in the range 0-59 inclusive, and Z is seconds in the range
-0-59 inclusive. Y and Z are always printed with two digits, for
-example \'06\' or \'31\' or \'00\'.
-
-.I 9,halfminutes
-\- Raw Attribute number 9 is power-on time, measured in units of 30
-seconds. This format is used by some Samsung disks. Its raw value
-will be displayed in the form \'Xh+Ym\'. Here X is hours, and Y is
-minutes in the range 0-59 inclusive. Y is always printed with two
-digits, for example \'06\' or \'31\' or \'00\'.
-
-.I 9,temp
-\- Raw Attribute number 9 is the disk temperature in Celsius.
-
-.I 192,emergencyretractcyclect
-\- Raw Attribute number 192 is the Emergency Retract Cycle Count.
-
-.I 193,loadunload
-\- Raw Attribute number 193 contains two values. The first is the
-number of load cycles. The second is the number of unload cycles.
-The difference between these two values is the number of times that
-the drive was unexpectedly powered off (also called an emergency
-unload). As a rule of thumb, the mechanical stress created by one
-emergency unload is equivalent to that created by one hundred normal
-unloads.
-
-.I 194,10xCelsius
-\- Raw Attribute number 194 is ten times the disk temperature in
-Celsius. This is used by some Samsung disks (example: model SV1204H
-with RK100-13 firmware).
-
-.I 194,unknown
-\- Raw Attribute number 194 is NOT the disk temperature, and its
-interpretation is unknown. This is primarily useful for the -P
-(presets) Directive.
+The following arguments affect smartd warning output:
.I 197,increasing
\- Raw Attribute number 197 (Current Pending Sector Count) is not
-reset if uncorrectable sectors are reallocated. This also sets
-\'-C 197+\' if no other \'-C\' directive is specified.
+reset if uncorrectable sectors are reallocated. This sets \'-C 197+\'
+if no other \'-C\' directive is specified.
.I 198,increasing
\- Raw Attribute number 198 (Offline Uncorrectable Sector Count) is not
-reset if uncorrectable sector are reallocated. This also sets
-\'-U 198+\' if no other \'-U\' directive is specified.
-
-.I 198,offlinescanuncsectorct
-\- Raw Attribute number 198 is the Offline Scan UNC Sector Count.
-
-.I 200,writeerrorcount
-\- Raw Attribute number 200 is the Write Error Count.
-
-.I 201,detectedtacount
-\- Raw Attribute number 201 is the Detected TA Count.
-
-.I 220,temp
-\- Raw Attribute number 220 is the disk temperature in Celsius.
-
-Note: a table of hard drive models, listing which Attribute
-corresponds to temperature, can be found at:
-\fBhttp://www.guzu.net/linux/hddtemp.db\fP
-
-.I N,raw8
-\- Print the Raw value of Attribute N as six 8-bit unsigned base-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw8\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw8\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw16
-\- Print the Raw value of Attribute N as three 16-bit unsigned base-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw16\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw16\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw48
-\- Print the Raw value of Attribute N as a 48-bit unsigned base-10
-integer. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw48\' prints Raw values for ALL Attributes in
-this form. The form (for example) \'123,raw48\' only prints the Raw
-value for Attribute 123 in this form.
+reset if uncorrectable sector are reallocated. This sets \'-U 198+\'
+if no other \'-U\' directive is specified.
.TP
.B \-P TYPE
.SH
SVN ID OF THIS PAGE:
-$Id: smartd.8.in 2921 2009-09-20 19:19:32Z samm2 $
+$Id: smartd.8.in 2977 2009-10-30 22:29:05Z chrfranke $
.ig
Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-$Id: smartd.conf.5.in 2921 2009-09-20 19:19:32Z samm2 $
+$Id: smartd.conf.5.in 2977 2009-10-30 22:29:05Z chrfranke $
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
\fBsmartd\fP
will try to open all existing ATA devices (with entries in /dev)
.B /dev/ad[0-9]+
-and all existing SCSI devices
-.B /dev/da[0-9]+.
+and all existing SCSI devices (using CAM subsystem).
Under NetBSD/OpenBSD,
\fBsmartd\fP
will try to open all existing ATA devices (with entries in /dev)
SATA disks hosted by the Areca controller appear to \fBsmartd\fP as
normal ATA devices. Hence all the ATA directives can be used for
these disks. Areca firmware version 1.46 or later which supports
-smartmontools must be used; Please see the \fBsmartctl\fP man page for
-further details.
+smartmontools must be used; Please see the \fBsmartctl\fP(8) man page
+for further details.
.TP
.B \-d TYPE
address \fBany\fP of the physical disks (3ware ports), error and log
messages will make the most sense if you always list the 3ware SCSI
logical device corresponding to the particular physical disks. Please
-see the \fBsmartctl\fP man page for further details.
+see the \fBsmartctl\fP(8) man page for further details.
ATA disks behind 3ware controllers may alternatively be accessed via a
character device interface /dev/twe0-15 (3ware 6000/7000/8000
controllers) and /dev/twa0-15 (3ware 9000 series controllers). Note
that the 9000 series controllers may \fBonly\fP be accessed using the
character device interface /dev/twa0-15 and not the SCSI device
-interface /dev/sd?. Please see the \fBsmartctl\fP man page for
+interface /dev/sd?. Please see the \fBsmartctl\fP(8) man page for
further details.
Note that older 3w-xxxx drivers do not pass the \'Enable Autosave\'
files and email messages this disk will be identified as cciss_disk_XX
with XX in the range from 00 to 15 inclusive.
-.B 3ware and cciss controllers are currently ONLY supported under Linux and FreeBSD.
-
-.B MegaRAID and Areca controllers are currently ONLY supported under Linux.
+.B 3ware, MegaRAID, Areca and cciss controllers are currently ONLY supported under Linux.
.I hpt,L/M/N
\- the device consists of one or more ATA disks connected to a HighPoint
[Please see the \fBsmartctl \-F\fP command-line option.]
.TP
-.B \-v N,OPTION
-Modifies the labeling for Attribute N, for disks which use
-non-standard Attribute definitions. This is useful in connection with
-the Attribute tracking/reporting Directives.
-
-This Directive may appear multiple times. Valid arguments to this
-Directive are:
+.B \-v ID,FORMAT[,NAME]
+[ATA only] Sets a vendor\-specific raw value print FORMAT and
+optional NAME for Attribute ID.
+This directive may be used multiple times.
+Please see \fBsmartctl -v\fP command-line option for further details.
-.I 9,minutes
-\- Raw Attribute number 9 is power-on time in minutes. Its raw value
-will be displayed in the form \'Xh+Ym\'. Here X is hours, and Y is
-minutes in the range 0-59 inclusive. Y is always printed with two
-digits, for example \'06\' or \'31\' or \'00\'.
-
-.I 9,seconds
-\- Raw Attribute number 9 is power-on time in seconds. Its raw value
-will be displayed in the form \'Xh+Ym+Zs\'. Here X is hours, Y is
-minutes in the range 0-59 inclusive, and Z is seconds in the range
-0-59 inclusive. Y and Z are always printed with two digits, for
-example \'06\' or \'31\' or \'00\'.
-
-.I 9,halfminutes
-\- Raw Attribute number 9 is power-on time, measured in units of 30
-seconds. This format is used by some Samsung disks. Its raw value
-will be displayed in the form \'Xh+Ym\'. Here X is hours, and Y is
-minutes in the range 0-59 inclusive. Y is always printed with two
-digits, for example \'06\' or \'31\' or \'00\'.
-
-.I 9,temp
-\- Raw Attribute number 9 is the disk temperature in Celsius.
-
-.I 192,emergencyretractcyclect
-\- Raw Attribute number 192 is the Emergency Retract Cycle Count.
-
-.I 193,loadunload
-\- Raw Attribute number 193 contains two values. The first is the
-number of load cycles. The second is the number of unload cycles.
-The difference between these two values is the number of times that
-the drive was unexpectedly powered off (also called an emergency
-unload). As a rule of thumb, the mechanical stress created by one
-emergency unload is equivalent to that created by one hundred normal
-unloads.
-
-.I 194,10xCelsius
-\- Raw Attribute number 194 is ten times the disk temperature in
-Celsius. This is used by some Samsung disks (example: model SV1204H
-with RK100-13 firmware).
-
-.I 194,unknown
-\- Raw Attribute number 194 is NOT the disk temperature, and its
-interpretation is unknown. This is primarily useful for the -P
-(presets) Directive.
+The following arguments affect smartd warning output:
.I 197,increasing
\- Raw Attribute number 197 (Current Pending Sector Count) is not
-reset if uncorrectable sectors are reallocated. This also sets
-\'-C 197+\' if no other \'-C\' directive is specified.
+reset if uncorrectable sectors are reallocated. This sets \'-C 197+\'
+if no other \'-C\' directive is specified.
.I 198,increasing
\- Raw Attribute number 198 (Offline Uncorrectable Sector Count) is not
-reset if uncorrectable sector are reallocated. This also sets
-\'-U 198+\' if no other \'-U\' directive is specified.
-
-.I 198,offlinescanuncsectorct
-\- Raw Attribute number 198 is the Offline Scan UNC Sector Count.
-
-.I 200,writeerrorcount
-\- Raw Attribute number 200 is the Write Error Count.
-
-.I 201,detectedtacount
-\- Raw Attribute number 201 is the Detected TA Count.
-
-.I 220,temp
-\- Raw Attribute number 220 is the disk temperature in Celsius.
-
-Note: a table of hard drive models, listing which Attribute
-corresponds to temperature, can be found at:
-\fBhttp://www.guzu.net/linux/hddtemp.db\fP
-
-.I N,raw8
-\- Print the Raw value of Attribute N as six 8-bit unsigned base-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw8\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw8\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw16
-\- Print the Raw value of Attribute N as three 16-bit unsigned base-10
-integers. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw16\' prints Raw values for ALL Attributes in this
-form. The form (for example) \'123,raw16\' only prints the Raw value for
-Attribute 123 in this form.
-
-.I N,raw48
-\- Print the Raw value of Attribute N as a 48-bit unsigned base-10
-integer. This may be useful for decoding the meaning of the Raw
-value. The form \'N,raw48\' prints Raw values for ALL Attributes in
-this form. The form (for example) \'123,raw48\' only prints the Raw
-value for Attribute 123 in this form.
+reset if uncorrectable sector are reallocated. This sets \'-U 198+\'
+if no other \'-U\' directive is specified.
.TP
.B \-P TYPE
.SH
SVN ID OF THIS PAGE:
-$Id: smartd.conf.5.in 2921 2009-09-20 19:19:32Z samm2 $
+$Id: smartd.conf.5.in 2977 2009-10-30 22:29:05Z chrfranke $
#define ARGUSED(x) ((void)(x))
-const char * smartd_cpp_cvsid = "$Id: smartd.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char * smartd_cpp_cvsid = "$Id: smartd.cpp 2984 2009-11-14 22:46:31Z chrfranke $"
CONFIG_H_CVSID EXTERN_H_CVSID;
extern const char *reportbug;
attribute_flags monitor_attr_flags; // MONITOR_* flags for each attribute
- // TODO: Encapsulate, add get/set functions
- unsigned char attributedefs[256]; // -v options, see end of extern.h for def
+ ata_vendor_attr_defs attribute_defs; // -v options
dev_config();
};
curr_pending_incr(false), offl_pending_incr(false),
curr_pending_set(false), offl_pending_set(false)
{
- memset(attributedefs, 0, sizeof(attributedefs));
}
struct ata_attribute {
unsigned char id;
unsigned char val;
+ unsigned char worst; // Byte needed for 'raw64' attribute only.
uint64_t raw;
- ata_attribute() : id(0), val(0), raw(0) { }
+ ata_attribute() : id(0), val(0), worst(0), raw(0) { }
};
ata_attribute ata_attributes[NUMBER_ATA_SMART_ATTRIBUTES];
ata_attribute & pa = ata_attributes[i];
pa.id = ta.id;
if (ta.id == 0) {
- pa.val = 0; pa.raw = 0;
+ pa.val = pa.worst = 0; pa.raw = 0;
continue;
}
pa.val = ta.current;
+ pa.worst = ta.worst;
pa.raw = ta.raw[0]
| ( ta.raw[1] << 8)
| ( ta.raw[2] << 16)
ata_smart_attribute & ta = smartval.vendor_attributes[i];
ta.id = pa.id;
if (pa.id == 0) {
- ta.current = 0; memset(ta.raw, 0, sizeof(ta.raw));
+ ta.current = ta.worst = 0;
+ memset(ta.raw, 0, sizeof(ta.raw));
continue;
}
ta.current = pa.val;
+ ta.worst = pa.worst;
ta.raw[0] = (unsigned char) pa.raw;
ta.raw[1] = (unsigned char)(pa.raw >> 8);
ta.raw[2] = (unsigned char)(pa.raw >> 16);
"((count)" // (10 (11)
"|(first-sent-time)" // (12)
"|(last-sent-time)" // (13)
- ")" // 14)
+ ")" // 10)
")" // 8)
"|(ata-smart-attribute\\.([0-9]+)\\." // (14 (15)
- "((id)" // (16)
- "|(val)" // (17)
- "|(raw)" // (18)
- ")" // 19)
+ "((id)" // (16 (17)
+ "|(val)" // (18)
+ "|(worst)" // (19)
+ "|(raw)" // (20)
+ ")" // 16)
")" // 14)
")" // 1)
- " *= *([0-9]+)[ \n]*$", // (20)
+ " *= *([0-9]+)[ \n]*$", // (21)
REG_EXTENDED
);
if (regex.empty())
throw std::logic_error("parse_dev_state_line: invalid regex");
- const int nmatch = 1+20;
+ const int nmatch = 1+21;
regmatch_t match[nmatch];
if (!regex.execute(line, nmatch, match))
return false;
state.ata_attributes[i].id = (unsigned char)val;
else if (match[++m].rm_so >= 0)
state.ata_attributes[i].val = (unsigned char)val;
+ else if (match[++m].rm_so >= 0)
+ state.ata_attributes[i].worst = (unsigned char)val;
else if (match[++m].rm_so >= 0)
state.ata_attributes[i].raw = val;
else
continue;
write_dev_state_line(f, "ata-smart-attribute", i, "id", pa.id);
write_dev_state_line(f, "ata-smart-attribute", i, "val", pa.val);
+ write_dev_state_line(f, "ata-smart-attribute", i, "worst", pa.worst);
write_dev_state_line(f, "ata-smart-attribute", i, "raw", pa.raw);
}
arguments to the option opt or NULL on failure. */
const char *GetValidArgList(char opt) {
switch (opt) {
+ case 'A':
+ case 's':
+ return "<PATH_PREFIX>";
case 'c':
return "<FILE_NAME>, -";
- case 's':
- return "valid_regular_expression";
case 'l':
return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
case 'q':
return "nodev, errors, nodevstartup, never, onecheck, showtests";
case 'r':
return "ioctl[,N], ataioctl[,N], scsiioctl[,N]";
+ case 'B':
case 'p':
return "<FILE_NAME>";
case 'i':
/* prints help information for command syntax */
void Usage (void){
PrintOut(LOG_INFO,"Usage: smartd [options]\n\n");
+ PrintOut(LOG_INFO," -A PREFIX, --attributelog=PREFIX\n");
+ PrintOut(LOG_INFO," Log ATA attribute information to {PREFIX}MODEL-SERIAL.ata.csv\n");
+#ifdef SMARTMONTOOLS_ATTRIBUTELOG
+ PrintOut(LOG_INFO," [default is "SMARTMONTOOLS_ATTRIBUTELOG"MODEL-SERIAL.ata.csv]\n");
+#endif
+ PrintOut(LOG_INFO,"\n");
+ PrintOut(LOG_INFO," -B [+]FILE, --drivedb=[+]FILE\n");
+ PrintOut(LOG_INFO," Read and replace [add] drive database from FILE\n");
+#ifdef SMARTMONTOOLS_DRIVEDBDIR
+ PrintOut(LOG_INFO," [default is "SMARTMONTOOLS_DRIVEDBDIR"/drivedb.h]\n");
+#endif
+ PrintOut(LOG_INFO,"\n");
PrintOut(LOG_INFO," -c NAME|-, --configfile=NAME|-\n");
PrintOut(LOG_INFO," Read configuration file NAME or stdin [default is %s]\n\n", configfile);
PrintOut(LOG_INFO," -d, --debug\n");
PrintOut(LOG_INFO," Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
#ifdef SMARTMONTOOLS_SAVESTATES
PrintOut(LOG_INFO," [default is "SMARTMONTOOLS_SAVESTATES"MODEL-SERIAL.TYPE.state]\n");
-#endif
- PrintOut(LOG_INFO,"\n");
- PrintOut(LOG_INFO," -B [+]FILE, --drivedb=[+]FILE\n");
- PrintOut(LOG_INFO," Read and replace [add] drive database from FILE\n");
-#ifdef SMARTMONTOOLS_DRIVEDBDIR
- PrintOut(LOG_INFO," [default is "SMARTMONTOOLS_DRIVEDBDIR"/drivedb.h]\n");
#endif
PrintOut(LOG_INFO,"\n");
#ifdef _WIN32
PrintOut(LOG_INFO, "Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
else {
// do whatever applypresets decides to do.
- if (!apply_presets(&drive, cfg.attributedefs, cfg.fix_firmwarebug, fix_swapped_id))
+ if (!apply_presets(&drive, cfg.attribute_defs, cfg.fix_firmwarebug, fix_swapped_id))
PrintOut(LOG_INFO, "Device: %s, not found in smartd database.\n", name);
else
PrintOut(LOG_INFO, "Device: %s, found in smartd database.\n", name);
// Set default '-C 197[+]' if no '-C ID' is specified.
if (!cfg.curr_pending_set)
- cfg.curr_pending_id = get_unc_attr_id(false, cfg.attributedefs, cfg.curr_pending_incr);
+ cfg.curr_pending_id = get_unc_attr_id(false, cfg.attribute_defs, cfg.curr_pending_incr);
// Set default '-U 198[+]' if no '-U ID' is specified.
if (!cfg.offl_pending_set)
- cfg.offl_pending_id = get_unc_attr_id(true, cfg.attributedefs, cfg.offl_pending_incr);
+ cfg.offl_pending_id = get_unc_attr_id(true, cfg.attribute_defs, cfg.offl_pending_incr);
// If requested, show which presets would be used for this drive
if (cfg.showpresets) {
// see if the necessary Attribute is there to monitor offline or
// current pending sectors or temperature
- if (cfg.curr_pending_id && ATAReturnAttributeRawValue(cfg.curr_pending_id, &state.smartval) < 0) {
+ if (cfg.curr_pending_id && ata_find_attr_index(cfg.curr_pending_id, state.smartval) < 0) {
PrintOut(LOG_INFO,"Device: %s, can't monitor Current Pending Sector count - no Attribute %d\n",
name, cfg.curr_pending_id);
cfg.curr_pending_id = 0;
}
- if (cfg.offl_pending_id && ATAReturnAttributeRawValue(cfg.offl_pending_id, &state.smartval) < 0) {
+ if (cfg.offl_pending_id && ata_find_attr_index(cfg.offl_pending_id, state.smartval) < 0) {
PrintOut(LOG_INFO,"Device: %s, can't monitor Offline Uncorrectable Sector count - no Attribute %d\n",
name, cfg.offl_pending_id);
cfg.offl_pending_id = 0;
}
if ( (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit)
- && !ATAReturnTemperatureValue(&state.smartval, cfg.attributedefs)) {
+ && !ata_return_temperature_value(&state.smartval, cfg.attribute_defs)) {
PrintOut(LOG_CRIT, "Device: %s, can't monitor Temperature, ignoring -W Directive\n", name);
cfg.tempdiff = cfg.tempinfo = cfg.tempcrit = 0;
}
return 0;
}
-
-struct changedattribute_t {
- unsigned char newval;
- unsigned char oldval;
- unsigned char id;
- unsigned char prefail;
- unsigned char sameraw;
-};
-
-// We compare old and new values of the n'th attribute. Note that n
-// is NOT the attribute ID number.. If (Normalized & Raw) equal,
-// then return 0, else nonzero.
-static int ATACompareValues(changedattribute_t *delta,
- struct ata_smart_values *newv,
- struct ata_smart_values *oldv,
- struct ata_smart_thresholds_pvt *thresholds,
- int n, const char * name)
-{
- struct ata_smart_attribute *now,*was;
- struct ata_smart_threshold_entry *thre;
- unsigned char oldval,newval;
- int sameraw;
-
- // check that attribute number in range, and no null pointers
- if (n<0 || n>=NUMBER_ATA_SMART_ATTRIBUTES || !newv || !oldv || !thresholds)
- return 0;
-
- // pointers to disk's values and vendor's thresholds
- now=newv->vendor_attributes+n;
- was=oldv->vendor_attributes+n;
- thre=thresholds->thres_entries+n;
-
- // consider only valid attributes
- if (!now->id || !was->id || !thre->id)
- return 0;
-
-
- // issue warning if they don't have the same ID in all structures:
- if ( (now->id != was->id) || (now->id != thre->id) ){
- PrintOut(LOG_INFO,"Device: %s, same Attribute has different ID numbers: %d = %d = %d\n",
- name, (int)now->id, (int)was->id, (int)thre->id);
- return 0;
- }
-
- // new and old values of Normalized Attributes
- newval=now->current;
- oldval=was->current;
-
- // See if the RAW values are unchanged (ie, the same)
- if (memcmp(now->raw, was->raw, 6))
- sameraw=0;
- else
- sameraw=1;
-
- // if any values out of the allowed range, or if the values haven't
- // changed, return 0
- if (!newval || !oldval || newval>0xfe || oldval>0xfe || (oldval==newval && sameraw))
- return 0;
-
- // values have changed. Construct output and return
- delta->newval=newval;
- delta->oldval=oldval;
- delta->id=now->id;
- delta->prefail=ATTRIBUTE_FLAGS_PREFAILURE(now->flags);
- delta->sameraw=sameraw;
-
- return 1;
-}
-
// If the self-test log has got more self-test errors (or more recent
// self-test errors) recorded, then notify user.
static void CheckSelfTestLogs(const dev_config & cfg, dev_state & state, int newi)
const ata_smart_values & smartval,
int mailtype, const char * msg)
{
+ // Find attribute index
+ int i = ata_find_attr_index(id, smartval);
+ if (!(i >= 0 && ata_find_attr_index(id, state.smartval) == i))
+ return;
+
// No report if no sectors pending.
- int64_t rawval = ATAReturnAttributeRawValue(id, &smartval);
- if (rawval <= 0)
+ uint64_t rawval = ata_get_attr_raw_value(smartval.vendor_attributes[i], cfg.attribute_defs);
+ if (rawval == 0)
return;
// If attribute is not reset, report only sector count increases.
- int64_t prev_rawval = ATAReturnAttributeRawValue(id, &state.smartval);
+ uint64_t prev_rawval = ata_get_attr_raw_value(state.smartval.vendor_attributes[i], cfg.attribute_defs);
if (!(!increase_only || prev_rawval < rawval))
return;
}
}
+// Check normalized and raw attribute values.
+static void check_attribute(const dev_config & cfg, dev_state & state,
+ const ata_smart_attribute & attr,
+ const ata_smart_attribute & prev,
+ const ata_smart_threshold_entry & thre)
+{
+ // Check attribute and threshold
+ ata_attr_state attrstate = ata_get_attr_state(attr, thre, cfg.attribute_defs);
+ if (attrstate == ATTRSTATE_NON_EXISTING)
+ return;
+
+ // If requested, check for usage attributes that have failed.
+ if ( cfg.usagefailed && attrstate == ATTRSTATE_FAILED_NOW
+ && !cfg.monitor_attr_flags.is_set(attr.id, MONITOR_IGN_FAILUSE)) {
+ std::string attrname = ata_get_smart_attr_name(attr.id, cfg.attribute_defs);
+ PrintOut(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.name.c_str(), attr.id, attrname.c_str());
+ MailWarning(cfg, state, 2, "Device: %s, Failed SMART usage Attribute: %d %s.", cfg.name.c_str(), attr.id, attrname.c_str());
+ state.must_write = true;
+ }
+
+ // Return if we're not tracking this type of attribute
+ bool prefail = !!ATTRIBUTE_FLAGS_PREFAILURE(attr.flags);
+ if (!( ( prefail && cfg.prefail)
+ || (!prefail && cfg.usage )))
+ return;
+
+ // Return if '-I ID' was specified
+ if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_IGNORE))
+ return;
+
+ // Issue warning if they don't have the same ID in all structures.
+ if (attr.id != prev.id || attrstate == ATTRSTATE_BAD_THRESHOLD) {
+ PrintOut(LOG_INFO,"Device: %s, same Attribute has different ID numbers: %d = %d = %d\n",
+ cfg.name.c_str(), attr.id, prev.id, thre.id);
+ return;
+ }
+
+ // Compare normalized values if valid.
+ bool valchanged = false;
+ if (attrstate > ATTRSTATE_NO_NORMVAL) {
+ if (attr.current != prev.current)
+ valchanged = true;
+ }
+
+ // Compare raw values if requested.
+ bool rawchanged = false;
+ if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_RAW)) {
+ if ( ata_get_attr_raw_value(attr, cfg.attribute_defs)
+ != ata_get_attr_raw_value(prev, cfg.attribute_defs))
+ rawchanged = true;
+ }
+
+ // Return if no change
+ if (!(valchanged || rawchanged))
+ return;
+
+ // Format value strings
+ std::string currstr, prevstr;
+ if (attrstate == ATTRSTATE_NO_NORMVAL) {
+ // Print raw values only
+ currstr = strprintf("%s (Raw)",
+ ata_format_attr_raw_value(attr, cfg.attribute_defs).c_str());
+ prevstr = strprintf("%s (Raw)",
+ ata_format_attr_raw_value(prev, cfg.attribute_defs).c_str());
+ }
+ else if (cfg.monitor_attr_flags.is_set(attr.id, MONITOR_RAW_PRINT)) {
+ // Print normalized and raw values
+ currstr = strprintf("%d [Raw %s]", attr.current,
+ ata_format_attr_raw_value(attr, cfg.attribute_defs).c_str());
+ prevstr = strprintf("%d [Raw %s]", prev.current,
+ ata_format_attr_raw_value(prev, cfg.attribute_defs).c_str());
+ }
+ else {
+ // Print normalized values only
+ currstr = strprintf("%d", attr.current);
+ prevstr = strprintf("%d", prev.current);
+ }
+
+ // Format message
+ std::string msg = strprintf("Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
+ cfg.name.c_str(), (prefail ? "Prefailure" : "Usage"), attr.id,
+ ata_get_smart_attr_name(attr.id, cfg.attribute_defs).c_str(),
+ prevstr.c_str(), currstr.c_str());
+
+ // Report this change as critical ?
+ if ( (valchanged && cfg.monitor_attr_flags.is_set(attr.id, MONITOR_AS_CRIT))
+ || (rawchanged && cfg.monitor_attr_flags.is_set(attr.id, MONITOR_RAW_AS_CRIT))) {
+ PrintOut(LOG_CRIT, "%s\n", msg.c_str());
+ MailWarning(cfg, state, 2, "%s", msg.c_str());
+ }
+ else {
+ PrintOut(LOG_INFO, "%s\n", msg.c_str());
+ }
+ state.must_write = true;
+}
+
+
static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device * atadev, bool allow_selftests)
{
const char * name = cfg.name.c_str();
if ( cfg.usagefailed || cfg.prefail || cfg.usage
|| cfg.curr_pending_id || cfg.offl_pending_id
|| cfg.tempdiff || cfg.tempinfo || cfg.tempcrit || cfg.selftest) {
- struct ata_smart_values curval;
- struct ata_smart_thresholds_pvt * thresh = &state.smartthres;
- // Read current attribute values. *drive contains old values and thresholds
+ // Read current attribute values.
+ ata_smart_values curval;
if (ataReadSmartValues(atadev, &curval)){
PrintOut(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name);
MailWarning(cfg, state, 6, "Device: %s, failed to read SMART Attribute Data", name);
// check temperature limits
if (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit)
- CheckTemperature(cfg, state, ATAReturnTemperatureValue(&curval, cfg.attributedefs), 0);
+ CheckTemperature(cfg, state, ata_return_temperature_value(&curval, cfg.attribute_defs), 0);
if (cfg.usagefailed || cfg.prefail || cfg.usage) {
- // look for failed usage attributes, or track usage or prefail attributes
+ // look for failed usage attributes, or track usage or prefail attributes
for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
+ check_attribute(cfg, state,
+ curval.vendor_attributes[i],
+ state.smartval.vendor_attributes[i],
+ state.smartthres.thres_entries[i]);
+ }
- // This block looks for usage attributes that have failed.
- // Prefail attributes that have failed are returned with a
- // positive sign. No failure returns 0. Usage attributes<0.
- int att;
- if (cfg.usagefailed && ((att=ataCheckAttribute(&curval, thresh, i))<0)){
-
- // are we ignoring failures of this attribute?
- att *= -1;
- if (!cfg.monitor_attr_flags.is_set(att, MONITOR_IGN_FAILUSE)) {
- char attname[64], *loc=attname;
-
- // get attribute name & skip white space
- ataPrintSmartAttribName(loc, att, cfg.attributedefs);
- while (*loc && *loc==' ') loc++;
-
- // warning message
- PrintOut(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %s.\n", name, loc);
- MailWarning(cfg, state, 2, "Device: %s, Failed SMART usage Attribute: %s.", name, loc);
- state.must_write = true;
- }
- }
-
- // This block tracks usage or prefailure attributes to see if
- // they are changing. It also looks for changes in RAW values
- // if this has been requested by user.
- changedattribute_t delta;
- if ((cfg.usage || cfg.prefail) && ATACompareValues(&delta, &curval, &state.smartval, thresh, i, name)){
-
- // Continue if we're not tracking this type of attribute
- if (!( ( delta.prefail && cfg.prefail)
- || (!delta.prefail && cfg.usage )))
- continue;
-
- // Continue if '-I ID' was specified
- unsigned char id = delta.id;
- if (cfg.monitor_attr_flags.is_set(id, MONITOR_IGNORE))
- continue;
-
- // if the only change is the raw value, and we're not
- // tracking raw value, then continue loop over attributes
- if ( !delta.sameraw && delta.newval == delta.oldval
- && !cfg.monitor_attr_flags.is_set(id, MONITOR_RAW))
- continue;
-
- // get attribute name, skip spaces
- char attname[64], *loc = attname;
- ataPrintSmartAttribName(loc, id, cfg.attributedefs);
- while (*loc && *loc==' ')
- loc++;
-
- // has the user asked for us to print raw values?
- char newrawstring[64], oldrawstring[64];
- if (cfg.monitor_attr_flags.is_set(id, MONITOR_RAW_PRINT)) {
- // get raw values (as a string) and add to printout
- char rawstring[64];
- ataPrintSmartAttribRawValue(rawstring, curval.vendor_attributes+i, cfg.attributedefs);
- sprintf(newrawstring, " [Raw %s]", rawstring);
- ataPrintSmartAttribRawValue(rawstring, state.smartval.vendor_attributes+i, cfg.attributedefs);
- sprintf(oldrawstring, " [Raw %s]", rawstring);
- }
- else
- newrawstring[0]=oldrawstring[0]='\0';
-
- // Format message
- std::string msg = strprintf("Device: %s, SMART %s Attribute: %s changed from %d%s to %d%s",
- name, (delta.prefail ? "Prefailure" : "Usage"), loc,
- delta.oldval, oldrawstring, delta.newval, newrawstring);
-
- // Report this change as critical ?
- if ( (delta.newval != delta.oldval && cfg.monitor_attr_flags.is_set(id, MONITOR_AS_CRIT))
- || (!delta.sameraw && cfg.monitor_attr_flags.is_set(id, MONITOR_RAW_AS_CRIT))) {
- PrintOut(LOG_CRIT, "%s\n", msg.c_str());
- MailWarning(cfg, state, 2, "%s", msg.c_str());
- }
- else {
- PrintOut(LOG_INFO, "%s\n", msg.c_str());
- }
- state.must_write = true;
- } // endof block tracking usage or prefailure
- } // end of loop over attributes
-
if (cfg.selftest) {
- // Log changes of self-test executions status
+ // Log changes of self-test execution status
if ( curval.self_test_exec_status != state.smartval.self_test_exec_status
|| (!allow_selftests && curval.self_test_exec_status != 0x00) )
log_self_test_exec_status(name, curval.self_test_exec_status);
// non-default vendor-specific attribute meaning
if (!(arg=strtok(NULL,delim))) {
missingarg = 1;
- } else if (parse_attribute_def(arg, cfg.attributedefs)) {
+ } else if (!parse_attribute_def(arg, cfg.attribute_defs, PRIOR_USER)) {
badarg = 1;
}
break;
dev_config cfg = conf_entries[i];
// get device of appropriate type
- // TODO: exception handling
- smart_device * dev = 0;
+ smart_device_auto_ptr dev;
bool scanning = false;
// Device may already be detected during devicescan
smart_device::device_info oldinfo = dev->get_info();
// Open with autodetect support, may return 'better' device
- dev = dev->autodetect_open();
+ dev.replace( dev->autodetect_open() );
// Report if type has changed
- if (/* ent->dev_type && */ oldinfo.dev_type != dev->get_dev_type())
+ if (oldinfo.dev_type != dev->get_dev_type())
PrintOut(LOG_INFO,"Device: %s, type changed from '%s' to '%s'\n",
cfg.name.c_str(), oldinfo.dev_type.c_str(), dev->get_dev_type());
// If no debug and scanning - don't print errors
if (debugmode || !scanning)
PrintOut(LOG_INFO, "Device: %s, open() failed: %s\n", dev->get_info_name(), dev->get_errmsg());
- delete dev;
continue;
}
if (dev->is_ata()){
if (ATADeviceScan(cfg, state, dev->to_ata())) {
CanNotRegister(cfg.name.c_str(), "ATA", cfg.lineno, scanning);
- delete dev; dev = 0;
- }
- else {
- // move onto the list of ata devices
- configs.push_back(cfg);
- states.push_back(state);
- devices.push_back(dev);
+ dev.reset();
}
}
-
// or register SCSI devices
else if (dev->is_scsi()){
if (SCSIDeviceScan(cfg, state, dev->to_scsi())) {
CanNotRegister(cfg.name.c_str(), "SCSI", cfg.lineno, scanning);
- delete dev; dev = 0;
- }
- else {
- // move onto the list of scsi devices
- configs.push_back(cfg);
- states.push_back(state);
- devices.push_back(dev);
+ dev.reset();
}
}
-
+ else {
+ PrintOut(LOG_INFO, "Device: %s, neither ATA nor SCSI device\n", cfg.name.c_str());
+ dev.reset();
+ }
+
+ if (dev) {
+ // move onto the list of devices
+ configs.push_back(cfg);
+ states.push_back(state);
+ devices.push_back(dev);
+ }
// if device is explictly listed and we can't register it, then
// exit unless the user has specified that the device is removable
- if (!dev && !scanning) {
+ else if (!scanning) {
if (cfg.removable || quit==2)
PrintOut(LOG_INFO, "Device %s not available\n", cfg.name.c_str());
else {
#include "atacmds.h"
#include "dev_interface.h"
-const char * utility_cpp_cvsid = "$Id: utility.cpp 2915 2009-09-18 21:17:37Z chrfranke $"
+const char * utility_cpp_cvsid = "$Id: utility.cpp 2991 2009-12-03 19:53:21Z chrfranke $"
UTILITY_H_CVSID INT64_H_CVSID;
const char * packet_types[] = {
"software, and you are welcome to redistribute it under\n"
"the terms of the GNU General Public License Version 2.\n"
"See http://www.gnu.org for further details.\n"
- "\n"
+ "\n",
+ prog_name
+ );
+ info += strprintf(
"smartmontools release "PACKAGE_VERSION
" dated "SMARTMONTOOLS_RELEASE_DATE" at "SMARTMONTOOLS_RELEASE_TIME"\n"
"smartmontools SVN rev "SMARTMONTOOLS_SVN_REV
" dated "SMARTMONTOOLS_SVN_DATE" at "SMARTMONTOOLS_SVN_TIME"\n"
"smartmontools build host: "SMARTMONTOOLS_BUILD_HOST"\n"
"smartmontools build configured: "SMARTMONTOOLS_CONFIGURE_DATE "\n"
- "%s compile dated "__DATE__" at "__TIME__"\n",
- prog_name, prog_name
- );
- info += strprintf(
- "smartmontools configure arguments: %s\n",
- (sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ?
- SMARTMONTOOLS_CONFIGURE_ARGS : "[no arguments given]")
+ "%s compile dated "__DATE__" at "__TIME__"\n"
+ "smartmontools configure arguments: ",
+ prog_name
);
+ info += (sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ?
+ SMARTMONTOOLS_CONFIGURE_ARGS : "[no arguments given]");
+ info += '\n';
return info;
}